summaryrefslogtreecommitdiff
path: root/backport-stdlib-fix-grouping-verification-with-multi-byte-tho.patch
blob: 196707b9718bdbff1302f0ac2f573dc547c620ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
From 69239bd7a216007692470aa9d5f3658024638742 Mon Sep 17 00:00:00 2001
From: Andreas Schwab <schwab@suse.de>
Date: Wed, 11 Oct 2023 16:22:16 +0200
Subject: [PATCH] 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.

Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=69239bd7a216007692470aa9d5f3658024638742
Conflict:NA

---
 stdlib/grouping.c    | 33 ++++++++++-----------------------
 stdlib/tst-strtod4.c |  4 +++-
 2 files changed, 13 insertions(+), 24 deletions(-)

diff --git a/stdlib/grouping.c b/stdlib/grouping.c
index b6bf1dbab2..16b266d3e0 100644
--- a/stdlib/grouping.c
+++ b/stdlib/grouping.c
@@ -59,7 +59,6 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
   size_t thousands_len = 1;
 #else
   size_t thousands_len = strlen (thousands);
-  int cnt;
 #endif
 
   while (end - begin >= thousands_len)
@@ -74,14 +73,8 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
 	  if (*cp == thousands)
 	    break;
 #else
-	  if (cp[thousands_len - 1] == *thousands)
-	    {
-	      for (cnt = 1; thousands[cnt] != '\0'; ++cnt)
-		if (thousands[cnt] != cp[thousands_len - 1 - cnt])
-		  break;
-	      if (thousands[cnt] == '\0')
-		break;
-	    }
+	  if (memcmp (cp, thousands, thousands_len) == 0)
+	    break;
 #endif
 	  --cp;
 	}
@@ -91,7 +84,7 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
       if (cp < begin)
 	return end;
 
-      if (end - cp == (int) *gp + 1)
+      if (end - cp == (int) *gp + thousands_len)
 	{
 	  /* 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
 	     will consider if there is a grouping error in this trailing
 	     portion from CP to END.  */
-	  new_end = cp - 1;
+	  new_end = cp;
 
 	  /* Loop while the grouping is correct.  */
 	  while (1)
@@ -132,10 +125,7 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
 		      if (*cp == thousands)
 			break;
 #else
-		      for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
-			if (thousands[cnt] != cp[thousands_len - cnt - 1])
-			  break;
-		      if (thousands[cnt] == '\0')
+		      if (memcmp (cp, thousands, thousands_len) == 0)
 			break;
 #endif
 		      --cp;
@@ -156,20 +146,17 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
 		      if (*cp == thousands)
 			break;
 #else
-		      for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
-			if (thousands[cnt] != cp[thousands_len - cnt - 1])
-			  break;
-		      if (thousands[cnt] == '\0')
+		      if (memcmp (cp, thousands, thousands_len) == 0)
 			break;
 #endif
 		      --cp;
 		    }
 
-		  if (cp < begin && group_end - cp <= (int) *gp)
+		  if (cp < begin && group_end - cp <= (int) *gp + thousands_len - 1)
 		    /* Final group is correct.  */
 		    return end;
 
-		  if (cp < begin || group_end - cp != (int) *gp)
+		  if (cp < begin || group_end - cp != (int) *gp + thousands_len - 1)
 		    /* Incorrect group.  Punt.  */
 		    break;
 		}
@@ -183,8 +170,8 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
       else
 	{
 	  /* Even the first group was wrong; determine maximum shift.  */
-	  if (end - cp > (int) *gp + 1)
-	    end = cp + (int) *gp + 1;
+	  if (end - cp > (int) *gp + thousands_len)
+	    end = cp + (int) *gp + thousands_len;
 	  else if (cp < begin)
 	    /* This number does not fill the first group, but is correct.  */
 	    return end;
diff --git a/stdlib/tst-strtod4.c b/stdlib/tst-strtod4.c
index aae9835d82..6cc4e843c7 100644
--- a/stdlib/tst-strtod4.c
+++ b/stdlib/tst-strtod4.c
@@ -13,7 +13,9 @@ static const struct
 } tests[] =
   {
     { "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]))
 
-- 
2.37.3.1