all: improve C++ static analyzers

This commit is contained in:
Markus F.X.J. Oberhumer 2023-07-26 22:28:47 +02:00
parent 5a1203be0d
commit 053e95033f
24 changed files with 107 additions and 46 deletions

View File

@ -1,6 +1,24 @@
# for clang-tidy-16 from https://clang.llvm.org/extra/clang-tidy/
---
Checks: 'bugprone-exception-*,clang-analyzer-*,-clang-analyzer-optin.performance.Padding,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-analyzer-security.insecureAPI.strcpy,clang-diagnostics-*'
Checks: >
-*,
bugprone-*,
-bugprone-assignment-in-if-condition,
-bugprone-branch-clone,
-bugprone-easily-swappable-parameters,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-macro-parentheses,
-bugprone-narrowing-conversions,
-bugprone-reserved-identifier,
-bugprone-sizeof-expression,
-bugprone-suspicious-include,
-bugprone-suspicious-memory-comparison,
-bugprone-suspicious-string-compare,
clang-analyzer-*,
-clang-analyzer-optin.performance.Padding,
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
-clang-analyzer-security.insecureAPI.strcpy,
clang-diagnostics-*',
FormatStyle: file
HeaderFilterRegex: '.*'
...

View File

@ -12,8 +12,8 @@ env:
CMAKE_REQUIRED_QUIET: OFF
DEBIAN_FRONTEND: noninteractive
UPX_CMAKE_BUILD_FLAGS: --verbose
# 2023-07-25
ZIG_DIST_VERSION: 0.11.0-dev.4228+aea29afc4
# 2023-07-26
ZIG_DIST_VERSION: 0.11.0-dev.4246+71dfce31b
jobs:
job-rebuild-and-verify-stubs:
@ -390,6 +390,7 @@ jobs:
# { zig_target: aarch64-macos.13.0-none }
- { zig_target: aarch64-windows-gnu }
- { zig_target: arm-linux-musleabihf }
# { zig_target: arm-linux-musleabihf, zig_pic: -fPIE }
# { zig_target: i386-linux-musl }
- { zig_target: i386-windows-gnu }
# { zig_target: mips-linux-musl }

View File

@ -23,8 +23,8 @@ jobs:
run: |
git clone --branch "$GITHUB_REF_NAME" --depth 1 https://github.com/upx/upx
git -C upx submodule update --init
- name: 'Perform clang scan-build Analysis Debug'
run: 'make -C upx build/extra/scan-build/debug'
- name: 'Perform clang scan-build Analysis Release'
- name: 'Perform clang-analyzer scan-build Analysis Debug'
run: 'make -C upx build/analyze/clang-analyzer/debug'
- name: 'Perform clang-analyzer scan-build Analysis Release'
if: success() || failure() # run this step even if the previous step failed
run: 'make -C upx build/extra/scan-build/release'
run: 'make -C upx build/analyze/clang-analyzer/release'

View File

@ -24,11 +24,7 @@ jobs:
git clone --branch "$GITHUB_REF_NAME" --depth 1 https://github.com/upx/upx
git -C upx submodule update --init
- name: 'Perform clang-tidy Analysis Debug'
run: |
make -C upx build/extra/clang/debug
python3 upx/misc/scripts/run-clang-tidy.py -p upx/build/extra/clang/debug
run: 'make -C upx build/analyze/clang-tidy/debug'
- name: 'Perform clang-tidy Analysis Release'
if: success() || failure() # run this step even if the previous step failed
run: |
make -C upx build/extra/clang/release
python3 upx/misc/scripts/run-clang-tidy.py -p upx/build/extra/clang/release
run: 'make -C upx build/analyze/clang-tidy/release'

View File

@ -8,8 +8,8 @@ on:
env:
CMAKE_REQUIRED_QUIET: OFF
DEBIAN_FRONTEND: noninteractive
# 2023-07-25
ZIG_DIST_VERSION: 0.11.0-dev.4228+aea29afc4
# 2023-07-26
ZIG_DIST_VERSION: 0.11.0-dev.4246+71dfce31b
jobs:
job-linux-zigcc: # uses cmake + make
@ -28,6 +28,7 @@ jobs:
- { zig_target: aarch64-macos.13.0-none }
- { zig_target: aarch64-windows-gnu }
- { zig_target: arm-linux-musleabihf }
- { zig_target: arm-linux-musleabihf, zig_pic: -fPIE }
- { zig_target: i386-linux-musl }
- { zig_target: i386-windows-gnu }
- { zig_target: mips-linux-musl }

