stdlib: fix grouping verification with multi-byte thousands separator (bug 30964)

The grouping verification only worked for a single-byte thousands
separator.  With a multi-byte separator it returned as if no separators
were present.  The actual parsing in str_to_mpn will then go wrong when
there are multiple adjacent multi-byte separators in the number.
This commit is contained in:
Andreas Schwab 2023-10-11 16:22:16 +02:00
parent d846c28389
commit 69239bd7a2
2 changed files with 13 additions and 24 deletions

View File

@ -59,7 +59,6 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
size_t thousands_len = 1; size_t thousands_len = 1;
#else #else
size_t thousands_len = strlen (thousands); size_t thousands_len = strlen (thousands);
int cnt;
#endif #endif
while (end - begin >= thousands_len) while (end - begin >= thousands_len)
@ -74,14 +73,8 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
if (*cp == thousands) if (*cp == thousands)
break; break;
#else #else
if (cp[thousands_len - 1] == *thousands) if (memcmp (cp, thousands, thousands_len) == 0)
{ break;
for (cnt = 1; thousands[cnt] != '\0'; ++cnt)
if (thousands[cnt] != cp[thousands_len - 1 - cnt])
break;
if (thousands[cnt] == '\0')
break;
}
#endif #endif
--cp; --cp;
} }
@ -91,7 +84,7 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
if (cp < begin) if (cp < begin)
return end; return end;
if (end - cp == (int) *gp + 1) if (end - cp == (int) *gp + thousands_len)
{ {
/* This group matches the specification. */ /* This group matches the specification. */
@ -105,7 +98,7 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
remainder of the string from BEGIN to NEW_END is the part we remainder of the string from BEGIN to NEW_END is the part we
will consider if there is a grouping error in this trailing will consider if there is a grouping error in this trailing
portion from CP to END. */ portion from CP to END. */
new_end = cp - 1; new_end = cp;
/* Loop while the grouping is correct. */ /* Loop while the grouping is correct. */
while (1) while (1)
@ -132,10 +125,7 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
if (*cp == thousands) if (*cp == thousands)
break; break;
#else #else
for (cnt = 0; thousands[cnt] != '\0'; ++cnt) if (memcmp (cp, thousands, thousands_len) == 0)
if (thousands[cnt] != cp[thousands_len - cnt - 1])
break;
if (thousands[cnt] == '\0')
break; break;
#endif #endif
--cp; --cp;
@ -156,20 +146,17 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
if (*cp == thousands) if (*cp == thousands)
break; break;
#else #else
for (cnt = 0; thousands[cnt] != '\0'; ++cnt) if (memcmp (cp, thousands, thousands_len) == 0)
if (thousands[cnt] != cp[thousands_len - cnt - 1])
break;
if (thousands[cnt] == '\0')
break; break;
#endif #endif
--cp; --cp;
} }
if (cp < begin && group_end - cp <= (int) *gp) if (cp < begin && group_end - cp <= (int) *gp + thousands_len - 1)
/* Final group is correct. */ /* Final group is correct. */
return end; return end;
if (cp < begin || group_end - cp != (int) *gp) if (cp < begin || group_end - cp != (int) *gp + thousands_len - 1)
/* Incorrect group. Punt. */ /* Incorrect group. Punt. */
break; break;
} }
@ -183,8 +170,8 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
else else
{ {
/* Even the first group was wrong; determine maximum shift. */ /* Even the first group was wrong; determine maximum shift. */
if (end - cp > (int) *gp + 1) if (end - cp > (int) *gp + thousands_len)
end = cp + (int) *gp + 1; end = cp + (int) *gp + thousands_len;
else if (cp < begin) else if (cp < begin)
/* This number does not fill the first group, but is correct. */ /* This number does not fill the first group, but is correct. */
return end; return end;

View File

@ -13,7 +13,9 @@ static const struct
} tests[] = } tests[] =
{ {
{ "000"NNBSP"000"NNBSP"000", "", 0.0 }, { "000"NNBSP"000"NNBSP"000", "", 0.0 },
{ "1"NNBSP"000"NNBSP"000,5x", "x", 1000000.5 } { "1"NNBSP"000"NNBSP"000,5x", "x", 1000000.5 },
/* Bug 30964 */
{ "10"NNBSP NNBSP"200", NNBSP NNBSP"200", 10.0 }
}; };
#define NTESTS (sizeof (tests) / sizeof (tests[0])) #define NTESTS (sizeof (tests) / sizeof (tests[0]))