Skip to content

Commit b6180b5

Browse files
committed
Fixed underflow in C++ SDK decimal FromString, ToString and IsValid (#14807)
1 parent 25d79cb commit b6180b5

File tree

1 file changed

+24
-14
lines changed

1 file changed

+24
-14
lines changed

src/library/decimal/yql_decimal.cpp

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ bool IsNormal(TInt128 v) {
3232
}
3333

3434
const char* ToString(TInt128 val, ui8 precision, ui8 scale) {
35-
if (!precision || precision > MaxPrecision || scale > precision) {
35+
if (precision == 0 || precision > MaxPrecision || scale > precision) {
3636
return "";
3737
}
3838

@@ -47,7 +47,7 @@ const char* ToString(TInt128 val, ui8 precision, ui8 scale) {
4747
return nullptr;
4848
}
4949

50-
if (!val) {
50+
if (val == 0) {
5151
return "0";
5252
}
5353

@@ -63,9 +63,10 @@ const char* ToString(TInt128 val, ui8 precision, ui8 scale) {
6363
auto s = end;
6464

6565
do {
66-
if (!precision--) {
66+
if (precision == 0) {
6767
return "";
6868
}
69+
--precision;
6970

7071

7172
const auto digit = ui8(v % Ten);
@@ -80,9 +81,10 @@ const char* ToString(TInt128 val, ui8 precision, ui8 scale) {
8081

8182
if (scale) {
8283
do {
83-
if (!precision--) {
84+
if (precision == 0) {
8485
return nullptr;
8586
}
87+
--precision;
8688

8789
*--s = '0';
8890
} while (--scale);
@@ -119,7 +121,7 @@ TInt128 FromString(const std::string_view& str, ui8 precision, ui8 scale) {
119121
auto s = str.data();
120122
auto l = str.size();
121123

122-
if (!s || !l)
124+
if (s == nullptr || l == 0)
123125
return Err();
124126

125127
const bool neg = '-' == *s;
@@ -138,7 +140,7 @@ TInt128 FromString(const std::string_view& str, ui8 precision, ui8 scale) {
138140
TUint128 v = 0U;
139141
auto integral = precision - scale;
140142

141-
for (bool dot = false; l; --l) {
143+
for (bool dot = false; l > 0; --l) {
142144
if (*s == '.') {
143145
if (dot)
144146
return Err();
@@ -162,19 +164,23 @@ TInt128 FromString(const std::string_view& str, ui8 precision, ui8 scale) {
162164
v *= Ten;
163165
v += c - '0';
164166

165-
if (!dot && v && !integral--) {
166-
return neg ? -Inf() : Inf();
167+
if (!dot && v > 0) {
168+
if (integral == 0) {
169+
return neg ? -Inf() : Inf();
170+
}
171+
--integral;
167172
}
168173
}
169174

170-
if (l--) {
175+
if (l > 0) {
176+
--l;
171177
const char c = *s++;
172178
if (!std::isdigit(c))
173179
return Err();
174180

175181
bool plus = c > '5';
176182
if (!plus && c == '5') {
177-
for (plus = v & 1; !plus && l; --l) {
183+
for (plus = v & 1; !plus && l > 0; --l) {
178184
const char c = *s++;
179185
if (!std::isdigit(c))
180186
return Err();
@@ -183,17 +189,21 @@ TInt128 FromString(const std::string_view& str, ui8 precision, ui8 scale) {
183189
}
184190
}
185191

186-
while (l--)
192+
while (l > 0) {
193+
--l;
187194
if (!std::isdigit(*s++))
188195
return Err();
196+
}
189197

190198
if (plus)
191199
if (++v >= GetDivider(precision))
192200
v = Inf();
193201
}
194202

195-
while (scale--)
203+
while (scale > 0) {
204+
--scale;
196205
v *= Ten;
206+
}
197207

198208
return neg ? -v : v;
199209
}
@@ -209,7 +219,7 @@ bool IsValid(const std::string_view& str) {
209219
auto s = str.data();
210220
auto l = str.size();
211221

212-
if (!s || !l)
222+
if (s == nullptr || l == 0)
213223
return false;
214224

215225
if ('-' == *s || '+' == *s) {
@@ -221,7 +231,7 @@ bool IsValid(const std::string_view& str) {
221231
return true;
222232
}
223233

224-
for (bool dot = false; l--;) {
234+
for (bool dot = false; l > 0; l--) {
225235
const char c = *s++;
226236
if (c == '.') {
227237
if (dot)

0 commit comments

Comments
 (0)