[1/2] libio: Fix gconv module reference counter overflow in swscanf
Checks
| Context |
Check |
Description |
| redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
Commit Message
The swscanf family of functions creates a wide-oriented FILE stream
on the stack. Initialization of this stream invokes `_IO_fwide`, which
clones the global locale's gconv transformation steps via
`__wcsmbs_clone_conv`. This increments the reference counter (`__counter`)
of the gconv module.
Because the FILE stream is stack-allocated, `fclose` cannot be called,
and so `__gconv_release_step` is never invoked. The counter leaks,
eventually hitting the 32-bit integer overflow limit and aborting the
process.
To resolve this, we introduce `_IO_wstrfile_fclose_stack`, a dedicated
cleanup function for stack-allocated FILE streams. This function invokes
`_IO_FINISH` and correctly releases the gconv steps via
`__gconv_release_step` without attempting to `free` the FILE pointer.
This cleanup function is then hooked into all variants of swscanf right
before they return.
---
libio/iofwide.c | 15 +++++++++++++++
libio/iovswscanf.c | 4 +++-
libio/libioP.h | 1 +
libio/swscanf.c | 2 +-
.../ldbl-128ibm-compat/ieee128-isoc23_swscanf.c | 2 +-
.../ldbl-128ibm-compat/ieee128-isoc23_vswscanf.c | 4 +++-
.../ldbl-128ibm-compat/ieee128-isoc99_swscanf.c | 2 +-
.../ldbl-128ibm-compat/ieee128-isoc99_vswscanf.c | 4 +++-
.../ieee754/ldbl-128ibm-compat/ieee128-swscanf.c | 2 +-
.../ieee754/ldbl-128ibm-compat/ieee128-vswscanf.c | 4 +++-
sysdeps/ieee754/ldbl-opt/nldbl-compat.c | 12 +++++++++---
wcsmbs/isoc23_swscanf.c | 2 +-
wcsmbs/isoc23_vswscanf.c | 4 +++-
wcsmbs/isoc99_swscanf.c | 2 +-
wcsmbs/isoc99_vswscanf.c | 4 +++-
15 files changed, 49 insertions(+), 15 deletions(-)
Comments
On 29/04/26 11:59, Frédéric Bérat wrote:
> The swscanf family of functions creates a wide-oriented FILE stream
> on the stack. Initialization of this stream invokes `_IO_fwide`, which
> clones the global locale's gconv transformation steps via
> `__wcsmbs_clone_conv`. This increments the reference counter (`__counter`)
> of the gconv module.
>
> Because the FILE stream is stack-allocated, `fclose` cannot be called,
> and so `__gconv_release_step` is never invoked. The counter leaks,
> eventually hitting the 32-bit integer overflow limit and aborting the
> process.
>
> To resolve this, we introduce `_IO_wstrfile_fclose_stack`, a dedicated
> cleanup function for stack-allocated FILE streams. This function invokes
> `_IO_FINISH` and correctly releases the gconv steps via
> `__gconv_release_step` without attempting to `free` the FILE pointer.
> This cleanup function is then hooked into all variants of swscanf right
> before they return.
LGTM, thanks.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> ---
> libio/iofwide.c | 15 +++++++++++++++
> libio/iovswscanf.c | 4 +++-
> libio/libioP.h | 1 +
> libio/swscanf.c | 2 +-
> .../ldbl-128ibm-compat/ieee128-isoc23_swscanf.c | 2 +-
> .../ldbl-128ibm-compat/ieee128-isoc23_vswscanf.c | 4 +++-
> .../ldbl-128ibm-compat/ieee128-isoc99_swscanf.c | 2 +-
> .../ldbl-128ibm-compat/ieee128-isoc99_vswscanf.c | 4 +++-
> .../ieee754/ldbl-128ibm-compat/ieee128-swscanf.c | 2 +-
> .../ieee754/ldbl-128ibm-compat/ieee128-vswscanf.c | 4 +++-
> sysdeps/ieee754/ldbl-opt/nldbl-compat.c | 12 +++++++++---
> wcsmbs/isoc23_swscanf.c | 2 +-
> wcsmbs/isoc23_vswscanf.c | 4 +++-
> wcsmbs/isoc99_swscanf.c | 2 +-
> wcsmbs/isoc99_vswscanf.c | 4 +++-
> 15 files changed, 49 insertions(+), 15 deletions(-)
>
> diff --git a/libio/iofwide.c b/libio/iofwide.c
> index 8e71fdd21b..d016aa33ea 100644
> --- a/libio/iofwide.c
> +++ b/libio/iofwide.c
> @@ -251,3 +251,18 @@ __libio_codecvt_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
>
> return result;
> }
> +
> +void
> +_IO_wstrfile_fclose_stack (FILE *fp)
> +{
> + _IO_FINISH (fp);
> + if (fp->_mode > 0)
> + {
> + struct _IO_codecvt *cc = fp->_codecvt;
> +
> + __libc_lock_lock (__gconv_lock);
> + __gconv_release_step (cc->__cd_in.step);
> + __gconv_release_step (cc->__cd_out.step);
> + __libc_lock_unlock (__gconv_lock);
> + }
> +}
> diff --git a/libio/iovswscanf.c b/libio/iovswscanf.c
> index a97f4eed1e..986d94178d 100644
> --- a/libio/iovswscanf.c
> +++ b/libio/iovswscanf.c
> @@ -38,6 +38,8 @@ __vswscanf (const wchar_t *string, const wchar_t *format, va_list args)
> _IO_strfile sf;
> struct _IO_wide_data wd;
> FILE *f = _IO_strfile_readw (&sf, &wd, string);
> - return __vfwscanf_internal (f, format, args, 0);
> + int done = __vfwscanf_internal (f, format, args, 0);
> + _IO_wstrfile_fclose_stack (f);
> + return done;
> }
> ldbl_weak_alias (__vswscanf, vswscanf)
> diff --git a/libio/libioP.h b/libio/libioP.h
> index 1485d22619..1d4217e82a 100644
> --- a/libio/libioP.h
> +++ b/libio/libioP.h
> @@ -645,6 +645,7 @@ extern FILE* _IO_new_file_fopen (FILE *, const char *, const char *,
> int);
> extern void _IO_no_init (FILE *, int, int, struct _IO_wide_data *,
> const struct _IO_jump_t *) __THROW;
> +extern void _IO_wstrfile_fclose_stack (FILE *) attribute_hidden;
> extern void _IO_new_file_init_internal (struct _IO_FILE_plus *)
> __THROW attribute_hidden;
> extern FILE* _IO_new_file_setbuf (FILE *, char *, ssize_t);
> diff --git a/libio/swscanf.c b/libio/swscanf.c
> index d36ef48258..583253a7dc 100644
> --- a/libio/swscanf.c
> +++ b/libio/swscanf.c
> @@ -37,7 +37,7 @@ __swscanf (const wchar_t *s, const wchar_t *format, ...)
> va_start (arg, format);
> done = __vfwscanf_internal (f, format, arg, 0);
> va_end (arg);
> -
> + _IO_wstrfile_fclose_stack (f);
> return done;
> }
> ldbl_strong_alias (__swscanf, swscanf)
> diff --git a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc23_swscanf.c b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc23_swscanf.c
> index 6b3915357f..2e95cdf010 100644
> --- a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc23_swscanf.c
> +++ b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc23_swscanf.c
> @@ -35,7 +35,7 @@ ___ieee128_isoc23_swscanf (const wchar_t *string, const wchar_t *format, ...)
> va_start (ap, format);
> done = __vfwscanf_internal (fp, format, ap, mode_flags);
> va_end (ap);
> -
> + _IO_wstrfile_fclose_stack (fp);
> return done;
> }
> strong_alias (___ieee128_isoc23_swscanf, __isoc23_swscanfieee128)
> diff --git a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc23_vswscanf.c b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc23_vswscanf.c
> index 295321147c..857903b2a6 100644
> --- a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc23_vswscanf.c
> +++ b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc23_vswscanf.c
> @@ -28,6 +28,8 @@ ___ieee128_isoc23_vswscanf (wchar_t *string, const wchar_t *format, va_list ap)
> FILE *fp = _IO_strfile_readw (&sf, &wd, string);
> int mode_flags =
> SCANF_ISOC99_A | SCANF_ISOC23_BIN_CST | SCANF_LDBL_USES_FLOAT128;
> - return __vfwscanf_internal (fp, format, ap, mode_flags);
> + int done = __vfwscanf_internal (fp, format, ap, mode_flags);
> + _IO_wstrfile_fclose_stack (fp);
> + return done;
> }
> strong_alias (___ieee128_isoc23_vswscanf, __isoc23_vswscanfieee128)
> diff --git a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc99_swscanf.c b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc99_swscanf.c
> index 19b71940dd..2280bae1d0 100644
> --- a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc99_swscanf.c
> +++ b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc99_swscanf.c
> @@ -34,7 +34,7 @@ ___ieee128_isoc99_swscanf (const wchar_t *string, const wchar_t *format, ...)
> va_start (ap, format);
> done = __vfwscanf_internal (fp, format, ap, mode_flags);
> va_end (ap);
> -
> + _IO_wstrfile_fclose_stack (fp);
> return done;
> }
> strong_alias (___ieee128_isoc99_swscanf, __isoc99_swscanfieee128)
> diff --git a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc99_vswscanf.c b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc99_vswscanf.c
> index a1b51cb5b6..21cf25610a 100644
> --- a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc99_vswscanf.c
> +++ b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-isoc99_vswscanf.c
> @@ -27,6 +27,8 @@ ___ieee128_isoc99_vswscanf (wchar_t *string, const wchar_t *format, va_list ap)
> struct _IO_wide_data wd;
> FILE *fp = _IO_strfile_readw (&sf, &wd, string);
> int mode_flags = SCANF_ISOC99_A | SCANF_LDBL_USES_FLOAT128;
> - return __vfwscanf_internal (fp, format, ap, mode_flags);
> + int done = __vfwscanf_internal (fp, format, ap, mode_flags);
> + _IO_wstrfile_fclose_stack (fp);
> + return done;
> }
> strong_alias (___ieee128_isoc99_vswscanf, __isoc99_vswscanfieee128)
> diff --git a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-swscanf.c b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-swscanf.c
> index 7124ecb67c..fdfdf2b65c 100644
> --- a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-swscanf.c
> +++ b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-swscanf.c
> @@ -34,7 +34,7 @@ ___ieee128_swscanf (const wchar_t *string, const wchar_t *format, ...)
> done = __vfwscanf_internal (fp, format, ap,
> SCANF_LDBL_USES_FLOAT128);
> va_end (ap);
> -
> + _IO_wstrfile_fclose_stack (fp);
> return done;
> }
> strong_alias (___ieee128_swscanf, __swscanfieee128)
> diff --git a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-vswscanf.c b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-vswscanf.c
> index 8294582c48..b860a8e87d 100644
> --- a/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-vswscanf.c
> +++ b/sysdeps/ieee754/ldbl-128ibm-compat/ieee128-vswscanf.c
> @@ -27,6 +27,8 @@ ___ieee128_vswscanf (const wchar_t *string, const wchar_t *format,
> _IO_strfile sf;
> struct _IO_wide_data wd;
> FILE *fp = _IO_strfile_readw (&sf, &wd, string);
> - return __vfwscanf_internal (fp, format, ap, SCANF_LDBL_USES_FLOAT128);
> + int done = __vfwscanf_internal (fp, format, ap, SCANF_LDBL_USES_FLOAT128);
> + _IO_wstrfile_fclose_stack (fp);
> + return done;
> }
> strong_alias (___ieee128_vswscanf, __vswscanfieee128)
> diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
> index dcd5649200..e239cd5bc5 100644
> --- a/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
> +++ b/sysdeps/ieee754/ldbl-opt/nldbl-compat.c
> @@ -391,7 +391,9 @@ __nldbl_vswscanf (const wchar_t *s, const wchar_t *fmt, va_list ap)
> struct _IO_wide_data wd;
> FILE *f = _IO_strfile_readw (&sf, &wd, s);
>
> - return __vfwscanf_internal (f, fmt, ap, SCANF_LDBL_IS_DBL);
> + int ret = __vfwscanf_internal (f, fmt, ap, SCANF_LDBL_IS_DBL);
> + _IO_wstrfile_fclose_stack (f);
> + return ret;
> }
> libc_hidden_def (__nldbl_vswscanf)
>
> @@ -955,7 +957,9 @@ __nldbl___isoc99_vswscanf (const wchar_t *s, const wchar_t *fmt, va_list ap)
> struct _IO_wide_data wd;
> FILE *f = _IO_strfile_readw (&sf, &wd, s);
>
> - return __vfwscanf_internal (f, fmt, ap, SCANF_LDBL_IS_DBL | SCANF_ISOC99_A);
> + int ret = __vfwscanf_internal (f, fmt, ap, SCANF_LDBL_IS_DBL | SCANF_ISOC99_A);
> + _IO_wstrfile_fclose_stack (f);
> + return ret;
> }
> libc_hidden_def (__nldbl___isoc99_vswscanf)
>
> @@ -1115,9 +1119,11 @@ __nldbl___isoc23_vswscanf (const wchar_t *s, const wchar_t *fmt, va_list ap)
> struct _IO_wide_data wd;
> FILE *f = _IO_strfile_readw (&sf, &wd, s);
>
> - return __vfwscanf_internal (f, fmt, ap,
> + int ret = __vfwscanf_internal (f, fmt, ap,
> SCANF_LDBL_IS_DBL | SCANF_ISOC99_A
> | SCANF_ISOC23_BIN_CST);
> + _IO_wstrfile_fclose_stack (f);
> + return ret;
> }
> libc_hidden_def (__nldbl___isoc23_vswscanf)
>
> diff --git a/wcsmbs/isoc23_swscanf.c b/wcsmbs/isoc23_swscanf.c
> index 66b5290b3c..568ab138b4 100644
> --- a/wcsmbs/isoc23_swscanf.c
> +++ b/wcsmbs/isoc23_swscanf.c
> @@ -33,6 +33,6 @@ __isoc23_swscanf (const wchar_t *s, const wchar_t *format, ...)
> done = __vfwscanf_internal (f, format, arg,
> SCANF_ISOC99_A | SCANF_ISOC23_BIN_CST);
> va_end (arg);
> -
> + _IO_wstrfile_fclose_stack (f);
> return done;
> }
> diff --git a/wcsmbs/isoc23_vswscanf.c b/wcsmbs/isoc23_vswscanf.c
> index d84efb9350..89b7241a7a 100644
> --- a/wcsmbs/isoc23_vswscanf.c
> +++ b/wcsmbs/isoc23_vswscanf.c
> @@ -24,7 +24,9 @@ __isoc23_vswscanf (const wchar_t *string, const wchar_t *format, va_list args)
> _IO_strfile sf;
> struct _IO_wide_data wd;
> FILE *f = _IO_strfile_readw (&sf, &wd, string);
> - return __vfwscanf_internal (f, format, args,
> + int done = __vfwscanf_internal (f, format, args,
> SCANF_ISOC99_A | SCANF_ISOC23_BIN_CST);
> + _IO_wstrfile_fclose_stack (f);
> + return done;
> }
> libc_hidden_def (__isoc23_vswscanf)
> diff --git a/wcsmbs/isoc99_swscanf.c b/wcsmbs/isoc99_swscanf.c
> index 493fe01520..c94f19ca41 100644
> --- a/wcsmbs/isoc99_swscanf.c
> +++ b/wcsmbs/isoc99_swscanf.c
> @@ -32,6 +32,6 @@ __isoc99_swscanf (const wchar_t *s, const wchar_t *format, ...)
> va_start (arg, format);
> done = __vfwscanf_internal (f, format, arg, SCANF_ISOC99_A);
> va_end (arg);
> -
> + _IO_wstrfile_fclose_stack (f);
> return done;
> }
> diff --git a/wcsmbs/isoc99_vswscanf.c b/wcsmbs/isoc99_vswscanf.c
> index 326f7bfd24..6bc134a807 100644
> --- a/wcsmbs/isoc99_vswscanf.c
> +++ b/wcsmbs/isoc99_vswscanf.c
> @@ -33,6 +33,8 @@ __isoc99_vswscanf (const wchar_t *string, const wchar_t *format, va_list args)
> _IO_strfile sf;
> struct _IO_wide_data wd;
> FILE *f = _IO_strfile_readw (&sf, &wd, string);
> - return __vfwscanf_internal (f, format, args, SCANF_ISOC99_A);
> + int done = __vfwscanf_internal (f, format, args, SCANF_ISOC99_A);
> + _IO_wstrfile_fclose_stack (f);
> + return done;
> }
> libc_hidden_def (__isoc99_vswscanf)
@@ -251,3 +251,18 @@ __libio_codecvt_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
return result;
}
+
+void
+_IO_wstrfile_fclose_stack (FILE *fp)
+{
+ _IO_FINISH (fp);
+ if (fp->_mode > 0)
+ {
+ struct _IO_codecvt *cc = fp->_codecvt;
+
+ __libc_lock_lock (__gconv_lock);
+ __gconv_release_step (cc->__cd_in.step);
+ __gconv_release_step (cc->__cd_out.step);
+ __libc_lock_unlock (__gconv_lock);
+ }
+}
@@ -38,6 +38,8 @@ __vswscanf (const wchar_t *string, const wchar_t *format, va_list args)
_IO_strfile sf;
struct _IO_wide_data wd;
FILE *f = _IO_strfile_readw (&sf, &wd, string);
- return __vfwscanf_internal (f, format, args, 0);
+ int done = __vfwscanf_internal (f, format, args, 0);
+ _IO_wstrfile_fclose_stack (f);
+ return done;
}
ldbl_weak_alias (__vswscanf, vswscanf)
@@ -645,6 +645,7 @@ extern FILE* _IO_new_file_fopen (FILE *, const char *, const char *,
int);
extern void _IO_no_init (FILE *, int, int, struct _IO_wide_data *,
const struct _IO_jump_t *) __THROW;
+extern void _IO_wstrfile_fclose_stack (FILE *) attribute_hidden;
extern void _IO_new_file_init_internal (struct _IO_FILE_plus *)
__THROW attribute_hidden;
extern FILE* _IO_new_file_setbuf (FILE *, char *, ssize_t);
@@ -37,7 +37,7 @@ __swscanf (const wchar_t *s, const wchar_t *format, ...)
va_start (arg, format);
done = __vfwscanf_internal (f, format, arg, 0);
va_end (arg);
-
+ _IO_wstrfile_fclose_stack (f);
return done;
}
ldbl_strong_alias (__swscanf, swscanf)
@@ -35,7 +35,7 @@ ___ieee128_isoc23_swscanf (const wchar_t *string, const wchar_t *format, ...)
va_start (ap, format);
done = __vfwscanf_internal (fp, format, ap, mode_flags);
va_end (ap);
-
+ _IO_wstrfile_fclose_stack (fp);
return done;
}
strong_alias (___ieee128_isoc23_swscanf, __isoc23_swscanfieee128)
@@ -28,6 +28,8 @@ ___ieee128_isoc23_vswscanf (wchar_t *string, const wchar_t *format, va_list ap)
FILE *fp = _IO_strfile_readw (&sf, &wd, string);
int mode_flags =
SCANF_ISOC99_A | SCANF_ISOC23_BIN_CST | SCANF_LDBL_USES_FLOAT128;
- return __vfwscanf_internal (fp, format, ap, mode_flags);
+ int done = __vfwscanf_internal (fp, format, ap, mode_flags);
+ _IO_wstrfile_fclose_stack (fp);
+ return done;
}
strong_alias (___ieee128_isoc23_vswscanf, __isoc23_vswscanfieee128)
@@ -34,7 +34,7 @@ ___ieee128_isoc99_swscanf (const wchar_t *string, const wchar_t *format, ...)
va_start (ap, format);
done = __vfwscanf_internal (fp, format, ap, mode_flags);
va_end (ap);
-
+ _IO_wstrfile_fclose_stack (fp);
return done;
}
strong_alias (___ieee128_isoc99_swscanf, __isoc99_swscanfieee128)
@@ -27,6 +27,8 @@ ___ieee128_isoc99_vswscanf (wchar_t *string, const wchar_t *format, va_list ap)
struct _IO_wide_data wd;
FILE *fp = _IO_strfile_readw (&sf, &wd, string);
int mode_flags = SCANF_ISOC99_A | SCANF_LDBL_USES_FLOAT128;
- return __vfwscanf_internal (fp, format, ap, mode_flags);
+ int done = __vfwscanf_internal (fp, format, ap, mode_flags);
+ _IO_wstrfile_fclose_stack (fp);
+ return done;
}
strong_alias (___ieee128_isoc99_vswscanf, __isoc99_vswscanfieee128)
@@ -34,7 +34,7 @@ ___ieee128_swscanf (const wchar_t *string, const wchar_t *format, ...)
done = __vfwscanf_internal (fp, format, ap,
SCANF_LDBL_USES_FLOAT128);
va_end (ap);
-
+ _IO_wstrfile_fclose_stack (fp);
return done;
}
strong_alias (___ieee128_swscanf, __swscanfieee128)
@@ -27,6 +27,8 @@ ___ieee128_vswscanf (const wchar_t *string, const wchar_t *format,
_IO_strfile sf;
struct _IO_wide_data wd;
FILE *fp = _IO_strfile_readw (&sf, &wd, string);
- return __vfwscanf_internal (fp, format, ap, SCANF_LDBL_USES_FLOAT128);
+ int done = __vfwscanf_internal (fp, format, ap, SCANF_LDBL_USES_FLOAT128);
+ _IO_wstrfile_fclose_stack (fp);
+ return done;
}
strong_alias (___ieee128_vswscanf, __vswscanfieee128)
@@ -391,7 +391,9 @@ __nldbl_vswscanf (const wchar_t *s, const wchar_t *fmt, va_list ap)
struct _IO_wide_data wd;
FILE *f = _IO_strfile_readw (&sf, &wd, s);
- return __vfwscanf_internal (f, fmt, ap, SCANF_LDBL_IS_DBL);
+ int ret = __vfwscanf_internal (f, fmt, ap, SCANF_LDBL_IS_DBL);
+ _IO_wstrfile_fclose_stack (f);
+ return ret;
}
libc_hidden_def (__nldbl_vswscanf)
@@ -955,7 +957,9 @@ __nldbl___isoc99_vswscanf (const wchar_t *s, const wchar_t *fmt, va_list ap)
struct _IO_wide_data wd;
FILE *f = _IO_strfile_readw (&sf, &wd, s);
- return __vfwscanf_internal (f, fmt, ap, SCANF_LDBL_IS_DBL | SCANF_ISOC99_A);
+ int ret = __vfwscanf_internal (f, fmt, ap, SCANF_LDBL_IS_DBL | SCANF_ISOC99_A);
+ _IO_wstrfile_fclose_stack (f);
+ return ret;
}
libc_hidden_def (__nldbl___isoc99_vswscanf)
@@ -1115,9 +1119,11 @@ __nldbl___isoc23_vswscanf (const wchar_t *s, const wchar_t *fmt, va_list ap)
struct _IO_wide_data wd;
FILE *f = _IO_strfile_readw (&sf, &wd, s);
- return __vfwscanf_internal (f, fmt, ap,
+ int ret = __vfwscanf_internal (f, fmt, ap,
SCANF_LDBL_IS_DBL | SCANF_ISOC99_A
| SCANF_ISOC23_BIN_CST);
+ _IO_wstrfile_fclose_stack (f);
+ return ret;
}
libc_hidden_def (__nldbl___isoc23_vswscanf)
@@ -33,6 +33,6 @@ __isoc23_swscanf (const wchar_t *s, const wchar_t *format, ...)
done = __vfwscanf_internal (f, format, arg,
SCANF_ISOC99_A | SCANF_ISOC23_BIN_CST);
va_end (arg);
-
+ _IO_wstrfile_fclose_stack (f);
return done;
}
@@ -24,7 +24,9 @@ __isoc23_vswscanf (const wchar_t *string, const wchar_t *format, va_list args)
_IO_strfile sf;
struct _IO_wide_data wd;
FILE *f = _IO_strfile_readw (&sf, &wd, string);
- return __vfwscanf_internal (f, format, args,
+ int done = __vfwscanf_internal (f, format, args,
SCANF_ISOC99_A | SCANF_ISOC23_BIN_CST);
+ _IO_wstrfile_fclose_stack (f);
+ return done;
}
libc_hidden_def (__isoc23_vswscanf)
@@ -32,6 +32,6 @@ __isoc99_swscanf (const wchar_t *s, const wchar_t *format, ...)
va_start (arg, format);
done = __vfwscanf_internal (f, format, arg, SCANF_ISOC99_A);
va_end (arg);
-
+ _IO_wstrfile_fclose_stack (f);
return done;
}
@@ -33,6 +33,8 @@ __isoc99_vswscanf (const wchar_t *string, const wchar_t *format, va_list args)
_IO_strfile sf;
struct _IO_wide_data wd;
FILE *f = _IO_strfile_readw (&sf, &wd, string);
- return __vfwscanf_internal (f, format, args, SCANF_ISOC99_A);
+ int done = __vfwscanf_internal (f, format, args, SCANF_ISOC99_A);
+ _IO_wstrfile_fclose_stack (f);
+ return done;
}
libc_hidden_def (__isoc99_vswscanf)