|
@@ -63,6 +63,7 @@
|
|
|
#define STRSCAN_MAXDIG 800 /* 772 + extra are sufficient. */
|
|
|
#define STRSCAN_DDIG (STRSCAN_DIG/2)
|
|
|
#define STRSCAN_DMASK (STRSCAN_DDIG-1)
|
|
|
+#define STRSCAN_MAXEXP (1 << 20)
|
|
|
|
|
|
/* Helpers for circular buffer. */
|
|
|
#define DNEXT(a) (((a)+1) & STRSCAN_DMASK)
|
|
@@ -121,7 +122,8 @@ static StrScanFmt strscan_hex(const uint8_t *p, TValue *o,
|
|
|
/* Format-specific handling. */
|
|
|
switch (fmt) {
|
|
|
case STRSCAN_INT:
|
|
|
- if (!(opt & STRSCAN_OPT_TONUM) && x < 0x80000000u+neg) {
|
|
|
+ if (!(opt & STRSCAN_OPT_TONUM) && x < 0x80000000u+neg &&
|
|
|
+ !(x == 0 && neg)) {
|
|
|
o->i = neg ? -(int32_t)x : (int32_t)x;
|
|
|
return STRSCAN_INT; /* Fast path for 32 bit integers. */
|
|
|
}
|
|
@@ -448,6 +450,7 @@ StrScanFmt lj_strscan_scan(const uint8_t *p, MSize len, TValue *o,
|
|
|
if (dig) {
|
|
|
ex = (int32_t)(dp-(p-1)); dp = p-1;
|
|
|
while (ex < 0 && *dp-- == '0') ex++, dig--; /* Skip trailing zeros. */
|
|
|
+ if (ex <= -STRSCAN_MAXEXP) return STRSCAN_ERROR;
|
|
|
if (base == 16) ex *= 4;
|
|
|
}
|
|
|
}
|
|
@@ -461,7 +464,8 @@ StrScanFmt lj_strscan_scan(const uint8_t *p, MSize len, TValue *o,
|
|
|
if (!lj_char_isdigit(*p)) return STRSCAN_ERROR;
|
|
|
xx = (*p++ & 15);
|
|
|
while (lj_char_isdigit(*p)) {
|
|
|
- if (xx < 65536) xx = xx * 10 + (*p & 15);
|
|
|
+ xx = xx * 10 + (*p & 15);
|
|
|
+ if (xx >= STRSCAN_MAXEXP) return STRSCAN_ERROR;
|
|
|
p++;
|
|
|
}
|
|
|
ex += negx ? -(int32_t)xx : (int32_t)xx;
|
|
@@ -499,6 +503,9 @@ StrScanFmt lj_strscan_scan(const uint8_t *p, MSize len, TValue *o,
|
|
|
if ((opt & STRSCAN_OPT_TONUM)) {
|
|
|
o->n = neg ? -(double)x : (double)x;
|
|
|
return STRSCAN_NUM;
|
|
|
+ } else if (x == 0 && neg) {
|
|
|
+ o->n = -0.0;
|
|
|
+ return STRSCAN_NUM;
|
|
|
} else {
|
|
|
o->i = neg ? -(int32_t)x : (int32_t)x;
|
|
|
return STRSCAN_INT;
|
|
@@ -516,7 +523,7 @@ StrScanFmt lj_strscan_scan(const uint8_t *p, MSize len, TValue *o,
|
|
|
fmt = strscan_dec(sp, o, fmt, opt, ex, neg, dig);
|
|
|
|
|
|
/* Try to convert number to integer, if requested. */
|
|
|
- if (fmt == STRSCAN_NUM && (opt & STRSCAN_OPT_TOINT)) {
|
|
|
+ if (fmt == STRSCAN_NUM && (opt & STRSCAN_OPT_TOINT) && !tvismzero(o)) {
|
|
|
double n = o->n;
|
|
|
int32_t i = lj_num2int(n);
|
|
|
if (n == (lua_Number)i) { o->i = i; return STRSCAN_INT; }
|