From 01a02d36b51c2714f850f98aa1d0e9e33ec6fbd9 Mon Sep 17 00:00:00 2001 From: Teresa Johnson Date: Thu, 8 Oct 2015 13:14:59 +0000 Subject: [PATCH] Fix UBSan test error from r248897 about left shift of unsigned value. Fixed by masking off the upper bits that we are shifting off before doing the left shift. llvm-svn: 249689 --- llvm/include/llvm/Support/Endian.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/Support/Endian.h b/llvm/include/llvm/Support/Endian.h index b72200e7ba46..7680240deac8 100644 --- a/llvm/include/llvm/Support/Endian.h +++ b/llvm/include/llvm/Support/Endian.h @@ -131,14 +131,22 @@ inline void writeAtBitAlignment(void *memory, value_type value, // Mask off any existing bits in the upper part of the lower value that // we want to replace. val[0] &= (1 << startBit) - 1; - // Now shift in the new bits - val[0] |= value << startBit; + unsigned numBitsFirstVal = (sizeof(value_type) * 8) - startBit; + unsigned lowerVal = value; + if (startBit > 0) { + // Mask off the upper bits in the new value that are not going to go into + // the lower value. This avoids a left shift of a negative value, which + // is undefined behavior. + lowerVal &= ((1 << numBitsFirstVal) - 1); + // Now shift the new bits into place + lowerVal <<= startBit; + } + val[0] |= lowerVal; // Mask off any existing bits in the lower part of the upper value that // we want to replace. val[1] &= ~((1 << startBit) - 1); // Next shift the bits that go into the upper value into position. - unsigned numBitsFirstVal = (sizeof(value_type) * 8) - startBit; unsigned upperVal = value >> numBitsFirstVal; // Mask off upper bits after right shift in case of signed type. upperVal &= (1 << startBit) - 1;