aboutsummaryrefslogtreecommitdiff
path: root/src/lj_opt_narrow.c
diff options
context:
space:
mode:
authorMike Pall <mike>2016-04-21 17:00:58 +0200
committerMike Pall <mike>2016-04-21 17:00:58 +0200
commit2f0001fad05731ea3787b27cf9b19e5293c358b8 (patch)
treecbfbb921518399867b24b0d82bf2ccc7fc111bf7 /src/lj_opt_narrow.c
parentcc4f5d056ab93521451631f28501015f054d8976 (diff)
downloadluajit-2f0001fad05731ea3787b27cf9b19e5293c358b8.tar.gz
luajit-2f0001fad05731ea3787b27cf9b19e5293c358b8.tar.bz2
luajit-2f0001fad05731ea3787b27cf9b19e5293c358b8.zip
Fix handling of non-numeric strings in arithmetic coercions.
Thanks to Vyacheslav Egorov.
Diffstat (limited to 'src/lj_opt_narrow.c')
-rw-r--r--src/lj_opt_narrow.c42
1 files changed, 22 insertions, 20 deletions
diff --git a/src/lj_opt_narrow.c b/src/lj_opt_narrow.c
index b1ab5ba8..36be66ee 100644
--- a/src/lj_opt_narrow.c
+++ b/src/lj_opt_narrow.c
@@ -517,18 +517,24 @@ static int numisint(lua_Number n)
517 return (n == (lua_Number)lj_num2int(n)); 517 return (n == (lua_Number)lj_num2int(n));
518} 518}
519 519
520/* Convert string to number. Error out for non-numeric string values. */
521static TRef conv_str_tonum(jit_State *J, TRef tr, TValue *o)
522{
523 if (tref_isstr(tr)) {
524 tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0);
525 /* Would need an inverted STRTO for this rare and useless case. */
526 if (!lj_strscan_num(strV(o), o)) /* Convert in-place. Value used below. */
527 lj_trace_err(J, LJ_TRERR_BADTYPE); /* Punt if non-numeric. */
528 }
529 return tr;
530}
531
520/* Narrowing of arithmetic operations. */ 532/* Narrowing of arithmetic operations. */
521TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc, 533TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc,
522 TValue *vb, TValue *vc, IROp op) 534 TValue *vb, TValue *vc, IROp op)
523{ 535{
524 if (tref_isstr(rb)) { 536 rb = conv_str_tonum(J, rb, vb);
525 rb = emitir(IRTG(IR_STRTO, IRT_NUM), rb, 0); 537 rc = conv_str_tonum(J, rc, vc);
526 lj_strscan_num(strV(vb), vb);
527 }
528 if (tref_isstr(rc)) {
529 rc = emitir(IRTG(IR_STRTO, IRT_NUM), rc, 0);
530 lj_strscan_num(strV(vc), vc);
531 }
532 /* Must not narrow MUL in non-DUALNUM variant, because it loses -0. */ 538 /* Must not narrow MUL in non-DUALNUM variant, because it loses -0. */
533 if ((op >= IR_ADD && op <= (LJ_DUALNUM ? IR_MUL : IR_SUB)) && 539 if ((op >= IR_ADD && op <= (LJ_DUALNUM ? IR_MUL : IR_SUB)) &&
534 tref_isinteger(rb) && tref_isinteger(rc) && 540 tref_isinteger(rb) && tref_isinteger(rc) &&
@@ -543,10 +549,7 @@ TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc,
543/* Narrowing of unary minus operator. */ 549/* Narrowing of unary minus operator. */
544TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc) 550TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc)
545{ 551{
546 if (tref_isstr(rc)) { 552 rc = conv_str_tonum(J, rc, vc);
547 rc = emitir(IRTG(IR_STRTO, IRT_NUM), rc, 0);
548 lj_strscan_num(strV(vc), vc);
549 }
550 if (tref_isinteger(rc)) { 553 if (tref_isinteger(rc)) {
551 if ((uint32_t)numberVint(vc) != 0x80000000u) 554 if ((uint32_t)numberVint(vc) != 0x80000000u)
552 return emitir(IRTGI(IR_SUBOV), lj_ir_kint(J, 0), rc); 555 return emitir(IRTGI(IR_SUBOV), lj_ir_kint(J, 0), rc);
@@ -556,11 +559,11 @@ TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc)
556} 559}
557 560
558/* Narrowing of modulo operator. */ 561/* Narrowing of modulo operator. */
559TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vc) 562TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vb, TValue *vc)
560{ 563{
561 TRef tmp; 564 TRef tmp;
562 if (tvisstr(vc) && !lj_strscan_num(strV(vc), vc)) 565 rb = conv_str_tonum(J, rb, vb);
563 lj_trace_err(J, LJ_TRERR_BADTYPE); 566 rc = conv_str_tonum(J, rc, vc);
564 if ((LJ_DUALNUM || (J->flags & JIT_F_OPT_NARROW)) && 567 if ((LJ_DUALNUM || (J->flags & JIT_F_OPT_NARROW)) &&
565 tref_isinteger(rb) && tref_isinteger(rc) && 568 tref_isinteger(rb) && tref_isinteger(rc) &&
566 (tvisint(vc) ? intV(vc) != 0 : !tviszero(vc))) { 569 (tvisint(vc) ? intV(vc) != 0 : !tviszero(vc))) {
@@ -577,10 +580,11 @@ TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vc)
577} 580}
578 581
579/* Narrowing of power operator or math.pow. */ 582/* Narrowing of power operator or math.pow. */
580TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vc) 583TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vb, TValue *vc)
581{ 584{
582 if (tvisstr(vc) && !lj_strscan_num(strV(vc), vc)) 585 rb = conv_str_tonum(J, rb, vb);
583 lj_trace_err(J, LJ_TRERR_BADTYPE); 586 rb = lj_ir_tonum(J, rb); /* Left arg is always treated as an FP number. */
587 rc = conv_str_tonum(J, rc, vc);
584 /* Narrowing must be unconditional to preserve (-x)^i semantics. */ 588 /* Narrowing must be unconditional to preserve (-x)^i semantics. */
585 if (tvisint(vc) || numisint(numV(vc))) { 589 if (tvisint(vc) || numisint(numV(vc))) {
586 int checkrange = 0; 590 int checkrange = 0;
@@ -591,8 +595,6 @@ TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vc)
591 checkrange = 1; 595 checkrange = 1;
592 } 596 }
593 if (!tref_isinteger(rc)) { 597 if (!tref_isinteger(rc)) {
594 if (tref_isstr(rc))
595 rc = emitir(IRTG(IR_STRTO, IRT_NUM), rc, 0);
596 /* Guarded conversion to integer! */ 598 /* Guarded conversion to integer! */
597 rc = emitir(IRTGI(IR_CONV), rc, IRCONV_INT_NUM|IRCONV_CHECK); 599 rc = emitir(IRTGI(IR_CONV), rc, IRCONV_INT_NUM|IRCONV_CHECK);
598 } 600 }