From 5cc33e5af71b9d499beb4fb5924d477997ecf9f7 Mon Sep 17 00:00:00 2001 From: John Regan Date: Thu, 7 Jul 2022 10:35:08 -0400 Subject: [PATCH] fix undefined behavior: left shift a negative integer C/C++ leaves left-shifting a negative integer up to the compiler implementation. On most platforms, left-shifting a negative integer is the same as casting to the unsigned equivalent, then casting back into the signed type. This replaces the left-shift with the mathematical equivalent and avoids the undefined behavior. Ideally this should be performed for any case of left-shifting a signed type, but this commit only covers cases picked up by the undefined behavior sanitizer. --- src/app/basicWavReader.cpp | 2 +- src/app/exhaleAppPch.cpp | 2 +- src/app/loudnessEstim.cpp | 2 +- src/lib/linearPrediction.cpp | 10 +++++----- src/lib/specGapFilling.cpp | 2 +- src/lib/tempAnalysis.cpp | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/app/basicWavReader.cpp b/src/app/basicWavReader.cpp index 595bdb5..007a3b7 100644 --- a/src/app/basicWavReader.cpp +++ b/src/app/basicWavReader.cpp @@ -277,7 +277,7 @@ unsigned BasicWavReader::readDataLnPcm16 (const int fileHandle, int32_t* frameBu for (unsigned i = read * chanCount; i > 0; i--) { - *(frameBuf++) = (int32_t) *(iBuf++) << 8; // * 2^8 + *(frameBuf++) = (int32_t) *(iBuf++) * (1 << 8); // * 2^8 } framesRead += read; } diff --git a/src/app/exhaleAppPch.cpp b/src/app/exhaleAppPch.cpp index 21d9ea0..e39411f 100644 --- a/src/app/exhaleAppPch.cpp +++ b/src/app/exhaleAppPch.cpp @@ -28,7 +28,7 @@ void eaExtrapolate (int32_t* const pcmBuffer, const uint16_t pcmOffset, // start for (uint16_t ch = 0; ch < numChannels; ch++) { int32_t* chPcmBuf = pcmBuffer + ch + (pcmOffset - (fadeIn ? 0 : 1)) * numChannels; - int32_t result32 = (pcmOffset == 0 ? 0 : *chPcmBuf << 8); // input is known to be 24-bit PCM + int32_t result32 = (pcmOffset == 0 ? 0 : *chPcmBuf * (1 << 8)); // input is known to be 24-bit PCM const int32_t s32 = result32 / size; for (uint16_t i = size; i > 0; i--) *(chPcmBuf += delta) = ((result32 -= s32) + 128) >> 8; diff --git a/src/app/loudnessEstim.cpp b/src/app/loudnessEstim.cpp index 9f74e39..4927ab6 100644 --- a/src/app/loudnessEstim.cpp +++ b/src/app/loudnessEstim.cpp @@ -80,7 +80,7 @@ uint32_t LoudnessEstimator::addNewPcmData (const unsigned samplesPerChannel) const int64_t pi = filtI[0] * i[0] + filtI[1] * i[1] + filtI[2] * i[2] + filtI[3] * i[3] - filtO[0] * o[0] - filtO[1] * o[1] - filtO[2] * o[2] - filtO[3] * o[3]; const int64_t to = (pi < 0 ? (1 << 28) - 1 : 0); // trunc. offset - const int32_t xi = (*(chSig++)) << 2; + const int32_t xi = (*(chSig++)) * (1 << 2); const int32_t yi = xi + int32_t ((pi + (xi == 0 ? to : (1 << 27))) >> 28); const uint32_t a = abs (xi >> 2); diff --git a/src/lib/linearPrediction.cpp b/src/lib/linearPrediction.cpp index a9b6f55..0359bcb 100644 --- a/src/lib/linearPrediction.cpp +++ b/src/lib/linearPrediction.cpp @@ -190,8 +190,8 @@ uint32_t LinearPredictor::calcParCorCoeffs (const int32_t* const anaSignal, cons for (p = s; p < nCoeffs; p++) { sampleHO = EN[p - s]; // use register? - EN[p - s] = (EN[p - s] << 9) + EP[p] * Ks; - EP[p] = (EP[p] << 9) + sampleHO * Ks; + EN[p - s] = (EN[p - s] * (1 << 9)) + EP[p] * Ks; + EP[p] = (EP[p] * (1 << 9)) + sampleHO * Ks; } if (s > 0 && EN[0] < 0) // EN wrap-around { @@ -255,11 +255,11 @@ uint8_t LinearPredictor::calcOptTnsCoeffs (short* const parCorCoeffs, int8_t* co } // determine direct-form filter damping factor - parCorCoeffs[0] <<= bitShift; + parCorCoeffs[0] *= 1 << bitShift; i = abs (parCorCoeffs[0]); for (s = 1; s < order; s++) { - parCorCoeffs[s] <<= bitShift; // scale coeff + parCorCoeffs[s] *= 1 << bitShift; // scale coeff i = __max (i, abs (parCorCoeffs[s])); } for (/*s*/; s < MAX_PREDICTION_ORDER; s++) @@ -343,7 +343,7 @@ unsigned LinearPredictor::lpToParCorCoeffs (/*mod!*/short* const lpCoeffs, const } for (p = 0; p < s; p++) { - lpCoeffs[p] = short ((o + ((int) lpCoeffs[p] << shift) - intBuf[p] * i) / d); + lpCoeffs[p] = short ((o + ((int) lpCoeffs[p] * (1 << shift)) - intBuf[p] * i) / d); } } parCorCoeffs[0] = lpCoeffs[0]; diff --git a/src/lib/specGapFilling.cpp b/src/lib/specGapFilling.cpp index 8f17cc7..48a8413 100644 --- a/src/lib/specGapFilling.cpp +++ b/src/lib/specGapFilling.cpp @@ -268,7 +268,7 @@ uint8_t SpecGapFiller::getSpecGapFillParams (const SfbQuantizer& sfbQuantizer, c { unsigned countOld = 0, countNew = 0; - b = CLIP_PM (((b << 8) + (a >> 1)) / a, SHRT_MAX); + b = CLIP_PM (((b * (1 << 8)) + (a >> 1)) / a, SHRT_MAX); a = ((ySum << 8) - b * xSum + (size >> 1)) / size; ySum = grpScFacs[start]; diff --git a/src/lib/tempAnalysis.cpp b/src/lib/tempAnalysis.cpp index 7cbe0ed..24e5a90 100644 --- a/src/lib/tempAnalysis.cpp +++ b/src/lib/tempAnalysis.cpp @@ -210,7 +210,7 @@ unsigned TempAnalyzer::temporalAnalysis (const int32_t* const timeSignals[USAC_M for (int i = nSamplesInFrame >> sbrShift; i > 0; i--, lrSig++, hrSig += 2) { - int64_t r = ((int64_t) hrSig[0] << 17) + (hrSig[-1] + (int64_t) hrSig[1]) * -2*SHRT_MIN; + int64_t r = ((int64_t) hrSig[0] * (1 << 17)) + (hrSig[-1] + (int64_t) hrSig[1]) * -2*SHRT_MIN; int16_t s; for (u = 65, s = 129; u > 0; s -= 2) r += (hrSig[-s] + (int64_t) hrSig[s]) * lpfc12[--u]; @@ -222,7 +222,7 @@ unsigned TempAnalyzer::temporalAnalysis (const int32_t* const timeSignals[USAC_M if ((i & 1) != 0) // compute quarter-rate mid-frequency SBR signal { - r = ((3 * (int64_t) hrSig[0]) << 16) - (hrSig[-1] + (int64_t) hrSig[1]) * SHRT_MIN - r; + r = ((3 * (int64_t) hrSig[0]) * (1 << 16)) - (hrSig[-1] + (int64_t) hrSig[1]) * SHRT_MIN - r; r += (hrSig[-2] + (int64_t) hrSig[2]) * SHRT_MIN; for (s = 127; s > 0; s--/*u = s*/) r += (hrSig[-s] + (int64_t) hrSig[s]) * lpfc34[s];