View File

@ -123,24 +123,17 @@ build/extra/gcc-static/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/gcc-static/%: export CC = gcc -static
build/extra/gcc-static/%: export CXX = g++ -static
# force building with clang Static Analyzer (scan-build)
build/extra/scan-build/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/scan-build/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/scan-build/%: CMAKE := scan-build $(CMAKE)
build/extra/scan-build/%: export CCC_CC ?= clang
build/extra/scan-build/%: export CCC_CXX ?= clang++
# cross compiler: Linux glibc aarch64-linux-gnu (arm64)
build/extra/cross-linux-aarch64/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/cross-linux-aarch64/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/cross-linux-aarch64/%: export CC = aarch64-linux-gnu-gcc
build/extra/cross-linux-aarch64/%: export CXX = aarch64-linux-gnu-g++
build/extra/cross-linux-gnu-aarch64/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/cross-linux-gnu-aarch64/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/cross-linux-gnu-aarch64/%: export CC = aarch64-linux-gnu-gcc
build/extra/cross-linux-gnu-aarch64/%: export CXX = aarch64-linux-gnu-g++
# cross compiler: Linux glibc arm-linux-gnueabihf
build/extra/cross-linux-arm/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/cross-linux-arm/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/cross-linux-arm/%: export CC = arm-linux-gnueabihf-gcc
build/extra/cross-linux-arm/%: export CXX = arm-linux-gnueabihf-g++ -Wno-psabi
build/extra/cross-linux-gnu-arm-eabihf/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/extra/cross-linux-gnu-arm-eabihf/release: PHONY; $(call run_config_and_build,$@,Release)
build/extra/cross-linux-gnu-arm-eabihf/%: export CC = arm-linux-gnueabihf-gcc
build/extra/cross-linux-gnu-arm-eabihf/%: export CXX = arm-linux-gnueabihf-g++ -Wno-psabi
# cross compiler: Windows x86 win32 MinGW (i386)
build/extra/cross-windows-mingw32/debug: PHONY; $(call run_config_and_build,$@,Debug)
@ -166,6 +159,27 @@ build/extra/cross-darwin-x86_64/release: PHONY; $(call run_config_and_build,$@,R
build/extra/cross-darwin-x86_64/%: export CC = clang -target x86_64-apple-darwin
build/extra/cross-darwin-x86_64/%: export CXX = clang++ -target x86_64-apple-darwin
#***********************************************************************
# C++ static analyzers
#***********************************************************************
# force building with clang Static Analyzer (scan-build)
build/analyze/clang-analyzer/debug: PHONY; $(call run_config_and_build,$@,Debug)
build/analyze/clang-analyzer/release: PHONY; $(call run_config_and_build,$@,Release)
build/analyze/clang-analyzer/%: CMAKE := scan-build $(CMAKE)
build/analyze/clang-analyzer/%: export CCC_CC ?= clang
build/analyze/clang-analyzer/%: export CCC_CXX ?= clang++
# run clang-tidy (uses file compile_commands.json from an existing clang build)
build/analyze/clang-tidy/debug: build/extra/clang/debug PHONY
python3 ./misc/scripts/run-clang-tidy.py -p $<
build/analyze/clang-tidy/release: build/extra/clang/release PHONY
python3 ./misc/scripts/run-clang-tidy.py -p $<
# OLD names
build/extra/scan-build/debug: build/analyze/clang-analyzer/debug
build/extra/scan-build/release: build/analyze/clang-analyzer/release
#***********************************************************************
# advanced: generic extra target
#***********************************************************************

View File

@ -6,7 +6,7 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
# create the image from Dockerfile
# using a rootless Podman container
image=upx-test-qemu2-alpine-20230708-v1
image=upx-test-qemu2-alpine-20230725-v1
[[ $1 == --print-image ]] && echo "$image" && exit 0
podman build --squash -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"

View File

@ -3,6 +3,7 @@ FROM docker.io/library/alpine:3.8
# install qemu-2.12.0-r3 and some utils
RUN apk update && apk upgrade && apk add \
bash-completion \
coreutils \
musl-dbg \
qemu-aarch64 \
qemu-aarch64_be \
@ -18,8 +19,11 @@ RUN apk update && apk upgrade && apk add \
qemu-riscv32 \
qemu-riscv64 \
qemu-s390x \
qemu-sh4 \
qemu-sh4eb \
qemu-x86_64 \
strace \
zsh \
&& true
# create default user upx:upx 2000:2000

View File

@ -6,7 +6,7 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
# create the image from Dockerfile
# using a rootless Podman container
image=upx-test-qemu3-alpine-20230708-v1
image=upx-test-qemu3-alpine-20230725-v1
[[ $1 == --print-image ]] && echo "$image" && exit 0
podman build --squash -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"

View File

@ -3,6 +3,7 @@ FROM docker.io/library/alpine:3.9
# install qemu-3.1.0-r3 and some utils
RUN apk update && apk upgrade && apk add \
bash-completion \
coreutils \
musl-dbg \
qemu-aarch64 \
qemu-aarch64_be \
@ -18,8 +19,11 @@ RUN apk update && apk upgrade && apk add \
qemu-riscv32 \
qemu-riscv64 \
qemu-s390x \
qemu-sh4 \
qemu-sh4eb \
qemu-x86_64 \
strace \
zsh \
&& true
# create default user upx:upx 2000:2000

View File

@ -6,7 +6,7 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
# create the image from Dockerfile
# using a rootless Podman container
image=upx-test-qemu4-alpine-20230708-v1
image=upx-test-qemu4-alpine-20230725-v1
[[ $1 == --print-image ]] && echo "$image" && exit 0
podman build --squash -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"

View File

@ -3,6 +3,7 @@ FROM docker.io/library/alpine:3.11
# install qemu-4.2.0-r0 and some utils
RUN apk update && apk upgrade && apk add \
bash-completion \
coreutils \
musl-dbg \
qemu-aarch64 \
qemu-aarch64_be \
@ -18,8 +19,11 @@ RUN apk update && apk upgrade && apk add \
qemu-riscv32 \
qemu-riscv64 \
qemu-s390x \
qemu-sh4 \
qemu-sh4eb \
qemu-x86_64 \
strace \
zsh \
&& true
# create default user upx:upx 2000:2000

View File

@ -6,7 +6,7 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
# create the image from Dockerfile
# using a rootless Podman container
image=upx-test-qemu5-alpine-20230708-v1
image=upx-test-qemu5-alpine-20230725-v1
[[ $1 == --print-image ]] && echo "$image" && exit 0
podman build --squash -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"

View File

@ -3,6 +3,7 @@ FROM docker.io/library/alpine:3.13
# install qemu-5.2.0-r3 and some utils
RUN apk update && apk upgrade && apk add \
bash-completion \
coreutils \
musl-dbg \
qemu-aarch64 \
qemu-aarch64_be \
@ -18,8 +19,11 @@ RUN apk update && apk upgrade && apk add \
qemu-riscv32 \
qemu-riscv64 \
qemu-s390x \
qemu-sh4 \
qemu-sh4eb \
qemu-x86_64 \
strace \
zsh \
&& true
# create default user upx:upx 2000:2000

View File

@ -6,7 +6,7 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
# create the image from Dockerfile
# using a rootless Podman container
image=upx-test-qemu6-alpine-20230708-v1
image=upx-test-qemu6-alpine-20230725-v1
[[ $1 == --print-image ]] && echo "$image" && exit 0
podman build --squash -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"

View File

@ -3,6 +3,7 @@ FROM docker.io/library/alpine:3.15
# install qemu-6.1.1-r0 and some utils
RUN apk update && apk upgrade && apk add \
bash-completion \
coreutils \
musl-dbg \
qemu-aarch64 \
qemu-aarch64_be \
@ -18,8 +19,11 @@ RUN apk update && apk upgrade && apk add \
qemu-riscv32 \
qemu-riscv64 \
qemu-s390x \
qemu-sh4 \
qemu-sh4eb \
qemu-x86_64 \
strace \
zsh \
&& true
# create default user upx:upx 2000:2000

View File

@ -6,7 +6,7 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
# create the image from Dockerfile
# using a rootless Podman container
image=upx-test-qemu7-alpine-20230708-v1
image=upx-test-qemu7-alpine-20230725-v1
[[ $1 == --print-image ]] && echo "$image" && exit 0
podman build --squash -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"

View File

@ -3,6 +3,7 @@ FROM docker.io/library/alpine:3.17
# install qemu-7.1.0-r7 and some utils
RUN apk update && apk upgrade && apk add \
bash-completion \
coreutils \
musl-dbg \
qemu-aarch64 \
qemu-aarch64_be \
@ -18,8 +19,11 @@ RUN apk update && apk upgrade && apk add \
qemu-riscv32 \
qemu-riscv64 \
qemu-s390x \
qemu-sh4 \
qemu-sh4eb \
qemu-x86_64 \
strace \
zsh \
&& true
# create default user upx:upx 2000:2000

View File

@ -6,7 +6,7 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
# create the image from Dockerfile
# using a rootless Podman container
image=upx-test-qemu8-alpine-20230708-v1
image=upx-test-qemu8-alpine-20230725-v1
[[ $1 == --print-image ]] && echo "$image" && exit 0
podman build --squash -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"

View File

@ -3,6 +3,7 @@ FROM docker.io/library/alpine:3.18
# install qemu-8.0.3-r1 and some utils
RUN apk update && apk upgrade && apk add \
bash-completion \
coreutils \
musl-dbg \
qemu-aarch64 \
qemu-aarch64_be \
@ -18,8 +19,11 @@ RUN apk update && apk upgrade && apk add \
qemu-riscv32 \
qemu-riscv64 \
qemu-s390x \
qemu-sh4 \
qemu-sh4eb \
qemu-x86_64 \
strace \
zsh \
&& true
# create default user upx:upx 2000:2000

View File

@ -66,8 +66,6 @@ static unsigned const EF_ARM_EABI_VER5 = 0x05000000;
/*offset 20*/ '.','s','h','s','t','r','t','a','b','\0'
};
// NOLINTBEGIN(clang-analyzer-*)
static unsigned
umin(unsigned a, unsigned b)
{
@ -1567,6 +1565,7 @@ PackLinuxElf64::buildLinuxLoader(
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "LZMA_ELF00,LZMA_DEC20,LZMA_DEC30");
}
len += snprintf(&sec[len], sizeof(sec) - len, ",%s", "EXP_TAIL,SO_TAIL,SO_MAIN");
(void)len;
addLoader(sec, nullptr);
relocateLoader();
{
@ -6746,7 +6745,7 @@ void PackLinuxElf32::un_DT_INIT(
}
}; break;
case Elf32_Dyn::DT_PLTGOT: { plt_va = dt_pltgot = val;}
case Elf32_Dyn::DT_PLTGOT: { plt_va = dt_pltgot = val; (void)dt_pltgot; }
// FALL THROUGH
case Elf32_Dyn::DT_PREINIT_ARRAY:
case Elf32_Dyn::DT_INIT_ARRAY:
@ -8527,6 +8526,4 @@ void PackLinuxElf::unpack(OutputFile * /*fo*/)
throwCantUnpack("internal error");
}
// NOLINTEND(clang-analyzer-*)
/* vim:set ts=4 sw=4 et: */

