From 6705981bbf4fb4dca956882d9540285e13273600 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Tue, 26 Apr 2022 18:25:34 -0700 Subject: [PATCH] fix UB --- openpower/sv/biginteger/analysis.mdwn | 4 ++-- openpower/sv/biginteger/divgnu64.c | 7 +++---- openpower/sv/biginteger/divmnu64.c | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/openpower/sv/biginteger/analysis.mdwn b/openpower/sv/biginteger/analysis.mdwn index 28f535db4..703f51235 100644 --- a/openpower/sv/biginteger/analysis.mdwn +++ b/openpower/sv/biginteger/analysis.mdwn @@ -112,7 +112,7 @@ that when Vectorised are exactly what is needed. void biglsh(unsigned s, unsigned vn[], unsigned const v[], int n) { for (int i = n - 1; i > 0; i--) - vn[i] = (v[i] << s) | ((unsigned long long)v[i - 1] >> (32 - s)); + vn[i] = ((unsigned long long)v[i] << s) | (v[i - 1] >> (32 - s)); vn[0] = v[0] << s; } ``` @@ -356,7 +356,7 @@ the digits are 32 bit and, special-casing the overflow, a 64/32 divide is suffic uint64_t dig2 = ((uint64_t)un[j + n] << 32) | un[j + n - 1]; if (un[j+n] >= vn[n-1]) { // rhat can be bigger than 32-bit when the division overflows, - rhat = dig2 - UINT32_MAX * vn[n - 1]; + rhat = dig2 - (uint64_t)UINT32_MAX * vn[n - 1]; } else { qhat = dig2 / vn[n - 1]; // 64/32 divide rhat = dig2 % vn[n - 1]; // 64/32 modulo diff --git a/openpower/sv/biginteger/divgnu64.c b/openpower/sv/biginteger/divgnu64.c index f2422933d..649143963 100644 --- a/openpower/sv/biginteger/divgnu64.c +++ b/openpower/sv/biginteger/divgnu64.c @@ -70,9 +70,9 @@ void biglsh(unsigned s, unsigned vn[], unsigned const v[], int n) vn[0] = v[0] << s; } -long bigdiv(unsigned v, unsigned q[], unsigned const u[], int m) +unsigned long bigdiv(unsigned v, unsigned q[], unsigned const u[], int m) { - long long k = 0; // the case of a + unsigned long long k = 0; // the case of a for (int j = m - 1; j >= 0; j--) { // single-digit unsigned long d2 = (k << 32) | u[j]; @@ -168,7 +168,6 @@ int divmnu(unsigned q[], unsigned r[], const unsigned u[], const unsigned v[], unsigned *un, *vn; // Normalized form of u, v. unsigned long long qhat; // Estimated quotient digit. unsigned long long rhat; // A remainder. - long long k; int s, j; if (m < n || n <= 0 || v[n - 1] == 0) @@ -176,7 +175,7 @@ int divmnu(unsigned q[], unsigned r[], const unsigned u[], const unsigned v[], if (n == 1) { // Take care of - k = bigdiv(v[0], q, u, m); + unsigned long k = bigdiv(v[0], q, u, m); if (r != NULL) r[0] = k; return 0; diff --git a/openpower/sv/biginteger/divmnu64.c b/openpower/sv/biginteger/divmnu64.c index 330e06d1a..10b05d5ab 100644 --- a/openpower/sv/biginteger/divmnu64.c +++ b/openpower/sv/biginteger/divmnu64.c @@ -207,7 +207,7 @@ int divmnu(unsigned q[], unsigned r[], const unsigned u[], const unsigned v[], { // rhat can be bigger than 32-bit when the division overflows, // so rhat's computation can't be folded into divrem_64_by_32 - rhat = dig2 - qr.q * vn[n - 1]; + rhat = dig2 - (uint64_t)qr.q * vn[n - 1]; } again: // use 3rd-from-top digit to obtain better accuracy -- 2.30.2