aboutsummaryrefslogtreecommitdiff
path: root/src/lj_strscan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_strscan.c')
-rw-r--r--src/lj_strscan.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/src/lj_strscan.c b/src/lj_strscan.c
index f681fbb0..173455b4 100644
--- a/src/lj_strscan.c
+++ b/src/lj_strscan.c
@@ -63,6 +63,7 @@
63#define STRSCAN_MAXDIG 800 /* 772 + extra are sufficient. */ 63#define STRSCAN_MAXDIG 800 /* 772 + extra are sufficient. */
64#define STRSCAN_DDIG (STRSCAN_DIG/2) 64#define STRSCAN_DDIG (STRSCAN_DIG/2)
65#define STRSCAN_DMASK (STRSCAN_DDIG-1) 65#define STRSCAN_DMASK (STRSCAN_DDIG-1)
66#define STRSCAN_MAXEXP (1 << 20)
66 67
67/* Helpers for circular buffer. */ 68/* Helpers for circular buffer. */
68#define DNEXT(a) (((a)+1) & STRSCAN_DMASK) 69#define DNEXT(a) (((a)+1) & STRSCAN_DMASK)
@@ -121,7 +122,8 @@ static StrScanFmt strscan_hex(const uint8_t *p, TValue *o,
121 /* Format-specific handling. */ 122 /* Format-specific handling. */
122 switch (fmt) { 123 switch (fmt) {
123 case STRSCAN_INT: 124 case STRSCAN_INT:
124 if (!(opt & STRSCAN_OPT_TONUM) && x < 0x80000000u+neg) { 125 if (!(opt & STRSCAN_OPT_TONUM) && x < 0x80000000u+neg &&
126 !(x == 0 && neg)) {
125 o->i = neg ? -(int32_t)x : (int32_t)x; 127 o->i = neg ? -(int32_t)x : (int32_t)x;
126 return STRSCAN_INT; /* Fast path for 32 bit integers. */ 128 return STRSCAN_INT; /* Fast path for 32 bit integers. */
127 } 129 }
@@ -448,6 +450,7 @@ StrScanFmt lj_strscan_scan(const uint8_t *p, MSize len, TValue *o,
448 if (dig) { 450 if (dig) {
449 ex = (int32_t)(dp-(p-1)); dp = p-1; 451 ex = (int32_t)(dp-(p-1)); dp = p-1;
450 while (ex < 0 && *dp-- == '0') ex++, dig--; /* Skip trailing zeros. */ 452 while (ex < 0 && *dp-- == '0') ex++, dig--; /* Skip trailing zeros. */
453 if (ex <= -STRSCAN_MAXEXP) return STRSCAN_ERROR;
451 if (base == 16) ex *= 4; 454 if (base == 16) ex *= 4;
452 } 455 }
453 } 456 }
@@ -461,7 +464,8 @@ StrScanFmt lj_strscan_scan(const uint8_t *p, MSize len, TValue *o,
461 if (!lj_char_isdigit(*p)) return STRSCAN_ERROR; 464 if (!lj_char_isdigit(*p)) return STRSCAN_ERROR;
462 xx = (*p++ & 15); 465 xx = (*p++ & 15);
463 while (lj_char_isdigit(*p)) { 466 while (lj_char_isdigit(*p)) {
464 if (xx < 65536) xx = xx * 10 + (*p & 15); 467 xx = xx * 10 + (*p & 15);
468 if (xx >= STRSCAN_MAXEXP) return STRSCAN_ERROR;
465 p++; 469 p++;
466 } 470 }
467 ex += negx ? -(int32_t)xx : (int32_t)xx; 471 ex += negx ? -(int32_t)xx : (int32_t)xx;
@@ -499,6 +503,9 @@ StrScanFmt lj_strscan_scan(const uint8_t *p, MSize len, TValue *o,
499 if ((opt & STRSCAN_OPT_TONUM)) { 503 if ((opt & STRSCAN_OPT_TONUM)) {
500 o->n = neg ? -(double)x : (double)x; 504 o->n = neg ? -(double)x : (double)x;
501 return STRSCAN_NUM; 505 return STRSCAN_NUM;
506 } else if (x == 0 && neg) {
507 o->n = -0.0;
508 return STRSCAN_NUM;
502 } else { 509 } else {
503 o->i = neg ? -(int32_t)x : (int32_t)x; 510 o->i = neg ? -(int32_t)x : (int32_t)x;
504 return STRSCAN_INT; 511 return STRSCAN_INT;
@@ -516,7 +523,7 @@ StrScanFmt lj_strscan_scan(const uint8_t *p, MSize len, TValue *o,
516 fmt = strscan_dec(sp, o, fmt, opt, ex, neg, dig); 523 fmt = strscan_dec(sp, o, fmt, opt, ex, neg, dig);
517 524
518 /* Try to convert number to integer, if requested. */ 525 /* Try to convert number to integer, if requested. */
519 if (fmt == STRSCAN_NUM && (opt & STRSCAN_OPT_TOINT)) { 526 if (fmt == STRSCAN_NUM && (opt & STRSCAN_OPT_TOINT) && !tvismzero(o)) {
520 double n = o->n; 527 double n = o->n;
521 int32_t i = lj_num2int(n); 528 int32_t i = lj_num2int(n);
522 if (n == (lua_Number)i) { o->i = i; return STRSCAN_INT; } 529 if (n == (lua_Number)i) { o->i = i; return STRSCAN_INT; }