mirror of
https://github.com/upx/upx.git
synced 2025-08-11 22:52:30 +08:00
all: cleanups
This commit is contained in:
18
.github/workflows/ci.yml
vendored
18
.github/workflows/ci.yml
vendored
@ -131,7 +131,7 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- { os: macos-11, gcc: gcc-10, gxx: 'g++-10', testsuite: true }
|
- { os: macos-11, gcc: gcc-10, gxx: 'g++-10', testsuite: true }
|
||||||
# { os: macos-12, gcc: gcc-11, gxx: 'g++-11', testsuite: true } # disable gcc - XCode 14.0 ld bug; supposed to be fixed in 14.1
|
# { os: macos-12, gcc: gcc-11, gxx: 'g++-11', testsuite: true } # disable gcc - XCode 14.0.1 ld bug; supposed to be fixed in 14.1
|
||||||
- { os: macos-12, testsuite: true }
|
- { os: macos-12, testsuite: true }
|
||||||
steps:
|
steps:
|
||||||
- name: 'Install brew packages'
|
- name: 'Install brew packages'
|
||||||
@ -245,10 +245,12 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- { name: amd64-win64-msvc-14.2, os: windows-2019, C: msvc-14.2-x64, A: x64 } # Visual Studio 2019
|
- { name: amd64-win64-vs2019, os: windows-2019, C: msvc-14.2-x64, arch: amd64 }
|
||||||
- { name: amd64-win64-msvc-14.3, os: windows-2022, C: msvc-14.3-x64, A: x64 } # Visual Studio 2022
|
- { name: amd64-win64-vs2022, os: windows-2022, C: msvc-14.3-x64, arch: amd64 }
|
||||||
- { name: i386-win32-msvc-14.2, os: windows-2019, C: msvc-14.2-x86, A: x86 } # Visual Studio 2019
|
- { name: arm64-win64-vs2019, os: windows-2019, C: msvc-14.2-x64, arch: amd64_arm64 }
|
||||||
- { name: i386-win32-msvc-14.3, os: windows-2022, C: msvc-14.3-x86, A: x86 } # Visual Studio 2022
|
- { name: arm64-win64-vs2022, os: windows-2022, C: msvc-14.3-x64, arch: amd64_arm64 }
|
||||||
|
- { name: i386-win32-vs2019, os: windows-2019, C: msvc-14.2-x86, arch: amd64_x86 }
|
||||||
|
- { name: i386-win32-vs2022, os: windows-2022, C: msvc-14.3-x86, arch: amd64_x86 }
|
||||||
steps:
|
steps:
|
||||||
- name: 'Check out code'
|
- name: 'Check out code'
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
@ -263,7 +265,7 @@ jobs:
|
|||||||
- name: 'Set up Developer Command Prompt'
|
- name: 'Set up Developer Command Prompt'
|
||||||
uses: ilammy/msvc-dev-cmd@v1
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
with:
|
with:
|
||||||
arch: ${{ matrix.A }}
|
arch: ${{ matrix.arch }}
|
||||||
- name: 'Build'
|
- name: 'Build'
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
@ -291,7 +293,7 @@ jobs:
|
|||||||
set s=%H%\src
|
set s=%H%\src
|
||||||
cat .GITREV.txt
|
cat .GITREV.txt
|
||||||
set /p GITREV=<.GITREV.txt
|
set /p GITREV=<.GITREV.txt
|
||||||
cl -std:c++17 -Zc:__cplusplus -EHsc -J -O2 -W4 -WX -DUPX_VERSION_GITREV="""%GITREV%""" -DWITH_ZSTD %DEFS% -I%H%\vendor -I%H%\vendor\boost-pfr\include -Feupx.exe %s%\*.cpp %s%\util\*.cpp %BDIR%\ucl\ucl.lib %BDIR%\zlib\zlib.lib %BDIR%\zstd\zstd.lib /link setargv.obj
|
cl -std:c++17 -Zc:__cplusplus -EHsc -J -O2 -W4 -WX -DUPX_VERSION_GITREV="""%GITREV%""" -DWITH_ZSTD %DEFS% -I%H%\vendor -I%H%\vendor\boost-pfr\include -Feupx.exe %s%\*.cpp %s%\check\*.cpp %s%\util\*.cpp %BDIR%\ucl\ucl.lib %BDIR%\zlib\zlib.lib %BDIR%\zstd\zstd.lib /link setargv.obj
|
||||||
- name: 'Make artifact'
|
- name: 'Make artifact'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@ -306,6 +308,7 @@ jobs:
|
|||||||
name: ${{ env.artifact_name }}
|
name: ${{ env.artifact_name }}
|
||||||
path: tmp/artifact
|
path: tmp/artifact
|
||||||
- name: 'Run basic tests'
|
- name: 'Run basic tests'
|
||||||
|
if: ${{ matrix.arch != 'amd64_arm64' }}
|
||||||
run: |
|
run: |
|
||||||
$ErrorActionPreference = 'stop'
|
$ErrorActionPreference = 'stop'
|
||||||
$ErrorView = 'NormalView'
|
$ErrorView = 'NormalView'
|
||||||
@ -318,6 +321,7 @@ jobs:
|
|||||||
.\upx.exe -t upx_packed.exe
|
.\upx.exe -t upx_packed.exe
|
||||||
.\upx_packed.exe --version
|
.\upx_packed.exe --version
|
||||||
- name: 'Run test suite'
|
- name: 'Run test suite'
|
||||||
|
if: ${{ matrix.arch != 'amd64_arm64' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
export upx_testsuite_SRCDIR="$(readlink -en ../deps/upx-testsuite)"
|
export upx_testsuite_SRCDIR="$(readlink -en ../deps/upx-testsuite)"
|
||||||
|
10
.github/workflows/codeql-analysis.yml
vendored
10
.github/workflows/codeql-analysis.yml
vendored
@ -1,11 +1,11 @@
|
|||||||
name: "CodeQL"
|
name: "CodeQL"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
# push:
|
||||||
branches: [ "devel", "devel4", "devel5", "master" ]
|
# branches: [ "devel", "devel4", "devel5", "master" ]
|
||||||
pull_request:
|
# pull_request:
|
||||||
# The branches below must be a subset of the branches above
|
# # The branches below must be a subset of the branches above
|
||||||
branches: [ "devel", "devel4", "devel5" ]
|
# branches: [ "devel", "devel4", "devel5" ]
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '20 1 * * 3'
|
- cron: '20 1 * * 3'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
@ -6,14 +6,12 @@ if(NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git")
|
|||||||
option(UPX_CONFIG_DISABLE_GITREV "Do not compile with default Git version info." ON)
|
option(UPX_CONFIG_DISABLE_GITREV "Do not compile with default Git version info." ON)
|
||||||
option(UPX_CONFIG_DISABLE_SANITIZE "Do not compile with default sanitize options." ON)
|
option(UPX_CONFIG_DISABLE_SANITIZE "Do not compile with default sanitize options." ON)
|
||||||
option(UPX_CONFIG_DISABLE_WERROR "Do not compile with default -Werror option." ON)
|
option(UPX_CONFIG_DISABLE_WERROR "Do not compile with default -Werror option." ON)
|
||||||
option(UPX_CONFIG_DISABLE_ZSTD "Do not compile with zstd; NOTE: zstd is WIP." ON)
|
|
||||||
else()
|
else()
|
||||||
# strict config defaults for devel builds
|
# strict config defaults for devel builds
|
||||||
message(STATUS "upx info: strict config defaults enabled")
|
message(STATUS "upx info: strict config defaults enabled")
|
||||||
option(UPX_CONFIG_DISABLE_GITREV "Do not compile with default Git version info." OFF)
|
option(UPX_CONFIG_DISABLE_GITREV "Do not compile with default Git version info." OFF)
|
||||||
option(UPX_CONFIG_DISABLE_SANITIZE "Do not compile with default sanitize options." OFF)
|
option(UPX_CONFIG_DISABLE_SANITIZE "Do not compile with default sanitize options." OFF)
|
||||||
option(UPX_CONFIG_DISABLE_WERROR "Do not compile with default -Werror option." OFF)
|
option(UPX_CONFIG_DISABLE_WERROR "Do not compile with default -Werror option." OFF)
|
||||||
option(UPX_CONFIG_DISABLE_ZSTD "Do not compile with zstd; NOTE: zstd is WIP." OFF)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# test config options (see below)
|
# test config options (see below)
|
||||||
@ -42,7 +40,7 @@ set(GITREV_SHORT "")
|
|||||||
set(GITREV_PLUS "")
|
set(GITREV_PLUS "")
|
||||||
set(GIT_DESCRIBE "")
|
set(GIT_DESCRIBE "")
|
||||||
find_package(Git)
|
find_package(Git)
|
||||||
if(GIT_FOUND AND NOT UPX_CONFIG_DISABLE_GITREV)
|
if(Git_FOUND AND NOT UPX_CONFIG_DISABLE_GITREV)
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND "${GIT_EXECUTABLE}" rev-parse --short=12 HEAD
|
COMMAND "${GIT_EXECUTABLE}" rev-parse --short=12 HEAD
|
||||||
RESULT_VARIABLE result ERROR_QUIET
|
RESULT_VARIABLE result ERROR_QUIET
|
||||||
@ -101,6 +99,10 @@ endif()
|
|||||||
# targets and compilation flags
|
# targets and compilation flags
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
|
|
||||||
|
#find_package(Threads)
|
||||||
|
|
||||||
|
set(UPX_CONFIG_DISABLE_ZSTD ON) # zstd is currently not used; maybe in UPX version 5
|
||||||
|
|
||||||
file(GLOB ucl_SOURCES "vendor/ucl/src/*.c")
|
file(GLOB ucl_SOURCES "vendor/ucl/src/*.c")
|
||||||
list(SORT ucl_SOURCES)
|
list(SORT ucl_SOURCES)
|
||||||
add_library(upx_vendor_ucl STATIC ${ucl_SOURCES})
|
add_library(upx_vendor_ucl STATIC ${ucl_SOURCES})
|
||||||
@ -118,7 +120,7 @@ add_library(upx_vendor_zstd STATIC ${zstd_SOURCES})
|
|||||||
set_property(TARGET upx_vendor_zstd PROPERTY C_STANDARD 11)
|
set_property(TARGET upx_vendor_zstd PROPERTY C_STANDARD 11)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
file(GLOB upx_SOURCES "src/*.cpp" "src/util/*.cpp")
|
file(GLOB upx_SOURCES "src/*.cpp" "src/check/*.cpp" "src/util/*.cpp")
|
||||||
list(SORT upx_SOURCES)
|
list(SORT upx_SOURCES)
|
||||||
add_executable(upx ${upx_SOURCES})
|
add_executable(upx ${upx_SOURCES})
|
||||||
#target_compile_features(upx PRIVATE cxx_std_17)
|
#target_compile_features(upx PRIVATE cxx_std_17)
|
||||||
@ -223,6 +225,10 @@ if(NOT UPX_CONFIG_DISABLE_ZSTD)
|
|||||||
target_compile_definitions(${t} PRIVATE WITH_ZSTD=1)
|
target_compile_definitions(${t} PRIVATE WITH_ZSTD=1)
|
||||||
target_link_libraries(upx upx_vendor_zstd)
|
target_link_libraries(upx upx_vendor_zstd)
|
||||||
endif()
|
endif()
|
||||||
|
if(Threads_FOUND AND 0)
|
||||||
|
# for RANGELESS_FN_ENABLE_PARALLEL multithreading test
|
||||||
|
target_link_libraries(upx Threads::Threads)
|
||||||
|
endif()
|
||||||
|
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
# "make test"
|
# "make test"
|
||||||
|
3
Makefile
3
Makefile
@ -141,6 +141,9 @@ endif
|
|||||||
ifeq ($(wildcard ./vendor/lzma-sdk/C/.),)
|
ifeq ($(wildcard ./vendor/lzma-sdk/C/.),)
|
||||||
$(error ERROR: missing git submodule; run 'git submodule update --init')
|
$(error ERROR: missing git submodule; run 'git submodule update --init')
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(wildcard ./vendor/rangeless/include/.),)
|
||||||
|
$(error ERROR: missing git submodule; run 'git submodule update --init')
|
||||||
|
endif
|
||||||
ifeq ($(wildcard ./vendor/ucl/include/.),)
|
ifeq ($(wildcard ./vendor/ucl/include/.),)
|
||||||
$(error ERROR: missing git submodule; run 'git submodule update --init')
|
$(error ERROR: missing git submodule; run 'git submodule update --init')
|
||||||
endif
|
endif
|
||||||
|
@ -6,10 +6,10 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
|
|||||||
# create the image from Dockerfile
|
# create the image from Dockerfile
|
||||||
# using a rootless Podman container
|
# using a rootless Podman container
|
||||||
|
|
||||||
# NOTE: this image is based on rebuild-stubs-with-upx/upx-stubtools-20221212-v2,
|
# NOTE: this image is based on rebuild-stubs-with-upx/upx-stubtools-20221212-v3,
|
||||||
# so you have to create that image first
|
# so you have to create that image first
|
||||||
# WARNING: we install many packages, so the resulting image needs A LOT of disk space!
|
# WARNING: we install many packages, so the resulting image needs A LOT of disk space!
|
||||||
image=upx-cross-compile-20221212-v2
|
image=upx-cross-compile-20230115-v1
|
||||||
|
|
||||||
podman build -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"
|
podman build -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
|
|||||||
# run an interactive shell in the image
|
# run an interactive shell in the image
|
||||||
# using a rootless Podman container
|
# using a rootless Podman container
|
||||||
|
|
||||||
image=upx-cross-compile-20221212-v2
|
image=upx-cross-compile-20230115-v1
|
||||||
|
|
||||||
flags=( -ti --read-only --rm )
|
flags=( -ti --read-only --rm )
|
||||||
flags+=( --cap-drop=all ) # drop all capabilities
|
flags+=( --cap-drop=all ) # drop all capabilities
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# NOTE: this image is based on rebuild-stubs-with-upx/upx-stubtools-20221212-v2,
|
# NOTE: this image is based on rebuild-stubs-with-upx/upx-stubtools-20221212-v3,
|
||||||
# so you have to create that image first
|
# so you have to create that image first
|
||||||
# WARNING: we install many packages, so the resulting image needs A LOT of disk space!
|
# WARNING: we install many packages, so the resulting image needs A LOT of disk space!
|
||||||
FROM localhost/upx-stubtools-20221212-v2
|
FROM localhost/upx-stubtools-20221212-v3
|
||||||
ENV UPX_CONTAINER_IMAGE_NAME=upx-cross-compile-20221212-v2
|
ENV UPX_CONTAINER_IMAGE_NAME=upx-cross-compile-20230115-v1
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
|
@ -6,7 +6,7 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
|
|||||||
# create the image from Dockerfile
|
# create the image from Dockerfile
|
||||||
# using a rootless Podman container
|
# using a rootless Podman container
|
||||||
|
|
||||||
image=upx-stubtools-20221212-v2
|
image=upx-stubtools-20221212-v3
|
||||||
|
|
||||||
podman build -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"
|
podman build -t "$image" -f "$argv0dir/Dockerfile" "$argv0dir"
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ argv0=$0; argv0abs="$(readlink -fn "$argv0")"; argv0dir="$(dirname "$argv0abs")"
|
|||||||
# run an interactive shell in the image
|
# run an interactive shell in the image
|
||||||
# using a rootless Podman container
|
# using a rootless Podman container
|
||||||
|
|
||||||
image=upx-stubtools-20221212-v2
|
image=upx-stubtools-20221212-v3
|
||||||
|
|
||||||
flags=( -ti --read-only --rm )
|
flags=( -ti --read-only --rm )
|
||||||
flags+=( --cap-drop=all ) # drop all capabilities
|
flags+=( --cap-drop=all ) # drop all capabilities
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
FROM docker.io/library/ubuntu:22.04
|
FROM docker.io/library/ubuntu:22.04
|
||||||
ENV UPX_CONTAINER_IMAGE_NAME=upx-stubtools-20221212-v2
|
ENV UPX_CONTAINER_IMAGE_NAME=upx-stubtools-20221212-v3
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
ENV LANG=C.UTF-8
|
ENV LANG=C.UTF-8
|
||||||
|
|
||||||
@ -13,8 +13,9 @@ RUN dpkg --add-architecture i386 \
|
|||||||
# the following packages are not required for rebuilding the stubs, but
|
# the following packages are not required for rebuilding the stubs, but
|
||||||
# they do make the image much more convenient and also allow building
|
# they do make the image much more convenient and also allow building
|
||||||
# the full UPX binary inside the container via CMake:
|
# the full UPX binary inside the container via CMake:
|
||||||
7zip bzip2 cmake elfutils file g++ gdb htop libzstd-dev lzip lzop ninja-build \
|
7zip bfs bzip2 cmake elfutils fd-find file fzf g++ gdb htop hyperfine \
|
||||||
p7zip patch patchelf pax-utils rsync screen unzip vim zip zlib1g-dev zsh zstd \
|
libzstd-dev lzip lzop ninja-build p7zip patch patchelf pax-utils ripgrep \
|
||||||
|
rsync screen universal-ctags unzip vim zip zlib1g-dev zsh zstd \
|
||||||
# extra packages for compiling with "gcc -m32" and and "gcc -mx32":
|
# extra packages for compiling with "gcc -m32" and and "gcc -mx32":
|
||||||
gcc-multilib g++-multilib \
|
gcc-multilib g++-multilib \
|
||||||
&& true
|
&& true
|
||||||
|
@ -79,7 +79,7 @@ CLANG_FORMAT_EXCLUDE_FILES += conf.h miniacc.h version.h
|
|||||||
CLANG_FORMAT_EXCLUDE_FILES += compress.cpp compress.h filter.cpp filter.h filteri.cpp help.cpp
|
CLANG_FORMAT_EXCLUDE_FILES += compress.cpp compress.h filter.cpp filter.h filteri.cpp help.cpp
|
||||||
CLANG_FORMAT_EXCLUDE_FILES += p_elf.h p_elf_enum.h p_lx_% p_mach% p_unix% p_vmli%
|
CLANG_FORMAT_EXCLUDE_FILES += p_elf.h p_elf_enum.h p_lx_% p_mach% p_unix% p_vmli%
|
||||||
CLANG_FORMAT_EXCLUDE_FILES += p_w32pe.cpp p_w64pep.cpp packer_c.cpp packer_f.cpp pefile%
|
CLANG_FORMAT_EXCLUDE_FILES += p_w32pe.cpp p_w64pep.cpp packer_c.cpp packer_f.cpp pefile%
|
||||||
CLANG_FORMAT_FILES := $(sort $(wildcard *.[ch]* ../maint/src/*.[ch]* util/*.[ch]*))
|
CLANG_FORMAT_FILES := $(sort $(wildcard *.[ch]* ../maint/src/*.[ch]* check/*.[ch]* util/*.[ch]*))
|
||||||
CLANG_FORMAT_FILES := $(filter-out $(CLANG_FORMAT_EXCLUDE_FILES),$(CLANG_FORMAT_FILES))
|
CLANG_FORMAT_FILES := $(filter-out $(CLANG_FORMAT_EXCLUDE_FILES),$(CLANG_FORMAT_FILES))
|
||||||
clang-format: PHONY $(CLANG_FORMAT_FILES)
|
clang-format: PHONY $(CLANG_FORMAT_FILES)
|
||||||
@echo "running upx-clang-format"
|
@echo "running upx-clang-format"
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2023 Laszlo Molnar
|
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@ -21,15 +20,10 @@
|
|||||||
If not, write to the Free Software Foundation, Inc.,
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer
|
||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if DEBUG || 1
|
|
||||||
#ifndef WITH_BOOST_PFR
|
|
||||||
#define WITH_BOOST_PFR 1
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#include "../conf.h"
|
#include "../conf.h"
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
@ -138,8 +132,13 @@ namespace {
|
|||||||
template <class T>
|
template <class T>
|
||||||
struct TestBELE {
|
struct TestBELE {
|
||||||
__acc_static_noinline bool test(void) {
|
__acc_static_noinline bool test(void) {
|
||||||
COMPILE_TIME_ASSERT_ALIGNED1(T)
|
// POD checks
|
||||||
|
// COMPILE_TIME_ASSERT(std::is_pod<T>::value); // deprecated in C++20
|
||||||
|
COMPILE_TIME_ASSERT(std::is_standard_layout<T>::value);
|
||||||
|
COMPILE_TIME_ASSERT(std::is_trivial<T>::value);
|
||||||
|
// alignment checks
|
||||||
{
|
{
|
||||||
|
COMPILE_TIME_ASSERT_ALIGNED1(T)
|
||||||
struct alignas(1) test1_t {
|
struct alignas(1) test1_t {
|
||||||
char a;
|
char a;
|
||||||
T b;
|
T b;
|
||||||
@ -160,6 +159,7 @@ struct TestBELE {
|
|||||||
UNUSED(t2);
|
UNUSED(t2);
|
||||||
}
|
}
|
||||||
#if 1
|
#if 1
|
||||||
|
// arithmetic checks
|
||||||
{
|
{
|
||||||
T allbits;
|
T allbits;
|
||||||
allbits = 0;
|
allbits = 0;
|
||||||
@ -453,33 +453,4 @@ TEST_CASE("libc snprintf") {
|
|||||||
CHECK_EQ(strcmp(buf, "-7.0.0.0.0.0.0.0.7.0xffffffffffffffff"), 0);
|
CHECK_EQ(strcmp(buf, "-7.0.0.0.0.0.0.0.7.0xffffffffffffffff"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WITH_BOOST_PFR
|
|
||||||
TEST_CASE("Boost.PFR") {
|
|
||||||
int i = -1;
|
|
||||||
CHECK_EQ(strcmp(pfr_str(i), "-1"), 0);
|
|
||||||
BE32 b32;
|
|
||||||
b32 = 1;
|
|
||||||
LE32 l32;
|
|
||||||
l32 = 2;
|
|
||||||
CHECK_EQ(strcmp(pfr_str(b32), "1"), 0);
|
|
||||||
CHECK_EQ(strcmp(pfr_str(l32), "2"), 0);
|
|
||||||
struct Foo {
|
|
||||||
BE16 b16;
|
|
||||||
BE32 b32;
|
|
||||||
BE64 b64;
|
|
||||||
LE16 l16;
|
|
||||||
LE32 l32;
|
|
||||||
LE64 l64;
|
|
||||||
};
|
|
||||||
Foo foo;
|
|
||||||
foo.b16 = 1;
|
|
||||||
foo.b32 = 2;
|
|
||||||
foo.b64 = 3;
|
|
||||||
foo.l16 = 4;
|
|
||||||
foo.l32 = 5;
|
|
||||||
foo.l64 = 6;
|
|
||||||
CHECK_EQ(strcmp(pfr_str("foo", "=", foo), "foo = {1, 2, 3, 4, 5, 6}"), 0);
|
|
||||||
}
|
|
||||||
#endif // WITH_BOOST_PFR
|
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
@ -3,7 +3,6 @@
|
|||||||
This file is part of the UPX executable compressor.
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||||
Copyright (C) 1996-2023 Laszlo Molnar
|
|
||||||
All Rights Reserved.
|
All Rights Reserved.
|
||||||
|
|
||||||
UPX and the UCL library are free software; you can redistribute them
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
@ -21,8 +20,8 @@
|
|||||||
If not, write to the Free Software Foundation, Inc.,
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
Markus F.X.J. Oberhumer Laszlo Molnar
|
Markus F.X.J. Oberhumer
|
||||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
<markus@oberhumer.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
752
src/check/dt_xspan.cpp
Normal file
752
src/check/dt_xspan.cpp
Normal file
@ -0,0 +1,752 @@
|
|||||||
|
/* xspan -- a minimally invasive checked memory smart pointer
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer
|
||||||
|
<markus@oberhumer.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
// lots of tests (and probably quite a number of redundant tests)
|
||||||
|
|
||||||
|
#include "../conf.h"
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// basic
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
TEST_CASE("basic xspan usage") {
|
||||||
|
char buf[4] = {0, 1, 2, 3};
|
||||||
|
|
||||||
|
SUBCASE("SPAN_x") {
|
||||||
|
SPAN_0(char) a0 = nullptr;
|
||||||
|
|
||||||
|
SPAN_0(char) b0 = buf;
|
||||||
|
SPAN_P(char) bp = buf;
|
||||||
|
|
||||||
|
SPAN_0(char) c0 = SPAN_0_MAKE(char, buf);
|
||||||
|
SPAN_P(char) cp = SPAN_P_MAKE(char, buf);
|
||||||
|
SPAN_S(char) cs = SPAN_S_MAKE(char, buf, sizeof(buf));
|
||||||
|
|
||||||
|
SPAN_0(const char) const x0 = SPAN_0_MAKE(const char, buf);
|
||||||
|
SPAN_P(const char) const xp = SPAN_P_MAKE(const char, buf);
|
||||||
|
SPAN_S(const char) const xs = SPAN_S_MAKE(const char, buf, sizeof(buf));
|
||||||
|
SPAN_P(const char) const yp = xs;
|
||||||
|
SPAN_0(const char) const z0p = yp;
|
||||||
|
SPAN_0(const char) const z0s = xs;
|
||||||
|
|
||||||
|
CHECK((a0 == nullptr));
|
||||||
|
CHECK(c0 == b0);
|
||||||
|
CHECK(cp == bp);
|
||||||
|
CHECK(cs == bp);
|
||||||
|
CHECK(x0 == z0p);
|
||||||
|
CHECK(xp == z0s);
|
||||||
|
|
||||||
|
CHECK(raw_bytes(c0, 4) == buf);
|
||||||
|
CHECK(raw_index_bytes(c0, 1, 3) == buf + 1);
|
||||||
|
CHECK(raw_bytes(cp, 4) == buf);
|
||||||
|
CHECK(raw_index_bytes(cp, 1, 3) == buf + 1);
|
||||||
|
CHECK(raw_bytes(cs, 4) == buf);
|
||||||
|
CHECK(raw_index_bytes(cs, 1, 3) == buf + 1);
|
||||||
|
CHECK_THROWS(raw_bytes(cs, 5));
|
||||||
|
CHECK_THROWS(raw_index_bytes(cs, 1, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("SPAN_x_VAR") {
|
||||||
|
SPAN_0_VAR(char, a0, nullptr);
|
||||||
|
|
||||||
|
SPAN_0_VAR(char, b0, buf);
|
||||||
|
SPAN_P_VAR(char, bp, buf);
|
||||||
|
|
||||||
|
SPAN_0_VAR(char, c0, buf, sizeof(buf));
|
||||||
|
SPAN_P_VAR(char, cp, buf, sizeof(buf));
|
||||||
|
SPAN_S_VAR(char, cs, buf, sizeof(buf));
|
||||||
|
|
||||||
|
SPAN_0_VAR(char, d0, buf + 1, sizeof(buf), buf);
|
||||||
|
SPAN_P_VAR(char, dp, buf + 1, sizeof(buf), buf);
|
||||||
|
SPAN_S_VAR(char, ds, buf + 1, sizeof(buf), buf);
|
||||||
|
|
||||||
|
SPAN_0_VAR(const char, const x0, buf, sizeof(buf));
|
||||||
|
SPAN_P_VAR(const char, const xp, buf, sizeof(buf));
|
||||||
|
SPAN_S_VAR(const char, const xs, buf, sizeof(buf));
|
||||||
|
SPAN_P_VAR(const char, const yp, xs);
|
||||||
|
SPAN_0_VAR(const char, const z0p, yp);
|
||||||
|
SPAN_0_VAR(const char, const z0s, xs);
|
||||||
|
|
||||||
|
CHECK((a0 == nullptr));
|
||||||
|
CHECK(c0 == b0);
|
||||||
|
CHECK(cp == bp);
|
||||||
|
CHECK(cs == bp);
|
||||||
|
CHECK(d0 == dp);
|
||||||
|
CHECK(d0 == ds);
|
||||||
|
CHECK(x0 == z0p);
|
||||||
|
CHECK(xp == z0s);
|
||||||
|
|
||||||
|
CHECK(raw_bytes(c0, 4) == buf);
|
||||||
|
CHECK(raw_index_bytes(c0, 1, 3) == buf + 1);
|
||||||
|
CHECK(raw_bytes(cp, 4) == buf);
|
||||||
|
CHECK(raw_index_bytes(cp, 1, 3) == buf + 1);
|
||||||
|
CHECK(raw_bytes(cs, 4) == buf);
|
||||||
|
CHECK(raw_index_bytes(cs, 1, 3) == buf + 1);
|
||||||
|
CHECK_THROWS(raw_bytes(cs, 5));
|
||||||
|
CHECK_THROWS(raw_index_bytes(cs, 1, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
SUBCASE("xspan in class") {
|
||||||
|
struct MyType {
|
||||||
|
SPAN_0(char) s0;
|
||||||
|
SPAN_P(char) sp;
|
||||||
|
SPAN_S(char) ss;
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
SPAN_0(char) x0 = nullptr;
|
||||||
|
#endif
|
||||||
|
#if WITH_SPAN >= 2
|
||||||
|
// much nicer syntax when using fully checked xspan:
|
||||||
|
MyType(char *b, size_t n, bool) : s0(b, n), sp(b, n), ss(b, n) {}
|
||||||
|
#endif
|
||||||
|
MyType(char *b, size_t n)
|
||||||
|
: s0(SPAN_0_MAKE(char, b, n)), sp(SPAN_P_MAKE(char, b, n)),
|
||||||
|
ss(SPAN_S_MAKE(char, b, n)) {
|
||||||
|
UNUSED(n);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MyType x(buf, sizeof(buf));
|
||||||
|
MyType y = MyType(buf, sizeof(buf));
|
||||||
|
CHECK(x.s0 == y.sp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#if (WITH_SPAN >= 2) && DEBUG
|
||||||
|
|
||||||
|
TEST_CASE("PtrOrSpanOrNull") {
|
||||||
|
char real_buf[2 + 6 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 124, 125};
|
||||||
|
char *base_buf = real_buf + 2;
|
||||||
|
char *const my_null = nullptr;
|
||||||
|
typedef PtrOrSpanOrNull<char> Span0;
|
||||||
|
|
||||||
|
// basic nullptr
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = my_null);
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 4, base_buf).assign(my_null));
|
||||||
|
// basic range checking
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 4, base_buf));
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 0, base_buf));
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 0, base_buf) - 0);
|
||||||
|
CHECK_THROWS(Span0(base_buf, 0, base_buf) + 1);
|
||||||
|
CHECK_THROWS(Span0(base_buf, 0, base_buf) - 1);
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) + 4);
|
||||||
|
CHECK_THROWS(Span0(base_buf, 4, base_buf) + 5);
|
||||||
|
CHECK_THROWS(Span0(base_buf - 1, 4, base_buf));
|
||||||
|
CHECK_THROWS(Span0(base_buf + 1, 0, base_buf));
|
||||||
|
// basic same base
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 3, base_buf));
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 1, base_buf));
|
||||||
|
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 5, base_buf));
|
||||||
|
CHECK_THROWS(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 3, base_buf + 1));
|
||||||
|
|
||||||
|
Span0 a1(nullptr);
|
||||||
|
assert(a1 == nullptr);
|
||||||
|
assert(a1.raw_ptr() == nullptr);
|
||||||
|
assert(a1.raw_base() == nullptr);
|
||||||
|
assert(a1.raw_size_in_bytes() == 0u);
|
||||||
|
CHECK_THROWS(*a1);
|
||||||
|
CHECK_THROWS(a1[0]);
|
||||||
|
|
||||||
|
Span0 a2 = nullptr;
|
||||||
|
assert(a2 == nullptr);
|
||||||
|
assert(a2.raw_ptr() == nullptr);
|
||||||
|
assert(a2.raw_base() == nullptr);
|
||||||
|
assert(a2.raw_size_in_bytes() == 0u);
|
||||||
|
CHECK_THROWS(*a2);
|
||||||
|
CHECK_THROWS(a2[0]);
|
||||||
|
|
||||||
|
Span0 base0(nullptr, 4, base_buf);
|
||||||
|
assert(base0.raw_ptr() == nullptr);
|
||||||
|
assert(base0.raw_base() == base_buf);
|
||||||
|
assert(base0.raw_size_in_bytes() == 4u);
|
||||||
|
CHECK_THROWS(*base0); // nullptr
|
||||||
|
CHECK_THROWS(base0[0]); // nullptr
|
||||||
|
CHECK_THROWS(base0 + 1); // nullptr
|
||||||
|
|
||||||
|
Span0 base4(base_buf, 4);
|
||||||
|
assert(base4.raw_ptr() == base_buf);
|
||||||
|
assert(base4.raw_base() == base_buf);
|
||||||
|
assert(base4.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
a1 = base_buf;
|
||||||
|
a1 = base0;
|
||||||
|
assert(a1 == nullptr);
|
||||||
|
assert(a1.raw_ptr() == nullptr);
|
||||||
|
assert(a1.raw_base() == base_buf);
|
||||||
|
assert(a1.raw_size_in_bytes() == 4u);
|
||||||
|
a1 = base4;
|
||||||
|
assert(a1 == base_buf);
|
||||||
|
assert(a1.raw_ptr() == base_buf);
|
||||||
|
assert(a1.raw_base() == base_buf);
|
||||||
|
assert(a1.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
a1 = base_buf;
|
||||||
|
assert(a1 != nullptr);
|
||||||
|
a1 = base_buf + 1;
|
||||||
|
CHECK(*a1++ == 1);
|
||||||
|
CHECK(*++a1 == 3);
|
||||||
|
CHECK(*a1 == 3);
|
||||||
|
a1 = base_buf + 4; // at the end of buffer
|
||||||
|
CHECK_THROWS(*a1);
|
||||||
|
CHECK_THROWS(a1 = base_buf + 5); // range error
|
||||||
|
assert(a1 == base_buf + 4);
|
||||||
|
CHECK(a1[-4] == 0);
|
||||||
|
CHECK_THROWS(a1[-5]); // range error
|
||||||
|
a1 = base_buf;
|
||||||
|
CHECK(*a1 == 0);
|
||||||
|
|
||||||
|
Span0 new_base4(base_buf + 2, 4);
|
||||||
|
CHECK_THROWS(a1 = new_base4); // not same base
|
||||||
|
a2 = new_base4;
|
||||||
|
CHECK_THROWS(a2 = base4); // not same base
|
||||||
|
|
||||||
|
Span0 s0_no_base(nullptr);
|
||||||
|
Span0 s0_with_base(nullptr, 4, base_buf);
|
||||||
|
s0_no_base = nullptr;
|
||||||
|
s0_with_base = nullptr;
|
||||||
|
s0_with_base = s0_no_base;
|
||||||
|
assert(s0_no_base.raw_base() == nullptr);
|
||||||
|
assert(s0_with_base.raw_base() == base_buf);
|
||||||
|
s0_no_base = s0_with_base;
|
||||||
|
assert(s0_no_base.raw_base() == base_buf);
|
||||||
|
assert(s0_no_base.raw_ptr() == nullptr);
|
||||||
|
assert(s0_with_base.raw_ptr() == nullptr);
|
||||||
|
s0_no_base = my_null;
|
||||||
|
s0_with_base = my_null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
TEST_CASE("PtrOrSpan") {
|
||||||
|
char real_buf[2 + 6 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 124, 125};
|
||||||
|
char *base_buf = real_buf + 2;
|
||||||
|
char *const my_null = nullptr;
|
||||||
|
typedef PtrOrSpan<char> SpanP;
|
||||||
|
|
||||||
|
// basic nullptr
|
||||||
|
CHECK_THROWS(SpanP(base_buf, 4, base_buf) = my_null);
|
||||||
|
CHECK_THROWS(SpanP(base_buf, 4, base_buf).assign(my_null));
|
||||||
|
// basic range checking
|
||||||
|
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanP(base_buf, 0, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanP(base_buf, 0, base_buf) - 0);
|
||||||
|
CHECK_THROWS(SpanP(base_buf, 0, base_buf) + 1);
|
||||||
|
CHECK_THROWS(SpanP(base_buf, 0, base_buf) - 1);
|
||||||
|
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) + 4);
|
||||||
|
CHECK_THROWS(SpanP(base_buf, 4, base_buf) + 5);
|
||||||
|
CHECK_THROWS(SpanP(base_buf - 1, 4, base_buf));
|
||||||
|
CHECK_THROWS(SpanP(base_buf + 1, 0, base_buf));
|
||||||
|
// basic same base
|
||||||
|
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 3, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 1, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 5, base_buf));
|
||||||
|
CHECK_THROWS(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 3, base_buf + 1));
|
||||||
|
|
||||||
|
SpanP x1(base_buf, 0);
|
||||||
|
assert(x1 != nullptr);
|
||||||
|
assert(x1.raw_ptr() == base_buf);
|
||||||
|
assert(x1.raw_base() == base_buf);
|
||||||
|
assert(x1.raw_size_in_bytes() == 0u);
|
||||||
|
CHECK_THROWS(*x1);
|
||||||
|
CHECK_THROWS(x1[0]);
|
||||||
|
|
||||||
|
SpanP a2 = base_buf;
|
||||||
|
assert(a2 != nullptr);
|
||||||
|
assert(a2.raw_ptr() == base_buf);
|
||||||
|
assert(a2.raw_base() == nullptr);
|
||||||
|
assert(a2.raw_size_in_bytes() == 0u);
|
||||||
|
CHECK(*a2 == 0);
|
||||||
|
CHECK(a2[1] == 1);
|
||||||
|
|
||||||
|
SpanP base0(base_buf, 4, base_buf);
|
||||||
|
assert(base0.raw_ptr() == base_buf);
|
||||||
|
assert(base0.raw_base() == base_buf);
|
||||||
|
assert(base0.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
SpanP base4(base_buf, 4);
|
||||||
|
assert(base4.raw_ptr() == base_buf);
|
||||||
|
assert(base4.raw_base() == base_buf);
|
||||||
|
assert(base4.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
SpanP a1(base_buf, 4);
|
||||||
|
a1 = base_buf;
|
||||||
|
a1 = base0;
|
||||||
|
assert(a1 == base0);
|
||||||
|
assert(a1 != nullptr);
|
||||||
|
assert(a1.raw_ptr() == base0.raw_ptr());
|
||||||
|
assert(a1.raw_base() == base_buf);
|
||||||
|
assert(a1.raw_size_in_bytes() == 4u);
|
||||||
|
a1 = base4;
|
||||||
|
assert(a1 == base_buf);
|
||||||
|
assert(a1.raw_ptr() == base_buf);
|
||||||
|
assert(a1.raw_base() == base_buf);
|
||||||
|
assert(a1.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
a1 = base_buf;
|
||||||
|
a1 = base_buf + 1;
|
||||||
|
CHECK(*a1++ == 1);
|
||||||
|
CHECK(*++a1 == 3);
|
||||||
|
CHECK(*a1 == 3);
|
||||||
|
a1 = base_buf + 4; // at the end of buffer
|
||||||
|
CHECK_THROWS(*a1);
|
||||||
|
CHECK_THROWS(a1 = base_buf + 5); // range error
|
||||||
|
assert(a1 == base_buf + 4);
|
||||||
|
CHECK(a1[-4] == 0);
|
||||||
|
CHECK_THROWS(a1[-5]); // range error
|
||||||
|
a1 = base_buf;
|
||||||
|
CHECK(*a1 == 0);
|
||||||
|
|
||||||
|
SpanP new_base4(base_buf + 2, 4);
|
||||||
|
CHECK_THROWS(a1 = new_base4); // not same base
|
||||||
|
a2 = new_base4;
|
||||||
|
CHECK_THROWS(a2 = base4); // not same base
|
||||||
|
|
||||||
|
SpanP sp_no_base(base_buf);
|
||||||
|
SpanP sp_with_base(base_buf, 4, base_buf);
|
||||||
|
assert(sp_no_base.raw_base() == nullptr);
|
||||||
|
assert(sp_with_base.raw_base() == base_buf);
|
||||||
|
CHECK_THROWS(sp_no_base = my_null); // nullptr assignment
|
||||||
|
CHECK_THROWS(sp_with_base = my_null); // nullptr assignment
|
||||||
|
#if SPAN_CONFIG_ENABLE_SPAN_CONVERSION
|
||||||
|
typedef PtrOrSpanOrNull<char> Span0;
|
||||||
|
Span0 s0_no_base(nullptr);
|
||||||
|
Span0 s0_with_base(nullptr, 4, base_buf);
|
||||||
|
CHECK_THROWS(sp_no_base = s0_no_base); // nullptr assignment
|
||||||
|
CHECK_THROWS(sp_no_base = s0_with_base); // nullptr assignment
|
||||||
|
CHECK_THROWS(sp_with_base = s0_no_base); // nullptr assignment
|
||||||
|
CHECK_THROWS(sp_with_base = s0_with_base); // nullptr assignment
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
TEST_CASE("Span") {
|
||||||
|
char real_buf[2 + 6 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 124, 125};
|
||||||
|
char *base_buf = real_buf + 2;
|
||||||
|
char *const my_null = nullptr;
|
||||||
|
typedef Span<char> SpanS;
|
||||||
|
|
||||||
|
// basic nullptr
|
||||||
|
CHECK_THROWS(SpanS(base_buf, 4, base_buf) = my_null);
|
||||||
|
CHECK_THROWS(SpanS(base_buf, 4, base_buf).assign(my_null));
|
||||||
|
// basic range checking
|
||||||
|
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanS(base_buf, 0, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanS(base_buf, 0, base_buf) - 0);
|
||||||
|
CHECK_THROWS(SpanS(base_buf, 0, base_buf) + 1);
|
||||||
|
CHECK_THROWS(SpanS(base_buf, 0, base_buf) - 1);
|
||||||
|
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) + 4);
|
||||||
|
CHECK_THROWS(SpanS(base_buf, 4, base_buf) + 5);
|
||||||
|
CHECK_THROWS(SpanS(base_buf - 1, 4, base_buf));
|
||||||
|
CHECK_THROWS(SpanS(base_buf + 1, 0, base_buf));
|
||||||
|
// basic same base
|
||||||
|
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 3, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 1, base_buf));
|
||||||
|
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 5, base_buf));
|
||||||
|
CHECK_THROWS(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 3, base_buf + 1));
|
||||||
|
|
||||||
|
SpanS x1(base_buf, 0);
|
||||||
|
assert(x1 != nullptr);
|
||||||
|
assert(x1.raw_ptr() == base_buf);
|
||||||
|
assert(x1.raw_base() == base_buf);
|
||||||
|
assert(x1.raw_size_in_bytes() == 0u);
|
||||||
|
CHECK_THROWS(*x1);
|
||||||
|
CHECK_THROWS(x1[0]);
|
||||||
|
|
||||||
|
SpanS a2(base_buf, 4);
|
||||||
|
assert(a2 != nullptr);
|
||||||
|
assert(a2.raw_ptr() == base_buf);
|
||||||
|
assert(a2.raw_base() == base_buf);
|
||||||
|
assert(a2.raw_size_in_bytes() == 4u);
|
||||||
|
CHECK(*a2 == 0);
|
||||||
|
CHECK(a2[1] == 1);
|
||||||
|
|
||||||
|
SpanS base0(base_buf, 4, base_buf);
|
||||||
|
assert(base0.raw_ptr() == base_buf);
|
||||||
|
assert(base0.raw_base() == base_buf);
|
||||||
|
assert(base0.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
SpanS base4(base_buf, 4);
|
||||||
|
assert(base4.raw_ptr() == base_buf);
|
||||||
|
assert(base4.raw_base() == base_buf);
|
||||||
|
assert(base4.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
SpanS a1(base_buf, 4);
|
||||||
|
a1 = base_buf;
|
||||||
|
a1 = base0;
|
||||||
|
assert(a1 == base0);
|
||||||
|
assert(a1 != nullptr);
|
||||||
|
assert(a1.raw_ptr() == base0.raw_ptr());
|
||||||
|
assert(a1.raw_base() == base_buf);
|
||||||
|
assert(a1.raw_size_in_bytes() == 4u);
|
||||||
|
a1 = base4;
|
||||||
|
assert(a1 == base_buf);
|
||||||
|
assert(a1.raw_ptr() == base_buf);
|
||||||
|
assert(a1.raw_base() == base_buf);
|
||||||
|
assert(a1.raw_size_in_bytes() == 4u);
|
||||||
|
|
||||||
|
a1 = base_buf;
|
||||||
|
a1 = base_buf + 1;
|
||||||
|
CHECK(*a1++ == 1);
|
||||||
|
CHECK(*++a1 == 3);
|
||||||
|
CHECK(*a1 == 3);
|
||||||
|
a1 = base_buf + 4; // at the end of buffer
|
||||||
|
CHECK_THROWS(*a1);
|
||||||
|
CHECK_THROWS(a1 = base_buf + 5); // range error
|
||||||
|
assert(a1 == base_buf + 4);
|
||||||
|
CHECK(a1[-4] == 0);
|
||||||
|
CHECK_THROWS(a1[-5]); // range error
|
||||||
|
a1 = base_buf;
|
||||||
|
CHECK(*a1 == 0);
|
||||||
|
|
||||||
|
SpanS new_base4(base_buf + 2, 4);
|
||||||
|
CHECK_THROWS(a1 = new_base4); // not same base
|
||||||
|
CHECK_THROWS(a2 = new_base4); // not same base
|
||||||
|
|
||||||
|
SpanS ss_with_base(base_buf, 4, base_buf);
|
||||||
|
assert(ss_with_base.raw_base() == base_buf);
|
||||||
|
CHECK_THROWS(ss_with_base = my_null); // nullptr assignment
|
||||||
|
#if SPAN_CONFIG_ENABLE_SPAN_CONVERSION
|
||||||
|
{
|
||||||
|
typedef PtrOrSpanOrNull<char> Span0;
|
||||||
|
// v0 nullptr, b0 base, b1 base + 1
|
||||||
|
const Span0 v0_v0(nullptr);
|
||||||
|
const Span0 v0_b0(nullptr, 4, base_buf);
|
||||||
|
const Span0 v0_b1(nullptr, 3, base_buf + 1);
|
||||||
|
const Span0 b0_v0(base_buf);
|
||||||
|
const Span0 b0_b0(base_buf, 4, base_buf);
|
||||||
|
CHECK_THROWS(SPAN_0_MAKE(char, base_buf, 3, base_buf + 1)); // b0_b1
|
||||||
|
const Span0 b1_v0(base_buf + 1);
|
||||||
|
const Span0 b1_b0(base_buf + 1, 4, base_buf);
|
||||||
|
const Span0 b1_b1(base_buf + 1, 3, base_buf + 1);
|
||||||
|
CHECK_THROWS(ss_with_base = v0_v0); // nullptr assignment
|
||||||
|
CHECK_THROWS(ss_with_base = v0_b0); // nullptr assignment
|
||||||
|
CHECK_THROWS(ss_with_base = v0_b1); // nullptr assignment
|
||||||
|
CHECK_NOTHROW(ss_with_base = b0_v0);
|
||||||
|
CHECK_NOTHROW(ss_with_base = b0_b0);
|
||||||
|
CHECK_NOTHROW(ss_with_base = b1_v0);
|
||||||
|
CHECK_NOTHROW(ss_with_base = b1_b0);
|
||||||
|
CHECK_THROWS(ss_with_base = b1_b1); // different base
|
||||||
|
CHECK_THROWS(SPAN_S_MAKE(char, v0_v0));
|
||||||
|
CHECK_THROWS(SPAN_S_MAKE(char, v0_b0));
|
||||||
|
CHECK_THROWS(SPAN_S_MAKE(char, v0_b1));
|
||||||
|
CHECK_THROWS(SPAN_S_MAKE(char, b0_v0));
|
||||||
|
CHECK_NOTHROW(SPAN_S_MAKE(char, b0_b0));
|
||||||
|
CHECK_THROWS(SPAN_S_MAKE(char, b1_v0));
|
||||||
|
CHECK_NOTHROW(SPAN_S_MAKE(char, b1_b0));
|
||||||
|
CHECK_NOTHROW(SPAN_S_MAKE(char, b1_b1));
|
||||||
|
//
|
||||||
|
CHECK((SPAN_S_MAKE(char, b0_b0).raw_base() == base_buf));
|
||||||
|
CHECK((SPAN_S_MAKE(char, b1_b0).raw_base() == base_buf));
|
||||||
|
CHECK((SPAN_S_MAKE(char, b1_b1).raw_base() == base_buf + 1));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef PtrOrSpan<char> SpanP;
|
||||||
|
// v0 nullptr, b0 base, b1 base + 1
|
||||||
|
const SpanP b0_v0(base_buf);
|
||||||
|
const SpanP b0_b0(base_buf, 4, base_buf);
|
||||||
|
CHECK_THROWS(SPAN_P_MAKE(char, base_buf, 3, base_buf + 1)); // b0_b1
|
||||||
|
const SpanP b1_v0(base_buf + 1);
|
||||||
|
const SpanP b1_b0(base_buf + 1, 4, base_buf);
|
||||||
|
const SpanP b1_b1(base_buf + 1, 3, base_buf + 1);
|
||||||
|
CHECK_NOTHROW(ss_with_base = b0_v0);
|
||||||
|
CHECK_NOTHROW(ss_with_base = b0_b0);
|
||||||
|
CHECK_NOTHROW(ss_with_base = b1_v0);
|
||||||
|
CHECK_NOTHROW(ss_with_base = b1_b0);
|
||||||
|
CHECK_THROWS(ss_with_base = b1_b1); // different base
|
||||||
|
CHECK_THROWS(SPAN_S_MAKE(char, b0_v0));
|
||||||
|
CHECK_NOTHROW(SPAN_S_MAKE(char, b0_b0));
|
||||||
|
CHECK_THROWS(SPAN_S_MAKE(char, b1_v0));
|
||||||
|
CHECK_NOTHROW(SPAN_S_MAKE(char, b1_b0));
|
||||||
|
CHECK_NOTHROW(SPAN_S_MAKE(char, b1_b1));
|
||||||
|
//
|
||||||
|
CHECK((SPAN_S_MAKE(char, b0_b0).raw_base() == base_buf));
|
||||||
|
CHECK((SPAN_S_MAKE(char, b1_b0).raw_base() == base_buf));
|
||||||
|
CHECK((SPAN_S_MAKE(char, b1_b1).raw_base() == base_buf + 1));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
TEST_CASE("Span void ptr") {
|
||||||
|
static char a[4] = {0, 1, 2, 3};
|
||||||
|
SPAN_0(void) a0(a, 4);
|
||||||
|
SPAN_P(void) ap(a, 4);
|
||||||
|
SPAN_S(void) as(a, 4);
|
||||||
|
SPAN_0(const void) c0(a, 4);
|
||||||
|
SPAN_P(const void) cp(a, 4);
|
||||||
|
SPAN_S(const void) cs(a, 4);
|
||||||
|
static const char b[4] = {0, 1, 2, 3};
|
||||||
|
SPAN_0(const void) b0(b, 4);
|
||||||
|
SPAN_P(const void) bp(b, 4);
|
||||||
|
SPAN_S(const void) bs(b, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Span deref/array/arrow") {
|
||||||
|
static char real_a[2 + 4 + 2] = {126, 127, 0, 1, 2, 3, 124, 125};
|
||||||
|
static char *a = real_a + 2;
|
||||||
|
SPAN_0(char) a0(a, 4);
|
||||||
|
SPAN_P(char) ap(a, 4);
|
||||||
|
SPAN_S(char) as(a, 4);
|
||||||
|
CHECK_THROWS(a0[4]);
|
||||||
|
CHECK_THROWS(a0[-1]);
|
||||||
|
CHECK_THROWS(a0[-2]);
|
||||||
|
a0 += 2;
|
||||||
|
CHECK(*a0 == 2);
|
||||||
|
CHECK(a0[-1] == 1);
|
||||||
|
CHECK(a0[0] == 2);
|
||||||
|
CHECK(a0[1] == 3);
|
||||||
|
ap += 2;
|
||||||
|
CHECK(*ap == 2);
|
||||||
|
CHECK(ap[-1] == 1);
|
||||||
|
CHECK(ap[0] == 2);
|
||||||
|
CHECK(ap[1] == 3);
|
||||||
|
as += 2;
|
||||||
|
CHECK(*as == 2);
|
||||||
|
CHECK(as[-1] == 1);
|
||||||
|
CHECK(as[0] == 2);
|
||||||
|
CHECK(as[1] == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Span subspan") {
|
||||||
|
static char buf[4] = {0, 1, 2, 3};
|
||||||
|
SPAN_S(char) as(buf, 4);
|
||||||
|
CHECK(as.subspan(1, 1)[0] == 1);
|
||||||
|
CHECK((as + 1).subspan(1, 1)[0] == 2);
|
||||||
|
CHECK((as + 2).subspan(0, -2)[0] == 0);
|
||||||
|
CHECK_THROWS(as.subspan(1, 0)[0]);
|
||||||
|
CHECK_THROWS(as.subspan(1, 1)[-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Span constness") {
|
||||||
|
static char buf[4] = {0, 1, 2, 3};
|
||||||
|
|
||||||
|
SPAN_0(char) b0(buf, 4);
|
||||||
|
SPAN_P(char) bp(buf, 4);
|
||||||
|
SPAN_S(char) bs(buf, 4);
|
||||||
|
|
||||||
|
SPAN_0(char) s0(b0);
|
||||||
|
SPAN_P(char) sp(bp);
|
||||||
|
SPAN_S(char) ss(bs);
|
||||||
|
|
||||||
|
SPAN_0(const char) b0c(buf, 4);
|
||||||
|
SPAN_P(const char) bpc(buf, 4);
|
||||||
|
SPAN_S(const char) bsc(buf, 4);
|
||||||
|
|
||||||
|
SPAN_0(const char) s0c(b0c);
|
||||||
|
SPAN_P(const char) spc(bpc);
|
||||||
|
SPAN_S(const char) ssc(bsc);
|
||||||
|
|
||||||
|
SPAN_0(const char) x0c(b0);
|
||||||
|
SPAN_P(const char) xpc(bp);
|
||||||
|
SPAN_S(const char) xsc(bs);
|
||||||
|
|
||||||
|
CHECK(ptr_diff_bytes(b0, buf) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(bp, buf) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(bs, buf) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(s0, buf) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(sp, buf) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(bs, buf) == 0);
|
||||||
|
//
|
||||||
|
CHECK(ptr_diff_bytes(s0, bp) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(s0, sp) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(s0, ss) == 0);
|
||||||
|
//
|
||||||
|
CHECK(ptr_diff_bytes(s0c, b0c) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(spc, bpc) == 0);
|
||||||
|
CHECK(ptr_diff_bytes(ssc, bsc) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(DOCTEST_CONFIG_DISABLE)
|
||||||
|
namespace {
|
||||||
|
int my_memcmp_v1(SPAN_P(const void) a, SPAN_0(const void) b, size_t n) {
|
||||||
|
if (b == nullptr)
|
||||||
|
return -2;
|
||||||
|
SPAN_0(const void) x(a);
|
||||||
|
return memcmp(x, b, n);
|
||||||
|
}
|
||||||
|
int my_memcmp_v2(SPAN_P(const char) a, SPAN_0(const char) b, size_t n) {
|
||||||
|
if (a == b)
|
||||||
|
return 0;
|
||||||
|
if (b == nullptr)
|
||||||
|
return -2;
|
||||||
|
a += 1;
|
||||||
|
b -= 1;
|
||||||
|
SPAN_0(const char) x(a);
|
||||||
|
SPAN_0(const char) y = b;
|
||||||
|
return memcmp(x, y, n);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TEST_CASE("PtrOrSpan") {
|
||||||
|
static const char buf[4] = {0, 1, 2, 3};
|
||||||
|
CHECK(my_memcmp_v1(buf, nullptr, 4) == -2);
|
||||||
|
CHECK(my_memcmp_v2(buf + 4, buf + 4, 999) == 0);
|
||||||
|
CHECK(my_memcmp_v2(buf, buf + 2, 3) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
TEST_CASE("PtrOrSpan char") {
|
||||||
|
char real_buf[2 + 8 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 6, 7, 124, 125};
|
||||||
|
char *buf = real_buf + 2;
|
||||||
|
SPAN_P(char) a(buf, SpanSizeInBytes(8));
|
||||||
|
SPAN_P(char) b = a.subspan(0, 7);
|
||||||
|
SPAN_P(char) c = (b + 1).subspan(0, 6);
|
||||||
|
a += 1;
|
||||||
|
CHECK(*a == 1);
|
||||||
|
*a++ += 1;
|
||||||
|
*b++ = 1;
|
||||||
|
CHECK(a == buf + 2);
|
||||||
|
CHECK(b == buf + 1);
|
||||||
|
CHECK(c == buf + 1);
|
||||||
|
CHECK(*b == 2);
|
||||||
|
CHECK(*c == 2);
|
||||||
|
CHECK(a.raw_size_in_bytes() == 8u);
|
||||||
|
CHECK(b.raw_size_in_bytes() == 7u);
|
||||||
|
CHECK(c.raw_size_in_bytes() == 6u);
|
||||||
|
CHECK(a.raw_base() == buf);
|
||||||
|
CHECK(b.raw_base() == buf);
|
||||||
|
CHECK(c.raw_base() == buf + 1);
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
CHECK(get_le32(a) != 0);
|
||||||
|
#endif
|
||||||
|
++c;
|
||||||
|
c++;
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
CHECK(get_le32(c) != 0);
|
||||||
|
#endif
|
||||||
|
++c;
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
CHECK_THROWS(get_le32(c));
|
||||||
|
#endif
|
||||||
|
++b;
|
||||||
|
b++;
|
||||||
|
b += 4;
|
||||||
|
CHECK(b.raw_ptr() == buf + 7);
|
||||||
|
CHECK_THROWS(*b);
|
||||||
|
CHECK(a.raw_size_in_bytes() == 8u);
|
||||||
|
a = b;
|
||||||
|
CHECK(a.raw_size_in_bytes() == 8u);
|
||||||
|
CHECK(a.raw_ptr() == buf + 7);
|
||||||
|
a++;
|
||||||
|
CHECK_THROWS(*a);
|
||||||
|
CHECK_THROWS(raw_bytes(a, 1));
|
||||||
|
a = b;
|
||||||
|
CHECK_THROWS(a = c);
|
||||||
|
*a = 0;
|
||||||
|
a = buf;
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
CHECK(upx_safe_strlen(a) == 7u);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("PtrOrSpan int") {
|
||||||
|
int buf[8] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||||
|
SPAN_P(int) a(buf, SpanCount(8));
|
||||||
|
CHECK(a.raw_size_in_bytes() == 8 * sizeof(int));
|
||||||
|
SPAN_P(int) b = a.subspan(0, 7);
|
||||||
|
CHECK(b.raw_size_in_bytes() == 7 * sizeof(int));
|
||||||
|
SPAN_P(int) c = (b + 1).subspan(0, 6);
|
||||||
|
CHECK(c.raw_size_in_bytes() == 6 * sizeof(int));
|
||||||
|
a += 1;
|
||||||
|
CHECK(*a == 1);
|
||||||
|
CHECK(*a++ == 1);
|
||||||
|
CHECK(*++a == 3);
|
||||||
|
CHECK(--*a == 2);
|
||||||
|
CHECK(*a-- == 2);
|
||||||
|
CHECK(*b == 0);
|
||||||
|
CHECK(*c == 1);
|
||||||
|
a = buf + 7;
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
CHECK(get_le32(a) == ne32_to_le32(7));
|
||||||
|
#endif
|
||||||
|
a++;
|
||||||
|
#ifdef UPX_VERSION_HEX
|
||||||
|
CHECK_THROWS(get_le32(a));
|
||||||
|
#endif
|
||||||
|
CHECK_THROWS(raw_bytes(a, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// codegen
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template <class T>
|
||||||
|
__acc_static_noinline int foo(T p) {
|
||||||
|
unsigned r = 0;
|
||||||
|
r += *p++;
|
||||||
|
r += *++p;
|
||||||
|
p += 3;
|
||||||
|
r += *p;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
SPAN_0(T)
|
||||||
|
make_span_0(T *ptr, size_t count) {
|
||||||
|
return PtrOrSpanOrNull<T>(ptr, count);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
SPAN_P(T)
|
||||||
|
make_span_p(T *ptr, size_t count) {
|
||||||
|
return PtrOrSpan<T>(ptr, count);
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
SPAN_S(T)
|
||||||
|
make_span_s(T *ptr, size_t count) {
|
||||||
|
return Span<T>(ptr, count);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST_CASE("Span codegen") {
|
||||||
|
char buf[8] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||||
|
CHECK(foo(buf) == 0 + 2 + 5);
|
||||||
|
CHECK(foo(make_span_0(buf, 8)) == 0 + 2 + 5);
|
||||||
|
CHECK(foo(make_span_p(buf, 8)) == 0 + 2 + 5);
|
||||||
|
CHECK(foo(make_span_s(buf, 8)) == 0 + 2 + 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WITH_SPAN >= 2
|
||||||
|
|
||||||
|
/* vim:set ts=4 sw=4 et: */
|
82
src/check/dtx_boost_pfr.cpp
Normal file
82
src/check/dtx_boost_pfr.cpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/* dtx_.cpp -- DocTest eXtra checks
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer
|
||||||
|
<markus@oberhumer.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
#ifndef WITH_BOOST_PFR
|
||||||
|
#define WITH_BOOST_PFR 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../conf.h"
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#if WITH_BOOST_PFR
|
||||||
|
|
||||||
|
TEST_CASE("boost::pfr") {
|
||||||
|
struct Foo {
|
||||||
|
BE16 b16;
|
||||||
|
BE32 b32;
|
||||||
|
BE64 b64;
|
||||||
|
LE16 l16;
|
||||||
|
LE32 l32;
|
||||||
|
LE64 l64;
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
int i = -1;
|
||||||
|
CHECK_EQ(strcmp(pfr_str(i), "-1"), 0);
|
||||||
|
BE32 b32;
|
||||||
|
b32 = 1;
|
||||||
|
LE32 l32;
|
||||||
|
l32 = 2;
|
||||||
|
CHECK_EQ(strcmp(pfr_str(b32), "1"), 0);
|
||||||
|
CHECK_EQ(strcmp(pfr_str(l32), "2"), 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Foo foo;
|
||||||
|
foo.b16 = 1;
|
||||||
|
foo.b32 = 2;
|
||||||
|
foo.b64 = 3;
|
||||||
|
foo.l16 = 4;
|
||||||
|
foo.l32 = 5;
|
||||||
|
foo.l64 = 6;
|
||||||
|
CHECK_EQ(strcmp(pfr_str("foo", "=", foo), "foo = {1, 2, 3, 4, 5, 6}"), 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
#if (ACC_ABI_BIG_ENDIAN)
|
||||||
|
#else
|
||||||
|
constexpr Foo foo{{1}, {1}, {1}, {1}, {1}, {1}};
|
||||||
|
CHECK_EQ(strcmp(pfr_str(foo), "{256, 16777216, 72057594037927936, 1, 1, 1}"), 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WITH_BOOST_PFR
|
||||||
|
|
||||||
|
/* vim:set ts=4 sw=4 et: */
|
64
src/check/dtx_rangeless.cpp
Normal file
64
src/check/dtx_rangeless.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* dtx_.cpp -- DocTest eXtra checks
|
||||||
|
|
||||||
|
This file is part of the UPX executable compressor.
|
||||||
|
|
||||||
|
Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
UPX and the UCL library are free software; you can redistribute them
|
||||||
|
and/or modify them under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; see the file COPYING.
|
||||||
|
If not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
Markus F.X.J. Oberhumer
|
||||||
|
<markus@oberhumer.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if DEBUG && 0
|
||||||
|
#ifndef WITH_RANGELESS_FN
|
||||||
|
#define WITH_RANGELESS_FN 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if WITH_RANGELESS_FN
|
||||||
|
#define RANGELESS_FN_ENABLE_RUN_TESTS 1
|
||||||
|
#if defined(__i386__) && defined(__MSDOS__) && defined(__DJGPP__) && defined(__GNUC__)
|
||||||
|
#define RANGELESS_FN_ENABLE_PARALLEL 0
|
||||||
|
#elif defined(__m68k__) && defined(__atarist__) && defined(__GNUC__)
|
||||||
|
#define RANGELESS_FN_ENABLE_PARALLEL 0
|
||||||
|
#else
|
||||||
|
// disable multithreading for now; needs CMake find_package(Threads)
|
||||||
|
#define RANGELESS_FN_ENABLE_PARALLEL 0
|
||||||
|
#endif
|
||||||
|
#endif // WITH_RANGELESS_FN
|
||||||
|
|
||||||
|
#include "../conf.h"
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
//
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#if WITH_RANGELESS_FN && RANGELESS_FN_ENABLE_RUN_TESTS
|
||||||
|
|
||||||
|
TEST_CASE("rangeless::fn") { CHECK_NOTHROW(rangeless::fn::impl::run_tests()); }
|
||||||
|
|
||||||
|
#if RANGELESS_FN_ENABLE_PARALLEL
|
||||||
|
TEST_CASE("rangeless::fn parallel") {
|
||||||
|
// CHECK_NOTHROW(rangeless::mt::impl::run_tests());
|
||||||
|
ACC_UNUSED_FUNC(rangeless::mt::impl::run_tests);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // WITH_RANGELESS_FN
|
||||||
|
|
||||||
|
/* vim:set ts=4 sw=4 et: */
|
129
src/conf.h
129
src/conf.h
@ -83,10 +83,10 @@ ACC_COMPILE_TIME_ASSERT_HEADER((char)(-1) == 255) // -funsigned-char
|
|||||||
// don't enable before gcc-10 because of gcc bug #78010
|
// don't enable before gcc-10 because of gcc bug #78010
|
||||||
# pragma GCC diagnostic error "-Wsuggest-override"
|
# pragma GCC diagnostic error "-Wsuggest-override"
|
||||||
#endif
|
#endif
|
||||||
// Some non-GLIBC toolchains do not use 'nullptr' everywhere when C++:
|
// Some non-GLIBC toolchains do not use 'nullptr' everywhere when C++:
|
||||||
// openwrt-sdk-x86-64_gcc-11.2.0_musl.Linux-x86_64/staging_dir/
|
// openwrt-sdk-x86-64_gcc-11.2.0_musl.Linux-x86_64/staging_dir/
|
||||||
// toolchain-x86_64_gcc-11.2.0_musl/include/fortify/stdlib.h:
|
// toolchain-x86_64_gcc-11.2.0_musl/include/fortify/stdlib.h:
|
||||||
// 51:32: error: zero as null pointer constant
|
// 51:32: error: zero as null pointer constant
|
||||||
#if (ACC_CC_CLANG >= 0x050000)
|
#if (ACC_CC_CLANG >= 0x050000)
|
||||||
# pragma clang diagnostic error "-Wzero-as-null-pointer-constant"
|
# pragma clang diagnostic error "-Wzero-as-null-pointer-constant"
|
||||||
#elif (ACC_CC_GNUC >= 0x040700) && defined(__GLIBC__)
|
#elif (ACC_CC_GNUC >= 0x040700) && defined(__GLIBC__)
|
||||||
@ -115,7 +115,7 @@ ACC_COMPILE_TIME_ASSERT_HEADER((char)(-1) == 255) // -funsigned-char
|
|||||||
# include <intrin.h>
|
# include <intrin.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// C++ headers
|
// C++ system headers
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@ -128,11 +128,21 @@ ACC_COMPILE_TIME_ASSERT_HEADER((char)(-1) == 255) // -funsigned-char
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#define upx_std_atomic(Type) std::atomic<Type>
|
#define upx_std_atomic(Type) std::atomic<Type>
|
||||||
#endif
|
#endif
|
||||||
//#define DOCTEST_CONFIG_DISABLE 1
|
|
||||||
|
// C++ submodule headers
|
||||||
#include <doctest/doctest/parts/doctest_fwd.h>
|
#include <doctest/doctest/parts/doctest_fwd.h>
|
||||||
#if WITH_BOOST_PFR
|
#if WITH_BOOST_PFR
|
||||||
#include <sstream>
|
# include <sstream>
|
||||||
#include <boost/pfr/io.hpp>
|
# include <boost/pfr/io.hpp>
|
||||||
|
#endif
|
||||||
|
#if WITH_RANGELESS_FN
|
||||||
|
# include <rangeless/include/fn.hpp>
|
||||||
|
#endif
|
||||||
|
#ifndef WITH_VALGRIND
|
||||||
|
#define WITH_VALGRIND 1
|
||||||
|
#endif
|
||||||
|
#if (WITH_VALGRIND) && defined(__GNUC__) && !defined(__SANITIZE_ADDRESS__)
|
||||||
|
# include <valgrind/include/valgrind/memcheck.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// IMPORTANT: unconditionally enable assertions
|
// IMPORTANT: unconditionally enable assertions
|
||||||
@ -141,56 +151,9 @@ ACC_COMPILE_TIME_ASSERT_HEADER((char)(-1) == 255) // -funsigned-char
|
|||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
// core
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#if defined(__linux__) && !defined(__unix__)
|
|
||||||
# define __unix__ 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// just in case
|
|
||||||
#undef _
|
|
||||||
#undef __
|
|
||||||
#undef ___
|
|
||||||
#undef dos
|
|
||||||
#undef linux
|
|
||||||
#undef small
|
|
||||||
#undef tos
|
|
||||||
#undef unix
|
|
||||||
#if (ACC_OS_DOS32) && defined(__DJGPP__)
|
|
||||||
# undef sopen
|
|
||||||
# undef __unix__
|
|
||||||
# undef __unix
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define WITH_LZMA 0x443
|
|
||||||
#define WITH_UCL 1
|
|
||||||
#define WITH_ZLIB 1
|
|
||||||
#if (WITH_UCL)
|
|
||||||
# define ucl_compress_config_t REAL_ucl_compress_config_t
|
|
||||||
# include <ucl/include/ucl/uclconf.h>
|
|
||||||
# include <ucl/include/ucl/ucl.h>
|
|
||||||
# undef ucl_compress_config_t
|
|
||||||
# undef ucl_compress_config_p
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// malloc debuggers
|
|
||||||
#ifndef WITH_VALGRIND
|
|
||||||
# define WITH_VALGRIND 1
|
|
||||||
#endif
|
|
||||||
#if (WITH_VALGRIND) && defined(__GNUC__) && !defined(__SANITIZE_ADDRESS__)
|
|
||||||
# include <valgrind/include/valgrind/memcheck.h>
|
|
||||||
#endif
|
|
||||||
#if !defined(VALGRIND_MAKE_MEM_DEFINED)
|
|
||||||
# define VALGRIND_MAKE_MEM_DEFINED(addr,len) 0
|
|
||||||
#endif
|
|
||||||
#if !defined(VALGRIND_MAKE_MEM_NOACCESS)
|
|
||||||
# define VALGRIND_MAKE_MEM_NOACCESS(addr,len) 0
|
|
||||||
#endif
|
|
||||||
#if !defined(VALGRIND_MAKE_MEM_UNDEFINED)
|
|
||||||
# define VALGRIND_MAKE_MEM_UNDEFINED(addr,len) 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// intergral types
|
// intergral types
|
||||||
typedef acc_int8_t upx_int8_t;
|
typedef acc_int8_t upx_int8_t;
|
||||||
typedef acc_uint8_t upx_uint8_t;
|
typedef acc_uint8_t upx_uint8_t;
|
||||||
@ -227,6 +190,24 @@ typedef upx_int64_t upx_off_t;
|
|||||||
// portab
|
// portab
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
// just in case
|
||||||
|
#undef _
|
||||||
|
#undef __
|
||||||
|
#undef ___
|
||||||
|
#undef dos
|
||||||
|
#undef linux
|
||||||
|
#undef small
|
||||||
|
#undef tos
|
||||||
|
#undef unix
|
||||||
|
#if defined(__linux__) && !defined(__unix__)
|
||||||
|
# define __unix__ 1
|
||||||
|
#endif
|
||||||
|
#if (ACC_OS_DOS32) && defined(__DJGPP__)
|
||||||
|
# undef sopen
|
||||||
|
# undef __unix__
|
||||||
|
# undef __unix
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef STDIN_FILENO
|
#ifndef STDIN_FILENO
|
||||||
# define STDIN_FILENO (fileno(stdin))
|
# define STDIN_FILENO (fileno(stdin))
|
||||||
#endif
|
#endif
|
||||||
@ -307,11 +288,22 @@ typedef upx_int64_t upx_off_t;
|
|||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
//
|
// util
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#define CLANG_FORMAT_DUMMY_STATEMENT /*empty*/
|
#define CLANG_FORMAT_DUMMY_STATEMENT /*empty*/
|
||||||
|
|
||||||
|
// malloc debuggers
|
||||||
|
#if !defined(VALGRIND_MAKE_MEM_DEFINED)
|
||||||
|
# define VALGRIND_MAKE_MEM_DEFINED(addr,len) 0
|
||||||
|
#endif
|
||||||
|
#if !defined(VALGRIND_MAKE_MEM_NOACCESS)
|
||||||
|
# define VALGRIND_MAKE_MEM_NOACCESS(addr,len) 0
|
||||||
|
#endif
|
||||||
|
#if !defined(VALGRIND_MAKE_MEM_UNDEFINED)
|
||||||
|
# define VALGRIND_MAKE_MEM_UNDEFINED(addr,len) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(__MINGW32__) && defined(__GNUC__) && !defined(__clang__)
|
#if defined(_WIN32) && defined(__MINGW32__) && defined(__GNUC__) && !defined(__clang__)
|
||||||
# define attribute_format(a,b) __attribute__((__format__(__gnu_printf__,a,b)))
|
# define attribute_format(a,b) __attribute__((__format__(__gnu_printf__,a,b)))
|
||||||
#elif (ACC_CC_CLANG || ACC_CC_GNUC)
|
#elif (ACC_CC_CLANG || ACC_CC_GNUC)
|
||||||
@ -488,14 +480,14 @@ constexpr bool string_ge(const char *a, const char *b) {
|
|||||||
#define UPX_F_DOS_EXE 3
|
#define UPX_F_DOS_EXE 3
|
||||||
#define UPX_F_DJGPP2_COFF 4
|
#define UPX_F_DJGPP2_COFF 4
|
||||||
#define UPX_F_WATCOM_LE 5
|
#define UPX_F_WATCOM_LE 5
|
||||||
#define UPX_F_VXD_LE 6 // NOT IMPLEMENTED
|
//#define UPX_F_VXD_LE 6 // NOT IMPLEMENTED
|
||||||
#define UPX_F_DOS_EXEH 7 // OBSOLETE
|
#define UPX_F_DOS_EXEH 7 // OBSOLETE
|
||||||
#define UPX_F_TMT_ADAM 8
|
#define UPX_F_TMT_ADAM 8
|
||||||
#define UPX_F_WIN32_PE 9
|
#define UPX_F_WIN32_PE 9
|
||||||
#define UPX_F_LINUX_i386 10
|
#define UPX_F_LINUX_i386 10
|
||||||
#define UPX_F_WIN16_NE 11 // NOT IMPLEMENTED
|
//#define UPX_F_WIN16_NE 11 // NOT IMPLEMENTED
|
||||||
#define UPX_F_LINUX_ELF_i386 12
|
#define UPX_F_LINUX_ELF_i386 12
|
||||||
#define UPX_F_LINUX_SEP_i386 13 // NOT IMPLEMENTED
|
//#define UPX_F_LINUX_SEP_i386 13 // NOT IMPLEMENTED
|
||||||
#define UPX_F_LINUX_SH_i386 14
|
#define UPX_F_LINUX_SH_i386 14
|
||||||
#define UPX_F_VMLINUZ_i386 15
|
#define UPX_F_VMLINUZ_i386 15
|
||||||
#define UPX_F_BVMLINUZ_i386 16
|
#define UPX_F_BVMLINUZ_i386 16
|
||||||
@ -533,7 +525,7 @@ constexpr bool string_ge(const char *a, const char *b) {
|
|||||||
#define UPX_F_LINUX_ELF64_ARM 42
|
#define UPX_F_LINUX_ELF64_ARM 42
|
||||||
|
|
||||||
#define UPX_F_ATARI_TOS 129
|
#define UPX_F_ATARI_TOS 129
|
||||||
#define UPX_F_SOLARIS_SPARC 130 // NOT IMPLEMENTED
|
//#define UPX_F_SOLARIS_SPARC 130 // NOT IMPLEMENTED
|
||||||
#define UPX_F_MACH_PPC32 131
|
#define UPX_F_MACH_PPC32 131
|
||||||
#define UPX_F_LINUX_ELFPPC32 132
|
#define UPX_F_LINUX_ELFPPC32 132
|
||||||
#define UPX_F_LINUX_ELF32_ARMEB 133
|
#define UPX_F_LINUX_ELF32_ARMEB 133
|
||||||
@ -562,7 +554,7 @@ constexpr bool string_ge(const char *a, const char *b) {
|
|||||||
//#define M_CL1B_8 12
|
//#define M_CL1B_8 12
|
||||||
//#define M_CL1B_LE16 13
|
//#define M_CL1B_LE16 13
|
||||||
#define M_LZMA 14
|
#define M_LZMA 14
|
||||||
#define M_DEFLATE 15 /* zlib */
|
#define M_DEFLATE 15 // zlib
|
||||||
#define M_ZSTD 16
|
#define M_ZSTD 16
|
||||||
// compression methods internal usage
|
// compression methods internal usage
|
||||||
#define M_ALL (-1)
|
#define M_ALL (-1)
|
||||||
@ -588,9 +580,20 @@ constexpr bool string_ge(const char *a, const char *b) {
|
|||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// compression - callback_t
|
// compression - setup and callback_t
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
#define WITH_LZMA 0x443
|
||||||
|
#define WITH_UCL 1
|
||||||
|
#define WITH_ZLIB 1
|
||||||
|
#if (WITH_UCL)
|
||||||
|
# define ucl_compress_config_t REAL_ucl_compress_config_t
|
||||||
|
# include <ucl/include/ucl/uclconf.h>
|
||||||
|
# include <ucl/include/ucl/ucl.h>
|
||||||
|
# undef ucl_compress_config_t
|
||||||
|
# undef ucl_compress_config_p
|
||||||
|
#endif
|
||||||
|
|
||||||
struct upx_callback_t;
|
struct upx_callback_t;
|
||||||
typedef upx_callback_t *upx_callback_p;
|
typedef upx_callback_t *upx_callback_p;
|
||||||
typedef void (__acc_cdecl *upx_progress_func_t)
|
typedef void (__acc_cdecl *upx_progress_func_t)
|
||||||
|
@ -31,6 +31,15 @@
|
|||||||
// UPX version of string functions, with assertions and sane limits
|
// UPX version of string functions, with assertions and sane limits
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
|
upx_rsize_t upx_safe_strlen(const char *s) {
|
||||||
|
#undef strlen
|
||||||
|
assert(s != nullptr);
|
||||||
|
size_t len = strlen(s);
|
||||||
|
assert(len < UPX_RSIZE_MAX_STR);
|
||||||
|
return len;
|
||||||
|
#define strlen upx_safe_strlen
|
||||||
|
}
|
||||||
|
|
||||||
int upx_safe_vsnprintf(char *str, upx_rsize_t max_size, const char *format, va_list ap) {
|
int upx_safe_vsnprintf(char *str, upx_rsize_t max_size, const char *format, va_list ap) {
|
||||||
#undef vsnprintf
|
#undef vsnprintf
|
||||||
size_t size;
|
size_t size;
|
||||||
@ -114,13 +123,4 @@ char *upx_safe_xprintf(const char *format, ...) {
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
upx_rsize_t upx_safe_strlen(const char *s) {
|
|
||||||
#undef strlen
|
|
||||||
assert(s != nullptr);
|
|
||||||
size_t len = strlen(s);
|
|
||||||
assert(len < UPX_RSIZE_MAX_STR);
|
|
||||||
return len;
|
|
||||||
#define strlen upx_safe_strlen
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
@ -49,6 +49,9 @@ char *upx_safe_xprintf(const char *format, ...) attribute_format(1, 2);
|
|||||||
upx_rsize_t upx_safe_strlen(const char *);
|
upx_rsize_t upx_safe_strlen(const char *);
|
||||||
|
|
||||||
// globally redirect some functions
|
// globally redirect some functions
|
||||||
|
#undef strlen
|
||||||
|
#define strlen upx_safe_strlen
|
||||||
|
|
||||||
#undef snprintf
|
#undef snprintf
|
||||||
#undef sprintf
|
#undef sprintf
|
||||||
#undef vsnprintf
|
#undef vsnprintf
|
||||||
@ -56,9 +59,6 @@ upx_rsize_t upx_safe_strlen(const char *);
|
|||||||
#define sprintf ERROR_sprintf_IS_DANGEROUS_USE_snprintf
|
#define sprintf ERROR_sprintf_IS_DANGEROUS_USE_snprintf
|
||||||
#define vsnprintf upx_safe_vsnprintf
|
#define vsnprintf upx_safe_vsnprintf
|
||||||
|
|
||||||
#undef strlen
|
|
||||||
#define strlen upx_safe_strlen
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// some unsigned char string support functions to avoid casts
|
// some unsigned char string support functions to avoid casts
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
@ -69,727 +69,4 @@ SPAN_NAMESPACE_END
|
|||||||
|
|
||||||
#endif // WITH_SPAN
|
#endif // WITH_SPAN
|
||||||
|
|
||||||
// lots of tests (and probably quite a number of redundant tests)
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
TEST_CASE("basic xspan usage") {
|
|
||||||
char buf[4] = {0, 1, 2, 3};
|
|
||||||
|
|
||||||
SUBCASE("SPAN_x") {
|
|
||||||
SPAN_0(char) a0 = nullptr;
|
|
||||||
|
|
||||||
SPAN_0(char) b0 = buf;
|
|
||||||
SPAN_P(char) bp = buf;
|
|
||||||
|
|
||||||
SPAN_0(char) c0 = SPAN_0_MAKE(char, buf);
|
|
||||||
SPAN_P(char) cp = SPAN_P_MAKE(char, buf);
|
|
||||||
SPAN_S(char) cs = SPAN_S_MAKE(char, buf, sizeof(buf));
|
|
||||||
|
|
||||||
SPAN_0(const char) const x0 = SPAN_0_MAKE(const char, buf);
|
|
||||||
SPAN_P(const char) const xp = SPAN_P_MAKE(const char, buf);
|
|
||||||
SPAN_S(const char) const xs = SPAN_S_MAKE(const char, buf, sizeof(buf));
|
|
||||||
SPAN_P(const char) const yp = xs;
|
|
||||||
SPAN_0(const char) const z0p = yp;
|
|
||||||
SPAN_0(const char) const z0s = xs;
|
|
||||||
|
|
||||||
CHECK((a0 == nullptr));
|
|
||||||
CHECK(c0 == b0);
|
|
||||||
CHECK(cp == bp);
|
|
||||||
CHECK(cs == bp);
|
|
||||||
CHECK(x0 == z0p);
|
|
||||||
CHECK(xp == z0s);
|
|
||||||
|
|
||||||
CHECK(raw_bytes(c0, 4) == buf);
|
|
||||||
CHECK(raw_index_bytes(c0, 1, 3) == buf + 1);
|
|
||||||
CHECK(raw_bytes(cp, 4) == buf);
|
|
||||||
CHECK(raw_index_bytes(cp, 1, 3) == buf + 1);
|
|
||||||
CHECK(raw_bytes(cs, 4) == buf);
|
|
||||||
CHECK(raw_index_bytes(cs, 1, 3) == buf + 1);
|
|
||||||
CHECK_THROWS(raw_bytes(cs, 5));
|
|
||||||
CHECK_THROWS(raw_index_bytes(cs, 1, 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
SUBCASE("SPAN_x_VAR") {
|
|
||||||
SPAN_0_VAR(char, a0, nullptr);
|
|
||||||
|
|
||||||
SPAN_0_VAR(char, b0, buf);
|
|
||||||
SPAN_P_VAR(char, bp, buf);
|
|
||||||
|
|
||||||
SPAN_0_VAR(char, c0, buf, sizeof(buf));
|
|
||||||
SPAN_P_VAR(char, cp, buf, sizeof(buf));
|
|
||||||
SPAN_S_VAR(char, cs, buf, sizeof(buf));
|
|
||||||
|
|
||||||
SPAN_0_VAR(char, d0, buf + 1, sizeof(buf), buf);
|
|
||||||
SPAN_P_VAR(char, dp, buf + 1, sizeof(buf), buf);
|
|
||||||
SPAN_S_VAR(char, ds, buf + 1, sizeof(buf), buf);
|
|
||||||
|
|
||||||
SPAN_0_VAR(const char, const x0, buf, sizeof(buf));
|
|
||||||
SPAN_P_VAR(const char, const xp, buf, sizeof(buf));
|
|
||||||
SPAN_S_VAR(const char, const xs, buf, sizeof(buf));
|
|
||||||
SPAN_P_VAR(const char, const yp, xs);
|
|
||||||
SPAN_0_VAR(const char, const z0p, yp);
|
|
||||||
SPAN_0_VAR(const char, const z0s, xs);
|
|
||||||
|
|
||||||
CHECK((a0 == nullptr));
|
|
||||||
CHECK(c0 == b0);
|
|
||||||
CHECK(cp == bp);
|
|
||||||
CHECK(cs == bp);
|
|
||||||
CHECK(d0 == dp);
|
|
||||||
CHECK(d0 == ds);
|
|
||||||
CHECK(x0 == z0p);
|
|
||||||
CHECK(xp == z0s);
|
|
||||||
|
|
||||||
CHECK(raw_bytes(c0, 4) == buf);
|
|
||||||
CHECK(raw_index_bytes(c0, 1, 3) == buf + 1);
|
|
||||||
CHECK(raw_bytes(cp, 4) == buf);
|
|
||||||
CHECK(raw_index_bytes(cp, 1, 3) == buf + 1);
|
|
||||||
CHECK(raw_bytes(cs, 4) == buf);
|
|
||||||
CHECK(raw_index_bytes(cs, 1, 3) == buf + 1);
|
|
||||||
CHECK_THROWS(raw_bytes(cs, 5));
|
|
||||||
CHECK_THROWS(raw_index_bytes(cs, 1, 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
SUBCASE("xspan in class") {
|
|
||||||
struct MyType {
|
|
||||||
SPAN_0(char) s0;
|
|
||||||
SPAN_P(char) sp;
|
|
||||||
SPAN_S(char) ss;
|
|
||||||
#if __cplusplus >= 201103L
|
|
||||||
SPAN_0(char) x0 = nullptr;
|
|
||||||
#endif
|
|
||||||
#if WITH_SPAN >= 2
|
|
||||||
// much nicer syntax when using fully checked xspan:
|
|
||||||
MyType(char *b, size_t n, bool) : s0(b, n), sp(b, n), ss(b, n) {}
|
|
||||||
#endif
|
|
||||||
MyType(char *b, size_t n)
|
|
||||||
: s0(SPAN_0_MAKE(char, b, n)), sp(SPAN_P_MAKE(char, b, n)),
|
|
||||||
ss(SPAN_S_MAKE(char, b, n)) {
|
|
||||||
UNUSED(n);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
MyType x(buf, sizeof(buf));
|
|
||||||
MyType y = MyType(buf, sizeof(buf));
|
|
||||||
CHECK(x.s0 == y.sp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#if WITH_SPAN >= 2
|
|
||||||
|
|
||||||
TEST_CASE("PtrOrSpanOrNull") {
|
|
||||||
char real_buf[2 + 6 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 124, 125};
|
|
||||||
char *base_buf = real_buf + 2;
|
|
||||||
char *const my_null = nullptr;
|
|
||||||
typedef PtrOrSpanOrNull<char> Span0;
|
|
||||||
|
|
||||||
// basic nullptr
|
|
||||||
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = my_null);
|
|
||||||
CHECK_NOTHROW(Span0(base_buf, 4, base_buf).assign(my_null));
|
|
||||||
// basic range checking
|
|
||||||
CHECK_NOTHROW(Span0(base_buf, 4, base_buf));
|
|
||||||
CHECK_NOTHROW(Span0(base_buf, 0, base_buf));
|
|
||||||
CHECK_NOTHROW(Span0(base_buf, 0, base_buf) - 0);
|
|
||||||
CHECK_THROWS(Span0(base_buf, 0, base_buf) + 1);
|
|
||||||
CHECK_THROWS(Span0(base_buf, 0, base_buf) - 1);
|
|
||||||
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) + 4);
|
|
||||||
CHECK_THROWS(Span0(base_buf, 4, base_buf) + 5);
|
|
||||||
CHECK_THROWS(Span0(base_buf - 1, 4, base_buf));
|
|
||||||
CHECK_THROWS(Span0(base_buf + 1, 0, base_buf));
|
|
||||||
// basic same base
|
|
||||||
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 3, base_buf));
|
|
||||||
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 1, base_buf));
|
|
||||||
CHECK_NOTHROW(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 5, base_buf));
|
|
||||||
CHECK_THROWS(Span0(base_buf, 4, base_buf) = Span0(base_buf + 1, 3, base_buf + 1));
|
|
||||||
|
|
||||||
Span0 a1(nullptr);
|
|
||||||
assert(a1 == nullptr);
|
|
||||||
assert(a1.raw_ptr() == nullptr);
|
|
||||||
assert(a1.raw_base() == nullptr);
|
|
||||||
assert(a1.raw_size_in_bytes() == 0u);
|
|
||||||
CHECK_THROWS(*a1);
|
|
||||||
CHECK_THROWS(a1[0]);
|
|
||||||
|
|
||||||
Span0 a2 = nullptr;
|
|
||||||
assert(a2 == nullptr);
|
|
||||||
assert(a2.raw_ptr() == nullptr);
|
|
||||||
assert(a2.raw_base() == nullptr);
|
|
||||||
assert(a2.raw_size_in_bytes() == 0u);
|
|
||||||
CHECK_THROWS(*a2);
|
|
||||||
CHECK_THROWS(a2[0]);
|
|
||||||
|
|
||||||
Span0 base0(nullptr, 4, base_buf);
|
|
||||||
assert(base0.raw_ptr() == nullptr);
|
|
||||||
assert(base0.raw_base() == base_buf);
|
|
||||||
assert(base0.raw_size_in_bytes() == 4u);
|
|
||||||
CHECK_THROWS(*base0); // nullptr
|
|
||||||
CHECK_THROWS(base0[0]); // nullptr
|
|
||||||
CHECK_THROWS(base0 + 1); // nullptr
|
|
||||||
|
|
||||||
Span0 base4(base_buf, 4);
|
|
||||||
assert(base4.raw_ptr() == base_buf);
|
|
||||||
assert(base4.raw_base() == base_buf);
|
|
||||||
assert(base4.raw_size_in_bytes() == 4u);
|
|
||||||
|
|
||||||
a1 = base_buf;
|
|
||||||
a1 = base0;
|
|
||||||
assert(a1 == nullptr);
|
|
||||||
assert(a1.raw_ptr() == nullptr);
|
|
||||||
assert(a1.raw_base() == base_buf);
|
|
||||||
assert(a1.raw_size_in_bytes() == 4u);
|
|
||||||
a1 = base4;
|
|
||||||
assert(a1 == base_buf);
|
|
||||||
assert(a1.raw_ptr() == base_buf);
|
|
||||||
assert(a1.raw_base() == base_buf);
|
|
||||||
assert(a1.raw_size_in_bytes() == 4u);
|
|
||||||
|
|
||||||
a1 = base_buf;
|
|
||||||
assert(a1 != nullptr);
|
|
||||||
a1 = base_buf + 1;
|
|
||||||
CHECK(*a1++ == 1);
|
|
||||||
CHECK(*++a1 == 3);
|
|
||||||
CHECK(*a1 == 3);
|
|
||||||
a1 = base_buf + 4; // at the end of buffer
|
|
||||||
CHECK_THROWS(*a1);
|
|
||||||
CHECK_THROWS(a1 = base_buf + 5); // range error
|
|
||||||
assert(a1 == base_buf + 4);
|
|
||||||
CHECK(a1[-4] == 0);
|
|
||||||
CHECK_THROWS(a1[-5]); // range error
|
|
||||||
a1 = base_buf;
|
|
||||||
CHECK(*a1 == 0);
|
|
||||||
|
|
||||||
Span0 new_base4(base_buf + 2, 4);
|
|
||||||
CHECK_THROWS(a1 = new_base4); // not same base
|
|
||||||
a2 = new_base4;
|
|
||||||
CHECK_THROWS(a2 = base4); // not same base
|
|
||||||
|
|
||||||
Span0 s0_no_base(nullptr);
|
|
||||||
Span0 s0_with_base(nullptr, 4, base_buf);
|
|
||||||
s0_no_base = nullptr;
|
|
||||||
s0_with_base = nullptr;
|
|
||||||
s0_with_base = s0_no_base;
|
|
||||||
assert(s0_no_base.raw_base() == nullptr);
|
|
||||||
assert(s0_with_base.raw_base() == base_buf);
|
|
||||||
s0_no_base = s0_with_base;
|
|
||||||
assert(s0_no_base.raw_base() == base_buf);
|
|
||||||
assert(s0_no_base.raw_ptr() == nullptr);
|
|
||||||
assert(s0_with_base.raw_ptr() == nullptr);
|
|
||||||
s0_no_base = my_null;
|
|
||||||
s0_with_base = my_null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
TEST_CASE("PtrOrSpan") {
|
|
||||||
char real_buf[2 + 6 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 124, 125};
|
|
||||||
char *base_buf = real_buf + 2;
|
|
||||||
char *const my_null = nullptr;
|
|
||||||
typedef PtrOrSpan<char> SpanP;
|
|
||||||
|
|
||||||
// basic nullptr
|
|
||||||
CHECK_THROWS(SpanP(base_buf, 4, base_buf) = my_null);
|
|
||||||
CHECK_THROWS(SpanP(base_buf, 4, base_buf).assign(my_null));
|
|
||||||
// basic range checking
|
|
||||||
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf));
|
|
||||||
CHECK_NOTHROW(SpanP(base_buf, 0, base_buf));
|
|
||||||
CHECK_NOTHROW(SpanP(base_buf, 0, base_buf) - 0);
|
|
||||||
CHECK_THROWS(SpanP(base_buf, 0, base_buf) + 1);
|
|
||||||
CHECK_THROWS(SpanP(base_buf, 0, base_buf) - 1);
|
|
||||||
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) + 4);
|
|
||||||
CHECK_THROWS(SpanP(base_buf, 4, base_buf) + 5);
|
|
||||||
CHECK_THROWS(SpanP(base_buf - 1, 4, base_buf));
|
|
||||||
CHECK_THROWS(SpanP(base_buf + 1, 0, base_buf));
|
|
||||||
// basic same base
|
|
||||||
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 3, base_buf));
|
|
||||||
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 1, base_buf));
|
|
||||||
CHECK_NOTHROW(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 5, base_buf));
|
|
||||||
CHECK_THROWS(SpanP(base_buf, 4, base_buf) = SpanP(base_buf + 1, 3, base_buf + 1));
|
|
||||||
|
|
||||||
SpanP x1(base_buf, 0);
|
|
||||||
assert(x1 != nullptr);
|
|
||||||
assert(x1.raw_ptr() == base_buf);
|
|
||||||
assert(x1.raw_base() == base_buf);
|
|
||||||
assert(x1.raw_size_in_bytes() == 0u);
|
|
||||||
CHECK_THROWS(*x1);
|
|
||||||
CHECK_THROWS(x1[0]);
|
|
||||||
|
|
||||||
SpanP a2 = base_buf;
|
|
||||||
assert(a2 != nullptr);
|
|
||||||
assert(a2.raw_ptr() == base_buf);
|
|
||||||
assert(a2.raw_base() == nullptr);
|
|
||||||
assert(a2.raw_size_in_bytes() == 0u);
|
|
||||||
CHECK(*a2 == 0);
|
|
||||||
CHECK(a2[1] == 1);
|
|
||||||
|
|
||||||
SpanP base0(base_buf, 4, base_buf);
|
|
||||||
assert(base0.raw_ptr() == base_buf);
|
|
||||||
assert(base0.raw_base() == base_buf);
|
|
||||||
assert(base0.raw_size_in_bytes() == 4u);
|
|
||||||
|
|
||||||
SpanP base4(base_buf, 4);
|
|
||||||
assert(base4.raw_ptr() == base_buf);
|
|
||||||
assert(base4.raw_base() == base_buf);
|
|
||||||
assert(base4.raw_size_in_bytes() == 4u);
|
|
||||||
|
|
||||||
SpanP a1(base_buf, 4);
|
|
||||||
a1 = base_buf;
|
|
||||||
a1 = base0;
|
|
||||||
assert(a1 == base0);
|
|
||||||
assert(a1 != nullptr);
|
|
||||||
assert(a1.raw_ptr() == base0.raw_ptr());
|
|
||||||
assert(a1.raw_base() == base_buf);
|
|
||||||
assert(a1.raw_size_in_bytes() == 4u);
|
|
||||||
a1 = base4;
|
|
||||||
assert(a1 == base_buf);
|
|
||||||
assert(a1.raw_ptr() == base_buf);
|
|
||||||
assert(a1.raw_base() == base_buf);
|
|
||||||
assert(a1.raw_size_in_bytes() == 4u);
|
|
||||||
|
|
||||||
a1 = base_buf;
|
|
||||||
a1 = base_buf + 1;
|
|
||||||
CHECK(*a1++ == 1);
|
|
||||||
CHECK(*++a1 == 3);
|
|
||||||
CHECK(*a1 == 3);
|
|
||||||
a1 = base_buf + 4; // at the end of buffer
|
|
||||||
CHECK_THROWS(*a1);
|
|
||||||
CHECK_THROWS(a1 = base_buf + 5); // range error
|
|
||||||
assert(a1 == base_buf + 4);
|
|
||||||
CHECK(a1[-4] == 0);
|
|
||||||
CHECK_THROWS(a1[-5]); // range error
|
|
||||||
a1 = base_buf;
|
|
||||||
CHECK(*a1 == 0);
|
|
||||||
|
|
||||||
SpanP new_base4(base_buf + 2, 4);
|
|
||||||
CHECK_THROWS(a1 = new_base4); // not same base
|
|
||||||
a2 = new_base4;
|
|
||||||
CHECK_THROWS(a2 = base4); // not same base
|
|
||||||
|
|
||||||
SpanP sp_no_base(base_buf);
|
|
||||||
SpanP sp_with_base(base_buf, 4, base_buf);
|
|
||||||
assert(sp_no_base.raw_base() == nullptr);
|
|
||||||
assert(sp_with_base.raw_base() == base_buf);
|
|
||||||
CHECK_THROWS(sp_no_base = my_null); // nullptr assignment
|
|
||||||
CHECK_THROWS(sp_with_base = my_null); // nullptr assignment
|
|
||||||
#if SPAN_CONFIG_ENABLE_SPAN_CONVERSION
|
|
||||||
typedef PtrOrSpanOrNull<char> Span0;
|
|
||||||
Span0 s0_no_base(nullptr);
|
|
||||||
Span0 s0_with_base(nullptr, 4, base_buf);
|
|
||||||
CHECK_THROWS(sp_no_base = s0_no_base); // nullptr assignment
|
|
||||||
CHECK_THROWS(sp_no_base = s0_with_base); // nullptr assignment
|
|
||||||
CHECK_THROWS(sp_with_base = s0_no_base); // nullptr assignment
|
|
||||||
CHECK_THROWS(sp_with_base = s0_with_base); // nullptr assignment
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
TEST_CASE("Span") {
|
|
||||||
char real_buf[2 + 6 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 124, 125};
|
|
||||||
char *base_buf = real_buf + 2;
|
|
||||||
char *const my_null = nullptr;
|
|
||||||
typedef Span<char> SpanS;
|
|
||||||
|
|
||||||
// basic nullptr
|
|
||||||
CHECK_THROWS(SpanS(base_buf, 4, base_buf) = my_null);
|
|
||||||
CHECK_THROWS(SpanS(base_buf, 4, base_buf).assign(my_null));
|
|
||||||
// basic range checking
|
|
||||||
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf));
|
|
||||||
CHECK_NOTHROW(SpanS(base_buf, 0, base_buf));
|
|
||||||
CHECK_NOTHROW(SpanS(base_buf, 0, base_buf) - 0);
|
|
||||||
CHECK_THROWS(SpanS(base_buf, 0, base_buf) + 1);
|
|
||||||
CHECK_THROWS(SpanS(base_buf, 0, base_buf) - 1);
|
|
||||||
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) + 4);
|
|
||||||
CHECK_THROWS(SpanS(base_buf, 4, base_buf) + 5);
|
|
||||||
CHECK_THROWS(SpanS(base_buf - 1, 4, base_buf));
|
|
||||||
CHECK_THROWS(SpanS(base_buf + 1, 0, base_buf));
|
|
||||||
// basic same base
|
|
||||||
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 3, base_buf));
|
|
||||||
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 1, base_buf));
|
|
||||||
CHECK_NOTHROW(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 5, base_buf));
|
|
||||||
CHECK_THROWS(SpanS(base_buf, 4, base_buf) = SpanS(base_buf + 1, 3, base_buf + 1));
|
|
||||||
|
|
||||||
SpanS x1(base_buf, 0);
|
|
||||||
assert(x1 != nullptr);
|
|
||||||
assert(x1.raw_ptr() == base_buf);
|
|
||||||
assert(x1.raw_base() == base_buf);
|
|
||||||
assert(x1.raw_size_in_bytes() == 0u);
|
|
||||||
CHECK_THROWS(*x1);
|
|
||||||
CHECK_THROWS(x1[0]);
|
|
||||||
|
|
||||||
SpanS a2(base_buf, 4);
|
|
||||||
assert(a2 != nullptr);
|
|
||||||
assert(a2.raw_ptr() == base_buf);
|
|
||||||
assert(a2.raw_base() == base_buf);
|
|
||||||
assert(a2.raw_size_in_bytes() == 4u);
|
|
||||||
CHECK(*a2 == 0);
|
|
||||||
CHECK(a2[1] == 1);
|
|
||||||
|
|
||||||
SpanS base0(base_buf, 4, base_buf);
|
|
||||||
assert(base0.raw_ptr() == base_buf);
|
|
||||||
assert(base0.raw_base() == base_buf);
|
|
||||||
assert(base0.raw_size_in_bytes() == 4u);
|
|
||||||
|
|
||||||
SpanS base4(base_buf, 4);
|
|
||||||
assert(base4.raw_ptr() == base_buf);
|
|
||||||
assert(base4.raw_base() == base_buf);
|
|
||||||
assert(base4.raw_size_in_bytes() == 4u);
|
|
||||||
|
|
||||||
SpanS a1(base_buf, 4);
|
|
||||||
a1 = base_buf;
|
|
||||||
a1 = base0;
|
|
||||||
assert(a1 == base0);
|
|
||||||
assert(a1 != nullptr);
|
|
||||||
assert(a1.raw_ptr() == base0.raw_ptr());
|
|
||||||
assert(a1.raw_base() == base_buf);
|
|
||||||
assert(a1.raw_size_in_bytes() == 4u);
|
|
||||||
a1 = base4;
|
|
||||||
assert(a1 == base_buf);
|
|
||||||
assert(a1.raw_ptr() == base_buf);
|
|
||||||
assert(a1.raw_base() == base_buf);
|
|
||||||
assert(a1.raw_size_in_bytes() == 4u);
|
|
||||||
|
|
||||||
a1 = base_buf;
|
|
||||||
a1 = base_buf + 1;
|
|
||||||
CHECK(*a1++ == 1);
|
|
||||||
CHECK(*++a1 == 3);
|
|
||||||
CHECK(*a1 == 3);
|
|
||||||
a1 = base_buf + 4; // at the end of buffer
|
|
||||||
CHECK_THROWS(*a1);
|
|
||||||
CHECK_THROWS(a1 = base_buf + 5); // range error
|
|
||||||
assert(a1 == base_buf + 4);
|
|
||||||
CHECK(a1[-4] == 0);
|
|
||||||
CHECK_THROWS(a1[-5]); // range error
|
|
||||||
a1 = base_buf;
|
|
||||||
CHECK(*a1 == 0);
|
|
||||||
|
|
||||||
SpanS new_base4(base_buf + 2, 4);
|
|
||||||
CHECK_THROWS(a1 = new_base4); // not same base
|
|
||||||
CHECK_THROWS(a2 = new_base4); // not same base
|
|
||||||
|
|
||||||
SpanS ss_with_base(base_buf, 4, base_buf);
|
|
||||||
assert(ss_with_base.raw_base() == base_buf);
|
|
||||||
CHECK_THROWS(ss_with_base = my_null); // nullptr assignment
|
|
||||||
#if SPAN_CONFIG_ENABLE_SPAN_CONVERSION
|
|
||||||
{
|
|
||||||
typedef PtrOrSpanOrNull<char> Span0;
|
|
||||||
// v0 nullptr, b0 base, b1 base + 1
|
|
||||||
const Span0 v0_v0(nullptr);
|
|
||||||
const Span0 v0_b0(nullptr, 4, base_buf);
|
|
||||||
const Span0 v0_b1(nullptr, 3, base_buf + 1);
|
|
||||||
const Span0 b0_v0(base_buf);
|
|
||||||
const Span0 b0_b0(base_buf, 4, base_buf);
|
|
||||||
CHECK_THROWS(SPAN_0_MAKE(char, base_buf, 3, base_buf + 1)); // b0_b1
|
|
||||||
const Span0 b1_v0(base_buf + 1);
|
|
||||||
const Span0 b1_b0(base_buf + 1, 4, base_buf);
|
|
||||||
const Span0 b1_b1(base_buf + 1, 3, base_buf + 1);
|
|
||||||
CHECK_THROWS(ss_with_base = v0_v0); // nullptr assignment
|
|
||||||
CHECK_THROWS(ss_with_base = v0_b0); // nullptr assignment
|
|
||||||
CHECK_THROWS(ss_with_base = v0_b1); // nullptr assignment
|
|
||||||
CHECK_NOTHROW(ss_with_base = b0_v0);
|
|
||||||
CHECK_NOTHROW(ss_with_base = b0_b0);
|
|
||||||
CHECK_NOTHROW(ss_with_base = b1_v0);
|
|
||||||
CHECK_NOTHROW(ss_with_base = b1_b0);
|
|
||||||
CHECK_THROWS(ss_with_base = b1_b1); // different base
|
|
||||||
CHECK_THROWS(SPAN_S_MAKE(char, v0_v0));
|
|
||||||
CHECK_THROWS(SPAN_S_MAKE(char, v0_b0));
|
|
||||||
CHECK_THROWS(SPAN_S_MAKE(char, v0_b1));
|
|
||||||
CHECK_THROWS(SPAN_S_MAKE(char, b0_v0));
|
|
||||||
CHECK_NOTHROW(SPAN_S_MAKE(char, b0_b0));
|
|
||||||
CHECK_THROWS(SPAN_S_MAKE(char, b1_v0));
|
|
||||||
CHECK_NOTHROW(SPAN_S_MAKE(char, b1_b0));
|
|
||||||
CHECK_NOTHROW(SPAN_S_MAKE(char, b1_b1));
|
|
||||||
//
|
|
||||||
CHECK((SPAN_S_MAKE(char, b0_b0).raw_base() == base_buf));
|
|
||||||
CHECK((SPAN_S_MAKE(char, b1_b0).raw_base() == base_buf));
|
|
||||||
CHECK((SPAN_S_MAKE(char, b1_b1).raw_base() == base_buf + 1));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
typedef PtrOrSpan<char> SpanP;
|
|
||||||
// v0 nullptr, b0 base, b1 base + 1
|
|
||||||
const SpanP b0_v0(base_buf);
|
|
||||||
const SpanP b0_b0(base_buf, 4, base_buf);
|
|
||||||
CHECK_THROWS(SPAN_P_MAKE(char, base_buf, 3, base_buf + 1)); // b0_b1
|
|
||||||
const SpanP b1_v0(base_buf + 1);
|
|
||||||
const SpanP b1_b0(base_buf + 1, 4, base_buf);
|
|
||||||
const SpanP b1_b1(base_buf + 1, 3, base_buf + 1);
|
|
||||||
CHECK_NOTHROW(ss_with_base = b0_v0);
|
|
||||||
CHECK_NOTHROW(ss_with_base = b0_b0);
|
|
||||||
CHECK_NOTHROW(ss_with_base = b1_v0);
|
|
||||||
CHECK_NOTHROW(ss_with_base = b1_b0);
|
|
||||||
CHECK_THROWS(ss_with_base = b1_b1); // different base
|
|
||||||
CHECK_THROWS(SPAN_S_MAKE(char, b0_v0));
|
|
||||||
CHECK_NOTHROW(SPAN_S_MAKE(char, b0_b0));
|
|
||||||
CHECK_THROWS(SPAN_S_MAKE(char, b1_v0));
|
|
||||||
CHECK_NOTHROW(SPAN_S_MAKE(char, b1_b0));
|
|
||||||
CHECK_NOTHROW(SPAN_S_MAKE(char, b1_b1));
|
|
||||||
//
|
|
||||||
CHECK((SPAN_S_MAKE(char, b0_b0).raw_base() == base_buf));
|
|
||||||
CHECK((SPAN_S_MAKE(char, b1_b0).raw_base() == base_buf));
|
|
||||||
CHECK((SPAN_S_MAKE(char, b1_b1).raw_base() == base_buf + 1));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
TEST_CASE("Span void ptr") {
|
|
||||||
static char a[4] = {0, 1, 2, 3};
|
|
||||||
SPAN_0(void) a0(a, 4);
|
|
||||||
SPAN_P(void) ap(a, 4);
|
|
||||||
SPAN_S(void) as(a, 4);
|
|
||||||
SPAN_0(const void) c0(a, 4);
|
|
||||||
SPAN_P(const void) cp(a, 4);
|
|
||||||
SPAN_S(const void) cs(a, 4);
|
|
||||||
static const char b[4] = {0, 1, 2, 3};
|
|
||||||
SPAN_0(const void) b0(b, 4);
|
|
||||||
SPAN_P(const void) bp(b, 4);
|
|
||||||
SPAN_S(const void) bs(b, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Span deref/array/arrow") {
|
|
||||||
static char real_a[2 + 4 + 2] = {126, 127, 0, 1, 2, 3, 124, 125};
|
|
||||||
static char *a = real_a + 2;
|
|
||||||
SPAN_0(char) a0(a, 4);
|
|
||||||
SPAN_P(char) ap(a, 4);
|
|
||||||
SPAN_S(char) as(a, 4);
|
|
||||||
CHECK_THROWS(a0[4]);
|
|
||||||
CHECK_THROWS(a0[-1]);
|
|
||||||
CHECK_THROWS(a0[-2]);
|
|
||||||
a0 += 2;
|
|
||||||
CHECK(*a0 == 2);
|
|
||||||
CHECK(a0[-1] == 1);
|
|
||||||
CHECK(a0[0] == 2);
|
|
||||||
CHECK(a0[1] == 3);
|
|
||||||
ap += 2;
|
|
||||||
CHECK(*ap == 2);
|
|
||||||
CHECK(ap[-1] == 1);
|
|
||||||
CHECK(ap[0] == 2);
|
|
||||||
CHECK(ap[1] == 3);
|
|
||||||
as += 2;
|
|
||||||
CHECK(*as == 2);
|
|
||||||
CHECK(as[-1] == 1);
|
|
||||||
CHECK(as[0] == 2);
|
|
||||||
CHECK(as[1] == 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Span subspan") {
|
|
||||||
static char buf[4] = {0, 1, 2, 3};
|
|
||||||
SPAN_S(char) as(buf, 4);
|
|
||||||
CHECK(as.subspan(1, 1)[0] == 1);
|
|
||||||
CHECK((as + 1).subspan(1, 1)[0] == 2);
|
|
||||||
CHECK((as + 2).subspan(0, -2)[0] == 0);
|
|
||||||
CHECK_THROWS(as.subspan(1, 0)[0]);
|
|
||||||
CHECK_THROWS(as.subspan(1, 1)[-1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Span constness") {
|
|
||||||
static char buf[4] = {0, 1, 2, 3};
|
|
||||||
|
|
||||||
SPAN_0(char) b0(buf, 4);
|
|
||||||
SPAN_P(char) bp(buf, 4);
|
|
||||||
SPAN_S(char) bs(buf, 4);
|
|
||||||
|
|
||||||
SPAN_0(char) s0(b0);
|
|
||||||
SPAN_P(char) sp(bp);
|
|
||||||
SPAN_S(char) ss(bs);
|
|
||||||
|
|
||||||
SPAN_0(const char) b0c(buf, 4);
|
|
||||||
SPAN_P(const char) bpc(buf, 4);
|
|
||||||
SPAN_S(const char) bsc(buf, 4);
|
|
||||||
|
|
||||||
SPAN_0(const char) s0c(b0c);
|
|
||||||
SPAN_P(const char) spc(bpc);
|
|
||||||
SPAN_S(const char) ssc(bsc);
|
|
||||||
|
|
||||||
SPAN_0(const char) x0c(b0);
|
|
||||||
SPAN_P(const char) xpc(bp);
|
|
||||||
SPAN_S(const char) xsc(bs);
|
|
||||||
|
|
||||||
CHECK(ptr_diff_bytes(b0, buf) == 0);
|
|
||||||
CHECK(ptr_diff_bytes(bp, buf) == 0);
|
|
||||||
CHECK(ptr_diff_bytes(bs, buf) == 0);
|
|
||||||
CHECK(ptr_diff_bytes(s0, buf) == 0);
|
|
||||||
CHECK(ptr_diff_bytes(sp, buf) == 0);
|
|
||||||
CHECK(ptr_diff_bytes(bs, buf) == 0);
|
|
||||||
//
|
|
||||||
CHECK(ptr_diff_bytes(s0, bp) == 0);
|
|
||||||
CHECK(ptr_diff_bytes(s0, sp) == 0);
|
|
||||||
CHECK(ptr_diff_bytes(s0, ss) == 0);
|
|
||||||
//
|
|
||||||
CHECK(ptr_diff_bytes(s0c, b0c) == 0);
|
|
||||||
CHECK(ptr_diff_bytes(spc, bpc) == 0);
|
|
||||||
CHECK(ptr_diff_bytes(ssc, bsc) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
#if !defined(DOCTEST_CONFIG_DISABLE)
|
|
||||||
namespace {
|
|
||||||
int my_memcmp_v1(SPAN_P(const void) a, SPAN_0(const void) b, size_t n) {
|
|
||||||
if (b == nullptr)
|
|
||||||
return -2;
|
|
||||||
SPAN_0(const void) x(a);
|
|
||||||
return memcmp(x, b, n);
|
|
||||||
}
|
|
||||||
int my_memcmp_v2(SPAN_P(const char) a, SPAN_0(const char) b, size_t n) {
|
|
||||||
if (a == b)
|
|
||||||
return 0;
|
|
||||||
if (b == nullptr)
|
|
||||||
return -2;
|
|
||||||
a += 1;
|
|
||||||
b -= 1;
|
|
||||||
SPAN_0(const char) x(a);
|
|
||||||
SPAN_0(const char) y = b;
|
|
||||||
return memcmp(x, y, n);
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TEST_CASE("PtrOrSpan") {
|
|
||||||
static const char buf[4] = {0, 1, 2, 3};
|
|
||||||
CHECK(my_memcmp_v1(buf, nullptr, 4) == -2);
|
|
||||||
CHECK(my_memcmp_v2(buf + 4, buf + 4, 999) == 0);
|
|
||||||
CHECK(my_memcmp_v2(buf, buf + 2, 3) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
//
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
TEST_CASE("PtrOrSpan char") {
|
|
||||||
char real_buf[2 + 8 + 2] = {126, 127, 0, 1, 2, 3, 4, 5, 6, 7, 124, 125};
|
|
||||||
char *buf = real_buf + 2;
|
|
||||||
SPAN_P(char) a(buf, SpanSizeInBytes(8));
|
|
||||||
SPAN_P(char) b = a.subspan(0, 7);
|
|
||||||
SPAN_P(char) c = (b + 1).subspan(0, 6);
|
|
||||||
a += 1;
|
|
||||||
CHECK(*a == 1);
|
|
||||||
*a++ += 1;
|
|
||||||
*b++ = 1;
|
|
||||||
CHECK(a == buf + 2);
|
|
||||||
CHECK(b == buf + 1);
|
|
||||||
CHECK(c == buf + 1);
|
|
||||||
CHECK(*b == 2);
|
|
||||||
CHECK(*c == 2);
|
|
||||||
CHECK(a.raw_size_in_bytes() == 8u);
|
|
||||||
CHECK(b.raw_size_in_bytes() == 7u);
|
|
||||||
CHECK(c.raw_size_in_bytes() == 6u);
|
|
||||||
CHECK(a.raw_base() == buf);
|
|
||||||
CHECK(b.raw_base() == buf);
|
|
||||||
CHECK(c.raw_base() == buf + 1);
|
|
||||||
#ifdef UPX_VERSION_HEX
|
|
||||||
CHECK(get_le32(a) != 0);
|
|
||||||
#endif
|
|
||||||
++c;
|
|
||||||
c++;
|
|
||||||
#ifdef UPX_VERSION_HEX
|
|
||||||
CHECK(get_le32(c) != 0);
|
|
||||||
#endif
|
|
||||||
++c;
|
|
||||||
#ifdef UPX_VERSION_HEX
|
|
||||||
CHECK_THROWS(get_le32(c));
|
|
||||||
#endif
|
|
||||||
++b;
|
|
||||||
b++;
|
|
||||||
b += 4;
|
|
||||||
CHECK(b.raw_ptr() == buf + 7);
|
|
||||||
CHECK_THROWS(*b);
|
|
||||||
CHECK(a.raw_size_in_bytes() == 8u);
|
|
||||||
a = b;
|
|
||||||
CHECK(a.raw_size_in_bytes() == 8u);
|
|
||||||
CHECK(a.raw_ptr() == buf + 7);
|
|
||||||
a++;
|
|
||||||
CHECK_THROWS(*a);
|
|
||||||
CHECK_THROWS(raw_bytes(a, 1));
|
|
||||||
a = b;
|
|
||||||
CHECK_THROWS(a = c);
|
|
||||||
*a = 0;
|
|
||||||
a = buf;
|
|
||||||
#ifdef UPX_VERSION_HEX
|
|
||||||
CHECK(upx_safe_strlen(a) == 7u);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("PtrOrSpan int") {
|
|
||||||
int buf[8] = {0, 1, 2, 3, 4, 5, 6, 7};
|
|
||||||
SPAN_P(int) a(buf, SpanCount(8));
|
|
||||||
CHECK(a.raw_size_in_bytes() == 8 * sizeof(int));
|
|
||||||
SPAN_P(int) b = a.subspan(0, 7);
|
|
||||||
CHECK(b.raw_size_in_bytes() == 7 * sizeof(int));
|
|
||||||
SPAN_P(int) c = (b + 1).subspan(0, 6);
|
|
||||||
CHECK(c.raw_size_in_bytes() == 6 * sizeof(int));
|
|
||||||
a += 1;
|
|
||||||
CHECK(*a == 1);
|
|
||||||
CHECK(*a++ == 1);
|
|
||||||
CHECK(*++a == 3);
|
|
||||||
CHECK(--*a == 2);
|
|
||||||
CHECK(*a-- == 2);
|
|
||||||
CHECK(*b == 0);
|
|
||||||
CHECK(*c == 1);
|
|
||||||
a = buf + 7;
|
|
||||||
#ifdef UPX_VERSION_HEX
|
|
||||||
CHECK(get_le32(a) == ne32_to_le32(7));
|
|
||||||
#endif
|
|
||||||
a++;
|
|
||||||
#ifdef UPX_VERSION_HEX
|
|
||||||
CHECK_THROWS(get_le32(a));
|
|
||||||
#endif
|
|
||||||
CHECK_THROWS(raw_bytes(a, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
// codegen
|
|
||||||
**************************************************************************/
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
template <class T>
|
|
||||||
__acc_static_noinline int foo(T p) {
|
|
||||||
unsigned r = 0;
|
|
||||||
r += *p++;
|
|
||||||
r += *++p;
|
|
||||||
p += 3;
|
|
||||||
r += *p;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
SPAN_0(T)
|
|
||||||
make_span_0(T *ptr, size_t count) {
|
|
||||||
return PtrOrSpanOrNull<T>(ptr, count);
|
|
||||||
}
|
|
||||||
template <class T>
|
|
||||||
SPAN_P(T)
|
|
||||||
make_span_p(T *ptr, size_t count) {
|
|
||||||
return PtrOrSpan<T>(ptr, count);
|
|
||||||
}
|
|
||||||
template <class T>
|
|
||||||
SPAN_S(T)
|
|
||||||
make_span_s(T *ptr, size_t count) {
|
|
||||||
return Span<T>(ptr, count);
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
TEST_CASE("Span codegen") {
|
|
||||||
char buf[8] = {0, 1, 2, 3, 4, 5, 6, 7};
|
|
||||||
CHECK(foo(buf) == 0 + 2 + 5);
|
|
||||||
CHECK(foo(make_span_0(buf, 8)) == 0 + 2 + 5);
|
|
||||||
CHECK(foo(make_span_p(buf, 8)) == 0 + 2 + 5);
|
|
||||||
CHECK(foo(make_span_s(buf, 8)) == 0 + 2 + 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // WITH_SPAN >= 2
|
|
||||||
|
|
||||||
/* vim:set ts=4 sw=4 et: */
|
/* vim:set ts=4 sw=4 et: */
|
||||||
|
@ -52,7 +52,7 @@ pointer base;
|
|||||||
size_type size_in_bytes;
|
size_type size_in_bytes;
|
||||||
|
|
||||||
// debug - internal sanity check; also serves as pseudo-documentation
|
// debug - internal sanity check; also serves as pseudo-documentation
|
||||||
#if DEBUG || 1
|
#if DEBUG
|
||||||
__acc_noinline void assertInvariants() const {
|
__acc_noinline void assertInvariants() const {
|
||||||
if __acc_cte (configRequirePtr)
|
if __acc_cte (configRequirePtr)
|
||||||
assert(ptr != nullptr);
|
assert(ptr != nullptr);
|
||||||
|
Reference in New Issue
Block a user