diff options
author | David Mitchell <davem@iabyn.com> | 2014-12-22 16:25:59 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2014-12-31 11:28:51 +0000 |
commit | 02b08bbcbd0ac87188306a567fc071bbfd134777 (patch) | |
tree | 4976a3981a61ed8bb506cf95047907b0bf22a877 /pp.c | |
parent | 919894b775f42c5afd2195b1a5240e66205560d1 (diff) | |
download | perl-02b08bbcbd0ac87188306a567fc071bbfd134777.tar.gz |
fix more -IV_MIN negations
Doing uv = -iv is undefined behaviour if iv happens to be IV_MIN.
This occurs in several places in the perl sources.
These ones were found by visual code inspection rather than
using -fsanitize=undefined, but I've added extra tests so that
-fsanitize could find them now.
Diffstat (limited to 'pp.c')
-rw-r--r-- | pp.c | 14 |
1 files changed, 9 insertions, 5 deletions
@@ -1337,6 +1337,10 @@ PP(pp_multiply) /* 2s complement assumption that (UV)-IV_MIN is correct. */ /* -ve result, which could overflow an IV */ SP--; + /* can't negate IV_MIN, but there are aren't two + * integers such that !ahigh && !bhigh, where the + * product equals 0x800....000 */ + assert(product != (UV)IV_MIN); SETi( -(IV)product ); RETURN; } /* else drop to NVs below. */ @@ -1437,7 +1441,7 @@ PP(pp_divide) right_non_neg = TRUE; /* effectively it's a UV now */ } else { - right = -biv; + right = (biv == IV_MIN) ? (UV)biv : (UV)(-biv); } } /* historically undef()/0 gives a "Use of uninitialized value" @@ -1458,7 +1462,7 @@ PP(pp_divide) left_non_neg = TRUE; /* effectively it's a UV now */ } else { - left = -aiv; + left = (aiv == IV_MIN) ? (UV)aiv : (UV)(-aiv); } } @@ -1488,7 +1492,7 @@ PP(pp_divide) } /* 2s complement assumption */ if (result <= (UV)IV_MIN) - SETi( -(IV)result ); + SETi(result == (UV)IV_MIN ? IV_MIN : -(IV)result); else { /* It's exact but too negative for IV. */ SETn( -(NV)result ); @@ -1538,7 +1542,7 @@ PP(pp_modulo) right = biv; right_neg = FALSE; /* effectively it's a UV now */ } else { - right = -biv; + right = (biv == IV_MIN) ? (UV)biv : (UV)(-biv); } } } @@ -1568,7 +1572,7 @@ PP(pp_modulo) left = aiv; left_neg = FALSE; /* effectively it's a UV now */ } else { - left = -aiv; + left = (aiv == IV_MIN) ? (UV)aiv : (UV)(-aiv); } } } |