summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2014-12-22 16:25:59 +0000
committerDavid Mitchell <davem@iabyn.com>2014-12-31 11:28:51 +0000
commit02b08bbcbd0ac87188306a567fc071bbfd134777 (patch)
tree4976a3981a61ed8bb506cf95047907b0bf22a877 /pp.c
parent919894b775f42c5afd2195b1a5240e66205560d1 (diff)
downloadperl-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.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/pp.c b/pp.c
index e24b5714fe..4f43704a61 100644
--- a/pp.c
+++ b/pp.c
@@ -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);
}
}
}