aboutsummaryrefslogtreecommitdiff
path: root/stdio-common/vfscanf-internal.c
diff options
context:
space:
mode:
Diffstat (limited to 'stdio-common/vfscanf-internal.c')
-rw-r--r--stdio-common/vfscanf-internal.c51
1 files changed, 34 insertions, 17 deletions
diff --git a/stdio-common/vfscanf-internal.c b/stdio-common/vfscanf-internal.c
index bfb9baa..9b1197d 100644
--- a/stdio-common/vfscanf-internal.c
+++ b/stdio-common/vfscanf-internal.c
@@ -1455,13 +1455,14 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
int from_level;
int to_level;
int level;
+ enum { num_digits_len = 10 };
#ifdef COMPILE_WSCANF
- const wchar_t *wcdigits[10];
- const wchar_t *wcdigits_extended[10];
+ const wchar_t *wcdigits[num_digits_len];
#else
- const char *mbdigits[10];
- const char *mbdigits_extended[10];
+ const char *mbdigits[num_digits_len];
#endif
+ CHAR_T *digits_extended[num_digits_len] = { NULL };
+
/* "to_inpunct" is a map from ASCII digits to their
equivalent in locale. This is defined for locales
which use an extra digits set. */
@@ -1482,18 +1483,23 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
/* Adding new level for extra digits set in locale file. */
++to_level;
- for (n = 0; n < 10; ++n)
+ for (n = 0; n < num_digits_len; ++n)
{
#ifdef COMPILE_WSCANF
wcdigits[n] = (const wchar_t *)
_NL_CURRENT (LC_CTYPE, _NL_CTYPE_INDIGITS0_WC + n);
wchar_t *wc_extended = (wchar_t *)
- alloca ((to_level + 2) * sizeof (wchar_t));
+ malloc ((to_level + 2) * sizeof (wchar_t));
+ if (wc_extended == NULL)
+ {
+ done = EOF;
+ goto digits_extended_fail;
+ }
__wmemcpy (wc_extended, wcdigits[n], to_level);
wc_extended[to_level] = __towctrans (L'0' + n, map);
wc_extended[to_level + 1] = '\0';
- wcdigits_extended[n] = wc_extended;
+ digits_extended[n] = wc_extended;
#else
mbdigits[n]
= curctype->values[_NL_CTYPE_INDIGITS0_MB + n].string;
@@ -1524,14 +1530,18 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
size_t mbdigits_len = last_char - mbdigits[n];
/* Allocate memory for extended multibyte digit. */
- char *mb_extended;
- mb_extended = (char *) alloca (mbdigits_len + mblen + 1);
+ char *mb_extended = malloc (mbdigits_len + mblen + 1);
+ if (mb_extended == NULL)
+ {
+ done = EOF;
+ goto digits_extended_fail;
+ }
/* And get the mbdigits + extra_digit string. */
*(char *) __mempcpy (__mempcpy (mb_extended, mbdigits[n],
mbdigits_len),
extra_mbdigit, mblen) = '\0';
- mbdigits_extended[n] = mb_extended;
+ digits_extended[n] = mb_extended;
#endif
}
}
@@ -1541,7 +1551,7 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
{
/* In this round we get the pointer to the digit strings
and also perform the first round of comparisons. */
- for (n = 0; n < 10; ++n)
+ for (n = 0; n < num_digits_len; ++n)
{
/* Get the string for the digits with value N. */
#ifdef COMPILE_WSCANF
@@ -1553,7 +1563,7 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
DIAG_IGNORE_NEEDS_COMMENT (4.7, "-Wmaybe-uninitialized");
if (__glibc_unlikely (map != NULL))
- wcdigits[n] = wcdigits_extended[n];
+ wcdigits[n] = digits_extended[n];
else
wcdigits[n] = (const wchar_t *)
_NL_CURRENT (LC_CTYPE, _NL_CTYPE_INDIGITS0_WC + n);
@@ -1574,7 +1584,7 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
int avail = width > 0 ? width : INT_MAX;
if (__glibc_unlikely (map != NULL))
- mbdigits[n] = mbdigits_extended[n];
+ mbdigits[n] = digits_extended[n];
else
mbdigits[n]
= curctype->values[_NL_CTYPE_INDIGITS0_MB + n].string;
@@ -1617,13 +1627,13 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
#endif
}
- if (n == 10)
+ if (n == num_digits_len)
{
/* Have not yet found the digit. */
for (level = from_level + 1; level <= to_level; ++level)
{
/* Search all ten digits of this level. */
- for (n = 0; n < 10; ++n)
+ for (n = 0; n < num_digits_len; ++n)
{
#ifdef COMPILE_WSCANF
if (c == (wint_t) *wcdigits[n])
@@ -1679,7 +1689,7 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
}
}
- if (n < 10)
+ if (n < num_digits_len)
c = L_('0') + n;
else if (flags & GROUP)
{
@@ -1708,7 +1718,7 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
{
__set_errno (ENOMEM);
done = EOF;
- goto errout;
+ break;
}
if (*cmpp != '\0')
@@ -1742,6 +1752,13 @@ __vfscanf_internal (FILE *s, const char *format, va_list argptr,
c = inchar ();
}
+
+digits_extended_fail:
+ for (n = 0; n < num_digits_len; n++)
+ free (digits_extended[n]);
+
+ if (done == EOF)
+ goto errout;
}
else
/* Read the number into workspace. */