From f6b31bf0d082315103d2fb5fc8f2094be567bb63 Mon Sep 17 00:00:00 2001 From: Yann Collet Date: Sat, 30 Sep 2017 10:35:55 -0700 Subject: fix #404 static analyzer `cppcheck` complains about a shift-by-32 on a 32 bits value, which is an undefined behavior. However, the flagged code path is never triggered in 32-bits mode, (actually, it's not even generated if DCE kicks in), the shift-by-32 is necessarily performed on a 64-bits value. While it doesn't change anything regarding lz4 code generation, for both 32 and 64 bits mode, (can be checked by md5sum on the generated binary), the shift has been rewritten in a way which should please this static analyzer, since it now pretends to shift by 16 on 32-bits cpu (note : it doesn't matter since the code will not even be generated in this case). Note : this is a blind fix, the new code has not been tested with cppcheck, because cppcheck only works on Windows. Other static analyzer, such as scan-build, do not trigger this false positive. --- lib/lz4.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/lz4.c b/lib/lz4.c index 707b94c..19967f2 100644 --- a/lib/lz4.c +++ b/lib/lz4.c @@ -334,7 +334,7 @@ static unsigned LZ4_NbCommonBytes (register reg_t val) # endif } } else /* Big Endian CPU */ { - if (sizeof(val)==8) { + if (sizeof(val)==8) { /* 64-bits */ # if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) unsigned long r = 0; _BitScanReverse64( &r, val ); @@ -342,8 +342,11 @@ static unsigned LZ4_NbCommonBytes (register reg_t val) # elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) return (__builtin_clzll((U64)val) >> 3); # else + static const U32 by32 = sizeof(val)*4; /* 32 on 64 bits (goal), 16 on 32 bits. + Just to avoid some static analyzer complaining about shift by 32 on 32-bits target. + Note that this code path is never triggered in 32-bits mode. */ unsigned r; - if (!(val>>32)) { r=4; } else { r=0; val>>=32; } + if (!(val>>by32)) { r=4; } else { r=0; val>>=by32; } if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } r += (!val); return r; -- cgit v0.12