View File

@ -306,9 +306,13 @@ TEST_CASE("MemBuffer global overloads") {
mb.clear();
mb4.clear();
CHECK(memcmp(mb, "\x00", 1) == 0);
// NOLINTNEXTLINE(bugprone-unused-return-value)
CHECK_THROWS(memcmp(mb, "\x00\x00", 2));
// NOLINTNEXTLINE(bugprone-unused-return-value)
CHECK_THROWS(memcmp("\x00\x00", mb, 2));
// NOLINTNEXTLINE(bugprone-unused-return-value)
CHECK_THROWS(memcmp(mb, mb4, 2));
// NOLINTNEXTLINE(bugprone-unused-return-value)
CHECK_THROWS(memcmp(mb4, mb, 2));
CHECK_NOTHROW(memset(mb, 255, 1));
CHECK_THROWS(memset(mb, 254, 2));

View File

@ -265,7 +265,9 @@ void upx_memswap(void *a, void *b, size_t n) {
char *x = (char *) a;
char *y = (char *) b;
do {
char tmp = *x;
// strange clang-analyzer-15 false positive when compiling in Debug mode
// clang-analyzer-core.uninitialized.Assign
char tmp = *x; // NOLINT(*core.uninitialized.Assign) // bogus clang-analyzer warning
*x++ = *y;
*y++ = tmp;
} while (--n != 0);

View File

@ -150,9 +150,9 @@ using OwningPointer = T *;
#else
// simple class with just a number of no-ops
// also works: a simple class with just a number of no-ops
template <class T>
struct OwningPointer {
struct OwningPointer final {
static_assert(std::is_class_v<T>); // UPX convention
typedef typename std::add_lvalue_reference<T>::type reference;
typedef typename std::add_lvalue_reference<const T>::type const_reference;
@ -167,7 +167,7 @@ struct OwningPointer {
inline pointer operator->() noexcept { return ptr; }
inline const_pointer operator->() const noexcept { return ptr; }
};
// overload mem_clear()
// must overload mem_clear()
template <class T>
inline void mem_clear(OwningPointer<T> object) noexcept {
mem_clear((T *) object);