aboutsummaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/lj_ffrecord.c6
-rw-r--r--src/lj_iropt.h4
-rw-r--r--src/lj_opt_narrow.c42
-rw-r--r--src/lj_record.c4
4 files changed, 28 insertions, 28 deletions
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c
index c258aee1..99d54233 100644
--- a/src/lj_ffrecord.c
+++ b/src/lj_ffrecord.c
@@ -539,10 +539,8 @@ static void LJ_FASTCALL recff_math_degrad(jit_State *J, RecordFFData *rd)
539 539
540static void LJ_FASTCALL recff_math_pow(jit_State *J, RecordFFData *rd) 540static void LJ_FASTCALL recff_math_pow(jit_State *J, RecordFFData *rd)
541{ 541{
542 TRef tr = lj_ir_tonum(J, J->base[0]); 542 J->base[0] = lj_opt_narrow_pow(J, J->base[0], J->base[1],
543 if (!tref_isnumber_str(J->base[1])) 543 &rd->argv[0], &rd->argv[1]);
544 lj_trace_err(J, LJ_TRERR_BADTYPE);
545 J->base[0] = lj_opt_narrow_pow(J, tr, J->base[1], &rd->argv[1]);
546 UNUSED(rd); 544 UNUSED(rd);
547} 545}
548 546
diff --git a/src/lj_iropt.h b/src/lj_iropt.h
index 1836e1b0..4bf95f15 100644
--- a/src/lj_iropt.h
+++ b/src/lj_iropt.h
@@ -142,8 +142,8 @@ LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_cindex(jit_State *J, TRef key);
142LJ_FUNC TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc, 142LJ_FUNC TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc,
143 TValue *vb, TValue *vc, IROp op); 143 TValue *vb, TValue *vc, IROp op);
144LJ_FUNC TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc); 144LJ_FUNC TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc);
145LJ_FUNC TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vc); 145LJ_FUNC TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vb, TValue *vc);
146LJ_FUNC TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vc); 146LJ_FUNC TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vb, TValue *vc);
147LJ_FUNC IRType lj_opt_narrow_forl(jit_State *J, cTValue *forbase); 147LJ_FUNC IRType lj_opt_narrow_forl(jit_State *J, cTValue *forbase);
148 148
149/* Optimization passes. */ 149/* Optimization passes. */
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 }
diff --git a/src/lj_record.c b/src/lj_record.c
index 9b51c51f..ff7825ee 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -1884,14 +1884,14 @@ void lj_record_ins(jit_State *J)
1884 case BC_MODVN: case BC_MODVV: 1884 case BC_MODVN: case BC_MODVV:
1885 recmod: 1885 recmod:
1886 if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) 1886 if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
1887 rc = lj_opt_narrow_mod(J, rb, rc, rcv); 1887 rc = lj_opt_narrow_mod(J, rb, rc, rbv, rcv);
1888 else 1888 else
1889 rc = rec_mm_arith(J, &ix, MM_mod); 1889 rc = rec_mm_arith(J, &ix, MM_mod);
1890 break; 1890 break;
1891 1891
1892 case BC_POW: 1892 case BC_POW:
1893 if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) 1893 if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
1894 rc = lj_opt_narrow_pow(J, lj_ir_tonum(J, rb), rc, rcv); 1894 rc = lj_opt_narrow_pow(J, rb, rc, rbv, rcv);
1895 else 1895 else
1896 rc = rec_mm_arith(J, &ix, MM_pow); 1896 rc = rec_mm_arith(J, &ix, MM_pow);
1897 break; 1897 break;