Skip to content

Commit e81efc8

Browse files
authored
[mono] Fix a few corner case overflow operations (#57407)
* [interp] Fix a few overflow conversions Comparison for overflow was incorrect because for example, (int8)-128.5 = -128, without overflows, even if -128.5 is smaller than the minimum integer. We use instead the float equality comparison between trunc (val) and (int)val. * [mono][jit] Fix invalid uses of SHL instead of MUL optimization mono_is_power_of_two is meant to be used only on unsigned numbers. In some cases we pass a signed value instead. This is typically not a problem because negative numbers are not detected as a power of two, except for the special number -2147483648, which is coded as 0x80000000, therefore a power of two. * Enable tests
1 parent 86562e1 commit e81efc8

File tree

6 files changed

+17
-38
lines changed

6 files changed

+17
-38
lines changed

src/mono/mono/mini/interp/interp.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5808,7 +5808,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
58085808
}
58095809
MINT_IN_CASE(MINT_CONV_OVF_I4_R8) {
58105810
double val = LOCAL_VAR (ip [2], double);
5811-
if (val < G_MININT32 || val > G_MAXINT32 || isnan (val))
5811+
if (mono_isnan (val) || mono_trunc (val) != (gint32)val)
58125812
THROW_EX (mono_get_exception_overflow (), ip);
58135813
LOCAL_VAR (ip [1], gint32) = (gint32)val;
58145814
ip += 3;
@@ -5840,7 +5840,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
58405840
}
58415841
MINT_IN_CASE(MINT_CONV_OVF_U4_R8) {
58425842
double val = LOCAL_VAR (ip [2], double);
5843-
if (val < 0 || val > G_MAXUINT32 || isnan (val))
5843+
if (mono_isnan (val) || mono_trunc (val) != (guint32)val)
58445844
THROW_EX (mono_get_exception_overflow (), ip);
58455845
LOCAL_VAR (ip [1], gint32) = (guint32) val;
58465846
ip += 3;
@@ -5880,15 +5880,15 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
58805880
}
58815881
MINT_IN_CASE(MINT_CONV_OVF_I2_R4) {
58825882
float val = LOCAL_VAR (ip [2], float);
5883-
if (val < G_MININT16 || val > G_MAXINT16 || isnan (val))
5883+
if (mono_isnan (val) || mono_trunc (val) != (gint16)val)
58845884
THROW_EX (mono_get_exception_overflow (), ip);
58855885
LOCAL_VAR (ip [1], gint32) = (gint16) val;
58865886
ip += 3;
58875887
MINT_IN_BREAK;
58885888
}
58895889
MINT_IN_CASE(MINT_CONV_OVF_I2_R8) {
58905890
double val = LOCAL_VAR (ip [2], double);
5891-
if (val < G_MININT16 || val > G_MAXINT16 || isnan (val))
5891+
if (mono_isnan (val) || mono_trunc (val) != (gint16)val)
58925892
THROW_EX (mono_get_exception_overflow (), ip);
58935893
LOCAL_VAR (ip [1], gint32) = (gint16) val;
58945894
ip += 3;
@@ -5912,15 +5912,15 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
59125912
}
59135913
MINT_IN_CASE(MINT_CONV_OVF_U2_R4) {
59145914
float val = LOCAL_VAR (ip [2], float);
5915-
if (val < 0 || val > G_MAXUINT16 || isnan (val))
5915+
if (mono_isnan (val) || mono_trunc (val) != (guint16)val)
59165916
THROW_EX (mono_get_exception_overflow (), ip);
59175917
LOCAL_VAR (ip [1], gint32) = (guint16) val;
59185918
ip += 3;
59195919
MINT_IN_BREAK;
59205920
}
59215921
MINT_IN_CASE(MINT_CONV_OVF_U2_R8) {
59225922
double val = LOCAL_VAR (ip [2], double);
5923-
if (val < 0 || val > G_MAXUINT16 || isnan (val))
5923+
if (mono_isnan (val) || mono_trunc (val) != (guint16)val)
59245924
THROW_EX (mono_get_exception_overflow (), ip);
59255925
LOCAL_VAR (ip [1], gint32) = (guint16) val;
59265926
ip += 3;
@@ -5960,15 +5960,15 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
59605960
}
59615961
MINT_IN_CASE(MINT_CONV_OVF_I1_R4) {
59625962
float val = LOCAL_VAR (ip [2], float);
5963-
if (val < G_MININT8 || val > G_MAXINT8 || isnan (val))
5963+
if (mono_isnan (val) || mono_trunc (val) != (gint8)val)
59645964
THROW_EX (mono_get_exception_overflow (), ip);
59655965
LOCAL_VAR (ip [1], gint32) = (gint8) val;
59665966
ip += 3;
59675967
MINT_IN_BREAK;
59685968
}
59695969
MINT_IN_CASE(MINT_CONV_OVF_I1_R8) {
59705970
double val = LOCAL_VAR (ip [2], double);
5971-
if (val < G_MININT8 || val > G_MAXINT8 || isnan (val))
5971+
if (mono_isnan (val) || mono_trunc (val) != (gint8)val)
59725972
THROW_EX (mono_get_exception_overflow (), ip);
59735973
LOCAL_VAR (ip [1], gint32) = (gint8) val;
59745974
ip += 3;
@@ -5992,15 +5992,15 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
59925992
}
59935993
MINT_IN_CASE(MINT_CONV_OVF_U1_R4) {
59945994
float val = LOCAL_VAR (ip [2], float);
5995-
if (val < 0 || val > G_MAXUINT8 || isnan (val))
5995+
if (mono_isnan (val) || mono_trunc (val) != (guint8)val)
59965996
THROW_EX (mono_get_exception_overflow (), ip);
59975997
LOCAL_VAR (ip [1], gint32) = (guint8) val;
59985998
ip += 3;
59995999
MINT_IN_BREAK;
60006000
}
60016001
MINT_IN_CASE(MINT_CONV_OVF_U1_R8) {
60026002
double val = LOCAL_VAR (ip [2], double);
6003-
if (val < 0 || val > G_MAXUINT8 || isnan (val))
6003+
if (mono_isnan (val) || mono_trunc (val) != (guint8)val)
60046004
THROW_EX (mono_get_exception_overflow (), ip);
60056005
LOCAL_VAR (ip [1], gint32) = (guint8) val;
60066006
ip += 3;

src/mono/mono/mini/local-propagation.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ mono_strength_reduction_division (MonoCompile *cfg, MonoInst *ins)
223223
guint32 tmp_regi;
224224
#endif
225225
struct magic_signed mag;
226-
int power2 = mono_is_power_of_two (ins->inst_imm);
226+
int power2 = (ins->inst_imm > 0) ? mono_is_power_of_two (ins->inst_imm) : -1;
227227
/* The decomposition doesn't handle exception throwing */
228228
/* Optimization with MUL does not apply for -1, 0 and 1 divisors */
229229
if (ins->inst_imm == 0 || ins->inst_imm == -1) {
@@ -350,7 +350,7 @@ mono_strength_reduction_ins (MonoCompile *cfg, MonoInst *ins, const char **spec)
350350
ins->opcode = OP_INEG;
351351
} else if ((ins->opcode == OP_LMUL_IMM) && (ins->inst_imm == -1)) {
352352
ins->opcode = OP_LNEG;
353-
} else {
353+
} else if (ins->inst_imm > 0) {
354354
int power2 = mono_is_power_of_two (ins->inst_imm);
355355
if (power2 >= 0) {
356356
ins->opcode = (ins->opcode == OP_MUL_IMM) ? OP_SHL_IMM : ((ins->opcode == OP_LMUL_IMM) ? OP_LSHL_IMM : OP_ISHL_IMM);

src/mono/mono/mini/mini-arm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3466,7 +3466,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
34663466
ins->inst_c0 = 0;
34673467
break;
34683468
}
3469-
imm8 = mono_is_power_of_two (ins->inst_imm);
3469+
imm8 = (ins->inst_imm > 0) ? mono_is_power_of_two (ins->inst_imm) : -1;
34703470
if (imm8 > 0) {
34713471
ins->opcode = OP_SHL_IMM;
34723472
ins->inst_imm = imm8;

src/mono/mono/mini/mini-mips.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,7 +1987,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
19871987
MONO_DELETE_INS (bb, ins);
19881988
continue;
19891989
}
1990-
} else {
1990+
} else if (ins->inst_imm > 0) {
19911991
int power2 = mono_is_power_of_two (ins->inst_imm);
19921992
if (power2 > 0) {
19931993
ins->opcode = OP_SHL_IMM;
@@ -2666,7 +2666,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
26662666
ins->inst_c0 = 0;
26672667
break;
26682668
}
2669-
imm = mono_is_power_of_two (ins->inst_imm);
2669+
imm = (ins->inst_imm > 0) ? mono_is_power_of_two (ins->inst_imm) : -1;
26702670
if (imm > 0) {
26712671
ins->opcode = OP_SHL_IMM;
26722672
ins->inst_imm = imm;

src/mono/mono/mini/mini-ppc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1963,7 +1963,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
19631963
MONO_DELETE_INS (bb, ins);
19641964
continue;
19651965
}
1966-
} else {
1966+
} else if (inst->inst_imm > 0) {
19671967
int power2 = mono_is_power_of_two (ins->inst_imm);
19681968
if (power2 > 0) {
19691969
ins->opcode = OP_SHL_IMM;
@@ -2537,7 +2537,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
25372537
ins->inst_c0 = 0;
25382538
break;
25392539
}
2540-
imm = mono_is_power_of_two (ins->inst_imm);
2540+
imm = (ins->inst_imm > 0) ? mono_is_power_of_two (ins->inst_imm) : -1;
25412541
if (imm > 0) {
25422542
ins->opcode = OP_SHL_IMM;
25432543
ins->inst_imm = imm;

src/tests/issues.targets

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -965,27 +965,9 @@
965965
</ExcludeList>
966966

967967

968-
<ExcludeList Include="$(XunitTestBinBase)/JIT/Directed/Convert/value_numbering_checked_casts_of_constants/*">
969-
<Issue>https://github.com/dotnet/runtime/issues/51323</Issue>
970-
</ExcludeList>
971-
<ExcludeList Include="$(XunitTestBinBase)/JIT/Methodical/int64/misc/longmul/*">
972-
<Issue>https://github.com/dotnet/runtime/issues/51323</Issue>
973-
</ExcludeList>
974968
<ExcludeList Include="$(XunitTestBinBase)/JIT/Directed/Convert/out_of_range_fp_to_int_conversions/*">
975969
<Issue>Mono does not define out of range fp to int conversions</Issue>
976970
</ExcludeList>
977-
<ExcludeList Include="$(XunitTestBinBase)/JIT/Methodical/Overflow/FloatOvfToInt2_r/*">
978-
<Issue>https://github.com/dotnet/runtime/issues/51323</Issue>
979-
</ExcludeList>
980-
<ExcludeList Include="$(XunitTestBinBase)/JIT/Methodical/Overflow/FloatOvfToInt2_ro/*">
981-
<Issue>https://github.com/dotnet/runtime/issues/51323</Issue>
982-
</ExcludeList>
983-
<ExcludeList Include="$(XunitTestBinBase)/JIT/Methodical/Overflow/FloatOvfToInt2_d/*">
984-
<Issue>https://github.com/dotnet/runtime/issues/51323</Issue>
985-
</ExcludeList>
986-
<ExcludeList Include="$(XunitTestBinBase)/JIT/Methodical/Overflow/FloatOvfToInt2_do/*">
987-
<Issue>https://github.com/dotnet/runtime/issues/51323</Issue>
988-
</ExcludeList>
989971
<ExcludeList Include="$(XunitTestBinBase)/JIT/opt/Devirtualization/Comparer_get_Default/*">
990972
<Issue>https://github.com/dotnet/runtime/issues/48190</Issue>
991973
</ExcludeList>
@@ -1239,9 +1221,6 @@
12391221
<ExcludeList Include="$(XunitTestBinBase)/JIT/Directed/Convert/ldind_conv/**">
12401222
<Issue>needs triage</Issue>
12411223
</ExcludeList>
1242-
<ExcludeList Include="$(XunitTestBinBase)/JIT/Directed/Convert/signed_overflow_conversions_are_not_treated_as_unsigned/**">
1243-
<Issue>https://github.com/dotnet/runtime/issues/51323</Issue>
1244-
</ExcludeList>
12451224
<ExcludeList Include="$(XunitTestBinBase)/JIT/Directed/coverage/compiler/FilterToHandler/**">
12461225
<Issue>needs triage</Issue>
12471226
</ExcludeList>

0 commit comments

Comments
 (0)