From ab4fe380f6f0fee107ac1adf8382e37ae24905d5 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Sun, 21 Sep 2025 01:50:02 +0200 Subject: [PATCH 01/39] Update loc_history.py --- scripts/loc_history.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/scripts/loc_history.py b/scripts/loc_history.py index 10fcabe54..40b1e7550 100644 --- a/scripts/loc_history.py +++ b/scripts/loc_history.py @@ -5,7 +5,9 @@ Requires scc tool in $PATH, then run: -python scripts/for_each_commit.py https://github.com/tobanteEmbedded/tetl --branch linalg --dest some-scratch-dir/tetl --cmd "scc -f json2 --exclude-dir arm_make -o ../out/{date}-{commit}.json ." +mkdir -p some-scratch-dir/out +python scripts/for_each_commit.py https://github.com/tobanteEmbedded/tetl --branch main --dest some-scratch-dir/tetl --cmd "scc -f json2 --exclude-dir arm_make -o ../out/{date}-{commit}.json ." +python scripts/loc_history.py some-scratch-dir/out """ import glob @@ -28,27 +30,40 @@ def main(): with open(json_dir/json_file, 'r') as f: content = json.load(f) - file_sum = 0 + total_lines = 0 + code_lines = 0 + comment_lines = 0 + blank_lines = 0 for lang in content['languageSummary']: - file_sum += lang['Lines'] + total_lines += lang['Lines'] + code_lines += lang['Code'] + comment_lines += lang['Comment'] + blank_lines += lang['Blank'] date_and_commit = json_file.stem.rsplit('-', 1) results.append({ 'date': date_and_commit[0], 'commit': date_and_commit[1], - 'lines': file_sum, + 'total': total_lines, + 'code': code_lines, + 'comment': comment_lines, + 'blank': blank_lines, }) df = pd.DataFrame.from_records(results) df['date'] = pd.to_datetime(df['date'], utc=True) - df.to_csv("loc.csv", encoding='utf-8', sep=';', index=False) + df['delta'] = df['total'].diff() print(df) print(df.dtypes) - plt.plot(df['date'], df['lines']) + plt.plot(df['date'], df['total'], label='Total') + plt.plot(df['date'], df['code'], label='Code') + plt.plot(df['date'], df['comment'], label='Comment') + plt.plot(df['date'], df['blank'], label='Blank') plt.xlabel('Date') plt.ylabel('LOC') plt.grid(which='both') + plt.legend() plt.show() From ef53b564b56753c10b7fbdd04e12034abef7ea00 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Sun, 21 Sep 2025 15:47:22 +0200 Subject: [PATCH 02/39] Rename AVR cmake toolchain file --- .github/workflows/freestanding-avr.yml | 2 +- CMakePresets.json | 2 +- CONTRIBUTING.md | 2 +- README.md | 12 ++++++------ cmake/toolchain/{atmega2560.cmake => avr-gcc.cmake} | 0 5 files changed, 9 insertions(+), 9 deletions(-) rename cmake/toolchain/{atmega2560.cmake => avr-gcc.cmake} (100%) diff --git a/.github/workflows/freestanding-avr.yml b/.github/workflows/freestanding-avr.yml index 6f050af36..a30c379b6 100644 --- a/.github/workflows/freestanding-avr.yml +++ b/.github/workflows/freestanding-avr.yml @@ -36,7 +36,7 @@ jobs: cmake -S . -B build -G "Ninja Multi-Config" - -D CMAKE_TOOLCHAIN_FILE=cmake/toolchain/atmega2560.cmake + -D CMAKE_TOOLCHAIN_FILE=cmake/toolchain/avr-gcc.cmake -D CMAKE_CXX_STANDARD=${{ matrix.cxx }} -D CMAKE_COMPILE_WARNING_AS_ERROR=ON -D TETL_BUILD_CONTRACT_CHECKS=OFF diff --git a/CMakePresets.json b/CMakePresets.json index 34af0dd0d..b5459580d 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -30,7 +30,7 @@ { "name": "avr-gcc", "description": "Configure with avr-gcc toolchain", - "toolchainFile": "${sourceDir}/cmake/toolchain/atmega2560.cmake", + "toolchainFile": "${sourceDir}/cmake/toolchain/avr-gcc.cmake", "inherits": ["_root-config"], "cacheVariables": { "TETL_BUILD_CONTRACT_CHECKS": false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index caead6a59..41200290e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,7 +21,7 @@ ctest --test-dir cmake-build-emscripten -C Debug --output-on-failure ```sh # AVR -cmake -S . -B cmake-build-avr-gcc -G "Ninja Multi-Config" -D CMAKE_TOOLCHAIN_FILE="cmake/toolchain/atmega2560.cmake" +cmake -S . -B cmake-build-avr-gcc -G "Ninja Multi-Config" -D CMAKE_TOOLCHAIN_FILE="cmake/toolchain/avr-gcc.cmake" cmake --build cmake-build-avr-gcc --config Debug ``` diff --git a/README.md b/README.md index 98e40f607..cc4aae2e9 100644 --- a/README.md +++ b/README.md @@ -55,12 +55,12 @@ For examples look at the [examples](./examples) subdirectory or the test files i ### Freestanding -| **Platform** | **Status** | **Notes** | -| :----------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------: | -| **ARM** | [![ARM](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-arm.yml/badge.svg)](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-arm.yml) | GCC 15 | -| **AVR** | [![AVR](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-avr.yml/badge.svg)](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-avr.yml) | GCC 15 | -| **MSP430** | [![MSP430](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-msp430.yml/badge.svg)](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-msp430.yml) | GCC 14 | -| **RISCV** | [![RISCV](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-riscv.yml/badge.svg)](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-riscv.yml) | GCC 15 | +| **Platform** | **Status** | **Notes** | +| :----------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------: | +| **ARM** | [![ARM](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-arm.yml/badge.svg)](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-arm.yml) | GCC 15 & Clang 20 | +| **AVR** | [![AVR](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-avr.yml/badge.svg)](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-avr.yml) | GCC 15 | +| **MSP430** | [![MSP430](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-msp430.yml/badge.svg)](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-msp430.yml) | GCC 14 | +| **RISCV** | [![RISCV](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-riscv.yml/badge.svg)](https://github.com/tobanteEmbedded/tetl/actions/workflows/freestanding-riscv.yml) | GCC 15 | ### Analysis diff --git a/cmake/toolchain/atmega2560.cmake b/cmake/toolchain/avr-gcc.cmake similarity index 100% rename from cmake/toolchain/atmega2560.cmake rename to cmake/toolchain/avr-gcc.cmake From 2320bcadf96316fd6a0e2f0d499a98edd0d808b5 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Sun, 21 Sep 2025 15:51:35 +0200 Subject: [PATCH 03/39] Rename ARM & RISCV cmake toolchain files --- .github/workflows/freestanding-arm.yml | 4 ++-- .github/workflows/freestanding-riscv.yml | 2 +- CMakePresets.json | 4 ++-- .../{clang-arm-none-eabi.cmake => arm-none-eabi-clang.cmake} | 2 +- .../{gcc-arm-none-eabi.cmake => arm-none-eabi-gcc.cmake} | 2 +- cmake/toolchain/{stm32.cmake => arm-none-eabi.cmake} | 0 .../{gcc-riscv-none-elf.cmake => riscv-none-elf-gcc.cmake} | 0 7 files changed, 7 insertions(+), 7 deletions(-) rename cmake/toolchain/{clang-arm-none-eabi.cmake => arm-none-eabi-clang.cmake} (99%) rename cmake/toolchain/{gcc-arm-none-eabi.cmake => arm-none-eabi-gcc.cmake} (98%) rename cmake/toolchain/{stm32.cmake => arm-none-eabi.cmake} (100%) rename cmake/toolchain/{gcc-riscv-none-elf.cmake => riscv-none-elf-gcc.cmake} (100%) diff --git a/.github/workflows/freestanding-arm.yml b/.github/workflows/freestanding-arm.yml index e9ac2deda..ff3bb0d72 100644 --- a/.github/workflows/freestanding-arm.yml +++ b/.github/workflows/freestanding-arm.yml @@ -46,7 +46,7 @@ jobs: -S . -B cmake-build-gcc -G "Ninja Multi-Config" - -D CMAKE_TOOLCHAIN_FILE=cmake/toolchain/gcc-arm-none-eabi.cmake + -D CMAKE_TOOLCHAIN_FILE=cmake/toolchain/arm-none-eabi-gcc.cmake -D CMAKE_CXX_STANDARD=${{ matrix.cxx }} -D CMAKE_COMPILE_WARNING_AS_ERROR=ON -D TETL_BUILD_CONTRACT_CHECKS=OFF @@ -63,7 +63,7 @@ jobs: -S . -B cmake-build-clang -G "Ninja Multi-Config" - -D CMAKE_TOOLCHAIN_FILE=cmake/toolchain/clang-arm-none-eabi.cmake + -D CMAKE_TOOLCHAIN_FILE=cmake/toolchain/arm-none-eabi-clang.cmake -D CMAKE_CXX_STANDARD=${{ matrix.cxx }} -D CMAKE_COMPILE_WARNING_AS_ERROR=ON -D TETL_BUILD_CONTRACT_CHECKS=OFF diff --git a/.github/workflows/freestanding-riscv.yml b/.github/workflows/freestanding-riscv.yml index 67acaa6cd..f5fc88700 100644 --- a/.github/workflows/freestanding-riscv.yml +++ b/.github/workflows/freestanding-riscv.yml @@ -43,7 +43,7 @@ jobs: -S . -B build -G "Ninja Multi-Config" - -D CMAKE_TOOLCHAIN_FILE=cmake/toolchain/gcc-riscv-none-elf.cmake + -D CMAKE_TOOLCHAIN_FILE=cmake/toolchain/riscv-none-elf-gcc.cmake -D CMAKE_CXX_STANDARD=${{ matrix.cxx }} -D CMAKE_COMPILE_WARNING_AS_ERROR=ON -D TETL_BUILD_CONTRACT_CHECKS=OFF diff --git a/CMakePresets.json b/CMakePresets.json index b5459580d..12c571b49 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -39,7 +39,7 @@ { "name": "arm-gcc", "description": "Configure with arm-gcc toolchain", - "toolchainFile": "${sourceDir}/cmake/toolchain/gcc-arm-none-eabi.cmake", + "toolchainFile": "${sourceDir}/cmake/toolchain/arm-none-eabi-gcc.cmake", "inherits": ["_root-config"], "cacheVariables": { "TETL_BUILD_CONTRACT_CHECKS": false @@ -48,7 +48,7 @@ { "name": "arm-clang", "description": "Configure with arm-clang toolchain", - "toolchainFile": "${sourceDir}/cmake/toolchain/clang-arm-none-eabi.cmake", + "toolchainFile": "${sourceDir}/cmake/toolchain/arm-none-eabi-clang.cmake", "inherits": ["_root-config"], "cacheVariables": { "TETL_BUILD_CONTRACT_CHECKS": false diff --git a/cmake/toolchain/clang-arm-none-eabi.cmake b/cmake/toolchain/arm-none-eabi-clang.cmake similarity index 99% rename from cmake/toolchain/clang-arm-none-eabi.cmake rename to cmake/toolchain/arm-none-eabi-clang.cmake index 227a3882f..2bcf6e32b 100644 --- a/cmake/toolchain/clang-arm-none-eabi.cmake +++ b/cmake/toolchain/arm-none-eabi-clang.cmake @@ -4,7 +4,7 @@ include_guard(GLOBAL) list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_LIST_DIR}") -include(stm32) +include(arm-none-eabi) execute_process( COMMAND arm-none-eabi-gcc ${MCU} -print-sysroot diff --git a/cmake/toolchain/gcc-arm-none-eabi.cmake b/cmake/toolchain/arm-none-eabi-gcc.cmake similarity index 98% rename from cmake/toolchain/gcc-arm-none-eabi.cmake rename to cmake/toolchain/arm-none-eabi-gcc.cmake index 497364912..a5ec798ad 100644 --- a/cmake/toolchain/gcc-arm-none-eabi.cmake +++ b/cmake/toolchain/arm-none-eabi-gcc.cmake @@ -4,7 +4,7 @@ include_guard(GLOBAL) list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_LIST_DIR}") -include(stm32) +include(arm-none-eabi) set(CMAKE_SYSTEM_PROCESSOR arm) set(CMAKE_SYSTEM_NAME Generic-ELF) diff --git a/cmake/toolchain/stm32.cmake b/cmake/toolchain/arm-none-eabi.cmake similarity index 100% rename from cmake/toolchain/stm32.cmake rename to cmake/toolchain/arm-none-eabi.cmake diff --git a/cmake/toolchain/gcc-riscv-none-elf.cmake b/cmake/toolchain/riscv-none-elf-gcc.cmake similarity index 100% rename from cmake/toolchain/gcc-riscv-none-elf.cmake rename to cmake/toolchain/riscv-none-elf-gcc.cmake From e4d1553b5a70ee1885b3a5596d1bd892dbee2b8c Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Sun, 21 Sep 2025 18:00:59 +0200 Subject: [PATCH 04/39] [chrono] Fix conversion warnings on avr clang builds --- include/etl/_chrono/weekday.hpp | 2 +- tests/chrono/calender.day.t.cpp | 2 +- tests/chrono/calender.year.t.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/etl/_chrono/weekday.hpp b/include/etl/_chrono/weekday.hpp index e05cae989..03fab157c 100644 --- a/include/etl/_chrono/weekday.hpp +++ b/include/etl/_chrono/weekday.hpp @@ -95,7 +95,7 @@ struct weekday { } private: - [[nodiscard]] static constexpr auto weekday_from_days(int tp) noexcept -> etl::uint8_t + [[nodiscard]] static constexpr auto weekday_from_days(etl::int_least32_t tp) noexcept -> etl::uint8_t { return static_cast(tp >= -4 ? (tp + 4) % 7 : ((tp + 5) % 7) + 6); } diff --git a/tests/chrono/calender.day.t.cpp b/tests/chrono/calender.day.t.cpp index b88657ed5..e38e2e83c 100644 --- a/tests/chrono/calender.day.t.cpp +++ b/tests/chrono/calender.day.t.cpp @@ -191,7 +191,7 @@ namespace chrono = etl::chrono; { // traits CHECK(etl::is_trivially_default_constructible_v); - CHECK(etl::is_nothrow_constructible_v); + CHECK(etl::is_nothrow_constructible_v); { auto const wdi = chrono::weekday_indexed{}; diff --git a/tests/chrono/calender.year.t.cpp b/tests/chrono/calender.year.t.cpp index 66a770e58..aaa9f9d3c 100644 --- a/tests/chrono/calender.year.t.cpp +++ b/tests/chrono/calender.year.t.cpp @@ -20,7 +20,7 @@ namespace chrono = etl::chrono; // traits CHECK(etl::is_trivially_default_constructible_v); - CHECK(etl::is_nothrow_constructible_v); + CHECK(etl::is_nothrow_constructible_v); CHECK(static_cast(chrono::year::min()) == -32767); CHECK(static_cast(chrono::year::max()) == +32767); From 8bd9ec1074af9b987dd23f4f2ce606ccf4b0c92a Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Sun, 21 Sep 2025 18:10:01 +0200 Subject: [PATCH 05/39] [cmath] Disable builtins for erf & log2 on clang AVR builds. Linker can't find the functions. Falling back to gcem. --- include/etl/_cmath/erf.hpp | 10 ++++++---- include/etl/_cmath/log10.hpp | 3 ++- include/etl/_cmath/log2.hpp | 13 ++++++++----- tests/cmath/cosh.t.cpp | 1 - 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/include/etl/_cmath/erf.hpp b/include/etl/_cmath/erf.hpp index 789777368..18161bd53 100644 --- a/include/etl/_cmath/erf.hpp +++ b/include/etl/_cmath/erf.hpp @@ -16,18 +16,20 @@ inline constexpr struct erf { template [[nodiscard]] constexpr auto operator()(Float arg) const noexcept -> Float { +#if not(defined(__AVR__) and defined(__clang__)) if (not is_constant_evaluated()) { -#if __has_builtin(__builtin_erff) + #if __has_builtin(__builtin_erff) if constexpr (etl::same_as) { return __builtin_erff(arg); } -#endif -#if __has_builtin(__builtin_erf) + #endif + #if __has_builtin(__builtin_erf) if constexpr (etl::same_as) { return __builtin_erf(arg); } -#endif + #endif } +#endif return etl::detail::gcem::erf(arg); } } erf; diff --git a/include/etl/_cmath/log10.hpp b/include/etl/_cmath/log10.hpp index f3dfd8a1d..43d746c28 100644 --- a/include/etl/_cmath/log10.hpp +++ b/include/etl/_cmath/log10.hpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -31,7 +32,7 @@ inline constexpr struct log10 { } #endif } - return etl::detail::gcem::log(arg) / static_cast(GCEM_LOG_10); + return etl::log(arg) / static_cast(GCEM_LOG_10); } } log10; diff --git a/include/etl/_cmath/log2.hpp b/include/etl/_cmath/log2.hpp index a964c0344..0d16aaec0 100644 --- a/include/etl/_cmath/log2.hpp +++ b/include/etl/_cmath/log2.hpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -19,19 +20,21 @@ inline constexpr struct log2 { template [[nodiscard]] constexpr auto operator()(Float arg) const noexcept -> Float { +#if not(defined(__AVR__) and defined(__clang__)) if (not is_constant_evaluated()) { -#if __has_builtin(__builtin_log2f) + #if __has_builtin(__builtin_log2f) if constexpr (etl::same_as) { return __builtin_log2f(arg); } -#endif -#if __has_builtin(__builtin_log2) + #endif + #if __has_builtin(__builtin_log2) if constexpr (etl::same_as) { return __builtin_log2(arg); } -#endif + #endif } - return etl::detail::gcem::log2(arg); +#endif + return etl::log(arg) / static_cast(GCEM_LOG_2); } } log2; diff --git a/tests/cmath/cosh.t.cpp b/tests/cmath/cosh.t.cpp index 9bad82055..a995689b5 100644 --- a/tests/cmath/cosh.t.cpp +++ b/tests/cmath/cosh.t.cpp @@ -21,7 +21,6 @@ static constexpr auto test() -> bool CHECK_APPROX(etl::cosh(T(1)), T(1.543080635)); CHECK_APPROX(etl::cosh(T(2)), T(3.762195691)); CHECK_APPROX(etl::cosh(T(4)), T(27.30823284)); - CHECK_APPROX(etl::cosh(T(8)), T(1490.479161)); return true; } From 1373775db27885d3b334f962e827c43cd9b33c61 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Sat, 27 Sep 2025 00:57:11 +0200 Subject: [PATCH 06/39] Upgrade clang-format to v21.1.2 --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1b32a4685..4fd32b6d1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v21.1.1 + rev: v21.1.2 hooks: - id: clang-format types_or: [c++, c] From d7721d924bc6a41eaae45d21f04ce98124bd2a0c Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Mon, 29 Sep 2025 21:09:53 +0200 Subject: [PATCH 07/39] Add clang ARM Toolchain for Embedded (ATfE) cmake toolchain --- cmake/toolchain/arm-atfe.cmake | 49 ++++++++++++++++++++++++++++++++++ scripts/build-atfe.sh | 17 ++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 cmake/toolchain/arm-atfe.cmake create mode 100755 scripts/build-atfe.sh diff --git a/cmake/toolchain/arm-atfe.cmake b/cmake/toolchain/arm-atfe.cmake new file mode 100644 index 000000000..367872f53 --- /dev/null +++ b/cmake/toolchain/arm-atfe.cmake @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: BSL-1.0 +# SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +include_guard(GLOBAL) + +set(ATFE_TOOLCHAIN "" CACHE STRING "Path to ARM toolchain for Embedded") + +if(NOT DEFINED ATFE_TOOLCHAIN) + message(FATAL_ERROR "Could not find ATfE. Use CMake variable ATFE_TOOLCHAIN") +else() + if(NOT EXISTS "${ATFE_TOOLCHAIN}/bin/clang") + message(FATAL_ERROR "ATFE_TOOLCHAIN does not point to a valid ATfE installation") + endif() +endif() + +set(CMAKE_SYSTEM_NAME Generic-ELF) +set(CMAKE_SYSTEM_PROCESSOR arm) + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +set(CMAKE_C_COMPILER "${ATFE_TOOLCHAIN}/bin/clang") +set(CMAKE_CXX_COMPILER "${ATFE_TOOLCHAIN}/bin/clang++") + +set(ARCH_FLAGS "--target=armv6m-none-eabi -march=armv6m -mfpu=none -mfloat-abi=soft -flto") +set(CPP_FLAGS "-fno-exceptions -fno-rtti") + +set(CMAKE_C_FLAGS_DEBUG "${ARCH_FLAGS} -O0 -g3") +set(CMAKE_CXX_FLAGS_DEBUG "${ARCH_FLAGS} ${CPP_FLAGS} -O0 -g3") + +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${ARCH_FLAGS} -O3 -g3 -DNDEBUG") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${ARCH_FLAGS} ${CPP_FLAGS} -O3 -g3 -DNDEBUG") + +set(CMAKE_C_FLAGS_RELEASE "${ARCH_FLAGS} -O3 -DNDEBUG") +set(CMAKE_CXX_FLAGS_RELEASE "${ARCH_FLAGS} ${CPP_FLAGS} -O3 -DNDEBUG") + +set(CMAKE_C_FLAGS_MINSIZEREL "${ARCH_FLAGS} -Oz -g3 -DNDEBUG") +set(CMAKE_CXX_FLAGS_MINSIZEREL "${ARCH_FLAGS} ${CPP_FLAGS} -Oz -g3 -DNDEBUG") + +add_link_options( + -nostartfiles + -lcrt0-semihost + -lsemihost + -Wl,--gc-sections + -Wl,-T "${ATFE_TOOLCHAIN}/samples/ldscripts/microbit.ld" +) diff --git a/scripts/build-atfe.sh b/scripts/build-atfe.sh new file mode 100755 index 000000000..e52decb39 --- /dev/null +++ b/scripts/build-atfe.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: BSL-1.0 +# SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +rm -rf cmake-build-atfe +cmake -S . -B cmake-build-atfe \ + -G Ninja -D CMAKE_BUILD_TYPE=Release \ + --toolchain cmake/toolchain/arm-atfe.cmake \ + -D ATFE_TOOLCHAIN=/home/tobante/bin/ATfE-21.1.1-Linux-x86_64 \ + -D CMAKE_CROSSCOMPILING_EMULATOR="qemu-system-arm;-M;microbit;-semihosting;-nographic;-kernel" \ + -D CMAKE_CXX_STANDARD=26 \ + -D CMAKE_COMPILE_WARNING_AS_ERROR=ON \ + -D CMAKE_CXX_SCAN_FOR_MODULES=OFF \ + -D TETL_BUILD_CONTRACT_CHECKS=OFF + +cmake --build cmake-build-atfe --target help +ctest --test-dir cmake-build-atfe --output-on-failure -j 16 From 32b195a3139f2d941c89186f3d17ac3d28cc8435 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Mon, 29 Sep 2025 21:10:31 +0200 Subject: [PATCH 08/39] [algorithm] Use merge_sort as default stable_sort --- include/etl/_algorithm/stable_sort.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/etl/_algorithm/stable_sort.hpp b/include/etl/_algorithm/stable_sort.hpp index 006b9d8ea..15a6a341b 100644 --- a/include/etl/_algorithm/stable_sort.hpp +++ b/include/etl/_algorithm/stable_sort.hpp @@ -4,7 +4,7 @@ #ifndef TETL_ALGORITHM_STABLE_SORT_HPP #define TETL_ALGORITHM_STABLE_SORT_HPP -#include +#include #include namespace etl { @@ -20,7 +20,7 @@ namespace etl { template constexpr auto stable_sort(RandomIt first, RandomIt last, Compare comp) -> void { - etl::insertion_sort(first, last, comp); + etl::merge_sort(first, last, comp); } template From a1f4f39e4c9c7c432eca37eab4d90b77df8de177 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Mon, 29 Sep 2025 21:12:29 +0200 Subject: [PATCH 09/39] [algorithm] Add quick_sort --- include/etl/_algorithm/gnome_sort.hpp | 8 +-- include/etl/_algorithm/insertion_sort.hpp | 7 +-- include/etl/_algorithm/merge_sort.hpp | 10 ++-- include/etl/_algorithm/quick_sort.hpp | 64 +++++++++++++++++++++++ include/etl/_algorithm/sort.hpp | 4 +- include/etl/algorithm.hpp | 1 + src/inc/algorithm.inc | 3 +- 7 files changed, 82 insertions(+), 15 deletions(-) create mode 100644 include/etl/_algorithm/quick_sort.hpp diff --git a/include/etl/_algorithm/gnome_sort.hpp b/include/etl/_algorithm/gnome_sort.hpp index be2a36570..bdbbdb84e 100644 --- a/include/etl/_algorithm/gnome_sort.hpp +++ b/include/etl/_algorithm/gnome_sort.hpp @@ -14,8 +14,8 @@ namespace etl { /// \details https://en.wikipedia.org/wiki/Gnome_sort /// \note Non-standard extension /// \ingroup algorithm -template -constexpr auto gnome_sort(BidirIt first, BidirIt last, Compare comp) -> void +template +constexpr auto gnome_sort(RandomIt first, RandomIt last, Compare comp) -> void { auto i = first; while (i != last) { @@ -32,8 +32,8 @@ constexpr auto gnome_sort(BidirIt first, BidirIt last, Compare comp) -> void /// \details https://en.wikipedia.org/wiki/Gnome_sort /// \note Non-standard extension /// \ingroup algorithm -template -constexpr auto gnome_sort(BidirIt first, BidirIt last) -> void +template +constexpr auto gnome_sort(RandomIt first, RandomIt last) -> void { etl::gnome_sort(first, last, less()); } diff --git a/include/etl/_algorithm/insertion_sort.hpp b/include/etl/_algorithm/insertion_sort.hpp index 0a74ef94f..03d2d83fd 100644 --- a/include/etl/_algorithm/insertion_sort.hpp +++ b/include/etl/_algorithm/insertion_sort.hpp @@ -6,6 +6,7 @@ #include #include +#include namespace etl { @@ -20,13 +21,13 @@ template constexpr auto insertion_sort(RandomIt first, RandomIt last, Compare comp) -> void { for (auto i = first; i != last; ++i) { - auto key = *i; + auto key = etl::move(*i); auto j = i; while (j != first and comp(key, *(j - 1))) { - *j = *(j - 1); + *j = etl::move(*(j - 1)); --j; } - *j = key; + *j = etl::move(key); } } diff --git a/include/etl/_algorithm/merge_sort.hpp b/include/etl/_algorithm/merge_sort.hpp index b051d5df6..49eb546d8 100644 --- a/include/etl/_algorithm/merge_sort.hpp +++ b/include/etl/_algorithm/merge_sort.hpp @@ -15,19 +15,19 @@ namespace etl { /// \brief Sorts the elements in the range `[first, last)` in non-descending order. /// \details https://en.wikipedia.org/wiki/Merge_sort /// \note Non-standard extension -template -constexpr auto merge_sort(BidirIt first, BidirIt last, Compare comp) -> void +template +constexpr auto merge_sort(RandomIt first, RandomIt last, Compare comp) -> void { if (last - first > 1) { - BidirIt mid = first + (last - first) / 2; + RandomIt mid = first + (last - first) / 2; etl::merge_sort(first, mid, comp); etl::merge_sort(mid, last, comp); etl::inplace_merge(first, mid, last, comp); } } -template -constexpr auto merge_sort(BidirIt first, BidirIt last) -> void +template +constexpr auto merge_sort(RandomIt first, RandomIt last) -> void { etl::merge_sort(first, last, etl::less()); } diff --git a/include/etl/_algorithm/quick_sort.hpp b/include/etl/_algorithm/quick_sort.hpp new file mode 100644 index 000000000..244db7b35 --- /dev/null +++ b/include/etl/_algorithm/quick_sort.hpp @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#ifndef TETL_ALGORITHM_QUICK_SORT_HPP +#define TETL_ALGORITHM_QUICK_SORT_HPP + +#include +#include +#include +#include + +namespace etl { + +namespace detail { + +template +constexpr auto lomuto_partition(RandomIt first, RandomIt last, Compare comp) -> RandomIt +{ + // pivot = last - 1 + auto pivot_it = etl::prev(last); + auto i = first; + + for (auto j = first; j != pivot_it; ++j) { + if (comp(*j, *pivot_it)) { + etl::iter_swap(i, j); + ++i; + } + } + + etl::iter_swap(i, pivot_it); + return i; // final pivot position +} + +} // namespace detail + +/// \ingroup algorithm +/// @{ + +/// \brief Sorts the elements in the range `[first, last)` in non-descending order. +/// \details https://en.wikipedia.org/wiki/Quick_sort +/// \note Non-standard extension +template +constexpr auto quick_sort(RandomIt first, RandomIt last, Compare comp) -> void +{ + if (first == last or etl::next(first) == last) { + return; + } + + auto pi = etl::detail::lomuto_partition(first, last, comp); + etl::quick_sort(first, pi, comp); + etl::quick_sort(etl::next(pi), last, comp); +} + +template +constexpr auto quick_sort(RandomIt first, RandomIt last) -> void +{ + etl::quick_sort(first, last, etl::less()); +} + +/// @} + +} // namespace etl + +#endif // TETL_ALGORITHM_QUICK_SORT_HPP diff --git a/include/etl/_algorithm/sort.hpp b/include/etl/_algorithm/sort.hpp index 19624cc3b..850be9b3f 100644 --- a/include/etl/_algorithm/sort.hpp +++ b/include/etl/_algorithm/sort.hpp @@ -4,7 +4,7 @@ #ifndef TETL_ALGORITHM_SORT_HPP #define TETL_ALGORITHM_SORT_HPP -#include +#include namespace etl { @@ -18,7 +18,7 @@ namespace etl { template constexpr auto sort(RandomIt first, RandomIt last, Compare comp) -> void { - etl::insertion_sort(first, last, comp); + etl::quick_sort(first, last, comp); } template diff --git a/include/etl/algorithm.hpp b/include/etl/algorithm.hpp index 56082862a..97a37854e 100644 --- a/include/etl/algorithm.hpp +++ b/include/etl/algorithm.hpp @@ -97,5 +97,6 @@ #include #include #include +#include #endif // TETL_ALGORITHM_HPP diff --git a/src/inc/algorithm.inc b/src/inc/algorithm.inc index d1f3bcfc1..65280490a 100644 --- a/src/inc/algorithm.inc +++ b/src/inc/algorithm.inc @@ -52,6 +52,7 @@ using etl::partial_sort; using etl::partition; using etl::partition_copy; using etl::partition_point; +using etl::ranges::in_fun_result; using etl::remove; using etl::remove_copy; using etl::remove_copy_if; @@ -78,7 +79,6 @@ using etl::transform; using etl::unique; using etl::unique_copy; using etl::upper_bound; -using etl::ranges::in_fun_result; // Non-standard extensions using etl::bubble_sort; @@ -86,5 +86,6 @@ using etl::exchange_sort; using etl::gnome_sort; using etl::insertion_sort; using etl::merge_sort; +using etl::quick_sort; } // namespace etl From dfc0290547d8a00a45f5aceed9549b4b27aa565b Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Tue, 30 Sep 2025 23:54:32 +0200 Subject: [PATCH 10/39] [random] Use lerp in uniform_real_distribution --- include/etl/_random/uniform_real_distribution.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/etl/_random/uniform_real_distribution.hpp b/include/etl/_random/uniform_real_distribution.hpp index 372133c13..c43b6fda1 100644 --- a/include/etl/_random/uniform_real_distribution.hpp +++ b/include/etl/_random/uniform_real_distribution.hpp @@ -4,6 +4,7 @@ #ifndef TETL_RANDOM_UNIFORM_REAL_DISTRIBUTION_HPP #define TETL_RANDOM_UNIFORM_REAL_DISTRIBUTION_HPP +#include #include #include @@ -110,10 +111,7 @@ struct uniform_real_distribution { static_assert(minBits <= 64); // x = a + u * (b - a) - auto const a = parm.a(); - auto const b = parm.b(); - auto const u = etl::generate_canonical(g); - return a + u * (b - a); + return etl::lerp(parm.a(), parm.b(), etl::generate_canonical(g)); } friend constexpr auto operator==(uniform_real_distribution const& x, uniform_real_distribution const& y) -> bool From 51038bdf78144f2d431f8741215bba07e654a358 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Tue, 30 Sep 2025 23:54:56 +0200 Subject: [PATCH 11/39] [bit] Fix conversion warning in bit_ceil --- include/etl/_bit/bit_ceil.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/etl/_bit/bit_ceil.hpp b/include/etl/_bit/bit_ceil.hpp index fd0599f98..ee24eb6b4 100644 --- a/include/etl/_bit/bit_ceil.hpp +++ b/include/etl/_bit/bit_ceil.hpp @@ -29,11 +29,11 @@ template return UInt{1}; } if constexpr (is_same_v) { - return UInt{1U} << bit_width(UInt{x - 1U}); + return UInt{1U} << bit_width(x - UInt{1U}); } else { // for types subject to integral promotion auto o = etl::numeric_limits::digits - etl::numeric_limits::digits; - return UInt{1U << (bit_width(UInt{x - 1U}) + o) >> o}; + return static_cast(1U << (bit_width(static_cast(x - 1U)) + o) >> o); } } From 3369259397215ee1cb6c73c021617d5e64aff28b Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Tue, 30 Sep 2025 23:55:36 +0200 Subject: [PATCH 12/39] [fuzzing] Use CMake for fuzz builds --- fuzzing/.gitignore | 10 - fuzzing/CMakeLists.txt | 58 +++++ fuzzing/Makefile | 41 ---- fuzzing/{src => include}/fuzzing.hpp | 0 fuzzing/include/sorting.hpp | 43 ++++ fuzzing/run.sh | 32 +++ fuzzing/src/algorithm.bubble_sort.fuzz.cpp | 6 + fuzzing/src/algorithm.equal.fuzz.cpp | 39 ++++ fuzzing/src/algorithm.exchange_sort.fuzz.cpp | 6 + fuzzing/src/algorithm.fuzz.cpp | 215 ------------------ fuzzing/src/algorithm.gnome_sort.fuzz.cpp | 6 + fuzzing/src/algorithm.insertion_sort.fuzz.cpp | 6 + fuzzing/src/algorithm.max_element.fuzz.cpp | 37 +++ fuzzing/src/algorithm.merge_sort.fuzz.cpp | 6 + fuzzing/src/algorithm.mismatch.fuzz.cpp | 38 ++++ fuzzing/src/algorithm.quick_sort.fuzz.cpp | 6 + fuzzing/src/algorithm.search.fuzz.cpp | 38 ++++ fuzzing/src/bit.bit_ceil.fuzz.cpp | 32 +++ fuzzing/src/bit.bit_floor.fuzz.cpp | 32 +++ fuzzing/src/bit.bit_width.fuzz.cpp | 32 +++ fuzzing/src/bit.byteswap.fuzz.cpp | 32 +++ fuzzing/src/bit.countl_one.fuzz.cpp | 32 +++ fuzzing/src/bit.countl_zero.fuzz.cpp | 32 +++ fuzzing/src/bit.countr_one.fuzz.cpp | 32 +++ fuzzing/src/bit.countr_zero.fuzz.cpp | 32 +++ fuzzing/src/bit.has_single_bit.fuzz.cpp | 33 +++ fuzzing/src/bit.popcount.fuzz.cpp | 34 +++ ....fuzz.cpp => charconv.from_chars.fuzz.cpp} | 0 ...rs.fuzz.cpp => charconv.to_chars.fuzz.cpp} | 0 .../random.uniform_int_distribution.fuzz.cpp | 53 +++++ .../random.uniform_real_distribution.fuzz.cpp | 44 ++++ fuzzing/src/string.fuzz.cpp | 42 ++++ 32 files changed, 783 insertions(+), 266 deletions(-) delete mode 100644 fuzzing/.gitignore create mode 100644 fuzzing/CMakeLists.txt delete mode 100644 fuzzing/Makefile rename fuzzing/{src => include}/fuzzing.hpp (100%) create mode 100644 fuzzing/include/sorting.hpp create mode 100755 fuzzing/run.sh create mode 100644 fuzzing/src/algorithm.bubble_sort.fuzz.cpp create mode 100644 fuzzing/src/algorithm.equal.fuzz.cpp create mode 100644 fuzzing/src/algorithm.exchange_sort.fuzz.cpp delete mode 100644 fuzzing/src/algorithm.fuzz.cpp create mode 100644 fuzzing/src/algorithm.gnome_sort.fuzz.cpp create mode 100644 fuzzing/src/algorithm.insertion_sort.fuzz.cpp create mode 100644 fuzzing/src/algorithm.max_element.fuzz.cpp create mode 100644 fuzzing/src/algorithm.merge_sort.fuzz.cpp create mode 100644 fuzzing/src/algorithm.mismatch.fuzz.cpp create mode 100644 fuzzing/src/algorithm.quick_sort.fuzz.cpp create mode 100644 fuzzing/src/algorithm.search.fuzz.cpp create mode 100644 fuzzing/src/bit.bit_ceil.fuzz.cpp create mode 100644 fuzzing/src/bit.bit_floor.fuzz.cpp create mode 100644 fuzzing/src/bit.bit_width.fuzz.cpp create mode 100644 fuzzing/src/bit.byteswap.fuzz.cpp create mode 100644 fuzzing/src/bit.countl_one.fuzz.cpp create mode 100644 fuzzing/src/bit.countl_zero.fuzz.cpp create mode 100644 fuzzing/src/bit.countr_one.fuzz.cpp create mode 100644 fuzzing/src/bit.countr_zero.fuzz.cpp create mode 100644 fuzzing/src/bit.has_single_bit.fuzz.cpp create mode 100644 fuzzing/src/bit.popcount.fuzz.cpp rename fuzzing/src/{from_chars.fuzz.cpp => charconv.from_chars.fuzz.cpp} (100%) rename fuzzing/src/{to_chars.fuzz.cpp => charconv.to_chars.fuzz.cpp} (100%) create mode 100644 fuzzing/src/random.uniform_int_distribution.fuzz.cpp create mode 100644 fuzzing/src/random.uniform_real_distribution.fuzz.cpp create mode 100644 fuzzing/src/string.fuzz.cpp diff --git a/fuzzing/.gitignore b/fuzzing/.gitignore deleted file mode 100644 index 0a8cf6703..000000000 --- a/fuzzing/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: BSL-1.0 -# SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch -/crash-* -/lcov -/build -/bin -/*.info -/*.gcda -/*.gcno -/*.profraw diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt new file mode 100644 index 000000000..05ad80db9 --- /dev/null +++ b/fuzzing/CMakeLists.txt @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: BSL-1.0 +# SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch +cmake_minimum_required(VERSION 3.28) +project(tetl-fuzzing LANGUAGES CXX) + +if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) + message(FATAL_ERROR "tetl-fuzzing needs to build with clang & libFuzzer") +endif() + +find_program(CCACHE ccache) +if(CCACHE) + set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE}) + set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE}) +endif() + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=fuzzer,address,undefined -ftest-coverage -fcoverage-mapping -fprofile-arcs -fprofile-instr-generate") +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +enable_testing() + +function(tetl_add_fuzz_test _target) + set(target_name "${_target}.fuzz") + + add_executable(${target_name} "src/${target_name}.cpp") + target_include_directories(${target_name} PRIVATE "./include" "../include") + + add_test(NAME "${target_name}" COMMAND ${target_name} -max_total_time=10) + set_tests_properties("${target_name}" PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=raw/%p-%m.profraw") +endfunction() + +tetl_add_fuzz_test("algorithm.bubble_sort") +tetl_add_fuzz_test("algorithm.equal") +tetl_add_fuzz_test("algorithm.exchange_sort") +tetl_add_fuzz_test("algorithm.gnome_sort") +tetl_add_fuzz_test("algorithm.insertion_sort") +tetl_add_fuzz_test("algorithm.max_element") +tetl_add_fuzz_test("algorithm.merge_sort") +tetl_add_fuzz_test("algorithm.mismatch") +tetl_add_fuzz_test("algorithm.quick_sort") +tetl_add_fuzz_test("algorithm.search") +tetl_add_fuzz_test("bit.bit_ceil") +tetl_add_fuzz_test("bit.bit_floor") +tetl_add_fuzz_test("bit.bit_width") +tetl_add_fuzz_test("bit.byteswap") +tetl_add_fuzz_test("bit.countl_one") +tetl_add_fuzz_test("bit.countl_zero") +tetl_add_fuzz_test("bit.countr_one") +tetl_add_fuzz_test("bit.countr_zero") +tetl_add_fuzz_test("bit.has_single_bit") +tetl_add_fuzz_test("bit.popcount") +tetl_add_fuzz_test("bitset") +tetl_add_fuzz_test("charconv.from_chars") +tetl_add_fuzz_test("charconv.to_chars") +tetl_add_fuzz_test("random.uniform_int_distribution") +tetl_add_fuzz_test("random.uniform_real_distribution") +tetl_add_fuzz_test("string_view") +tetl_add_fuzz_test("string") diff --git a/fuzzing/Makefile b/fuzzing/Makefile deleted file mode 100644 index 57432e3c8..000000000 --- a/fuzzing/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -# SPDX-License-Identifier: BSL-1.0 -# SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch - -CXX = clang++-21 -CXXFLAGS = -std=c++26 -g3 -O1 -fsanitize=fuzzer,address,undefined -ftest-coverage -fcoverage-mapping -fprofile-arcs -fprofile-instr-generate -LCOV = lcov --gcov-tool ../scripts/llvm-gcov.sh -MAXTIME ?= 20 - -.PHONY: bin -bin: - mkdir -p bin - -.PHONY: build -build: bin - $(CXX) $(CXXFLAGS) -I ../include -o bin/algorithm.fuzz src/algorithm.fuzz.cpp - $(CXX) $(CXXFLAGS) -I ../include -o bin/bitset.fuzz src/bitset.fuzz.cpp - $(CXX) $(CXXFLAGS) -I ../include -o bin/from_chars.fuzz src/from_chars.fuzz.cpp - $(CXX) $(CXXFLAGS) -I ../include -o bin/string_view.fuzz src/string_view.fuzz.cpp - $(CXX) $(CXXFLAGS) -I ../include -o bin/to_chars.fuzz src/to_chars.fuzz.cpp - -.PHONY: fuzz -fuzz: build - $(LCOV) -c -i -d . --base-directory . -o bin/base_cov.info --ignore-errors inconsistent - LLVM_PROFILE_FILE="bin/%p-%m.profraw" ./bin/algorithm.fuzz -max_total_time=$(MAXTIME) - LLVM_PROFILE_FILE="bin/%p-%m.profraw" ./bin/bitset.fuzz -max_total_time=$(MAXTIME) - LLVM_PROFILE_FILE="bin/%p-%m.profraw" ./bin/from_chars.fuzz -max_total_time=$(MAXTIME) - LLVM_PROFILE_FILE="bin/%p-%m.profraw" ./bin/string_view.fuzz -max_total_time=$(MAXTIME) - LLVM_PROFILE_FILE="bin/%p-%m.profraw" ./bin/to_chars.fuzz -max_total_time=$(MAXTIME) - $(LCOV) -c -d . --base-directory . -o bin/fuzz_cov.info --ignore-errors inconsistent - $(LCOV) -a bin/base_cov.info -a bin/fuzz_cov.info -o bin/cov.info --ignore-errors inconsistent - $(LCOV) --remove bin/cov.info "*clang*" -o bin/cov.info --ignore-errors inconsistent - $(LCOV) --remove bin/cov.info "*c++*" -o bin/cov.info --ignore-errors inconsistent - - -.PHONY: report -report: fuzz - genhtml bin/cov.info --output-directory lcov --ignore-errors inconsistent - -.PHONY: clean -clean: - rm -rf bin lcov *.profraw diff --git a/fuzzing/src/fuzzing.hpp b/fuzzing/include/fuzzing.hpp similarity index 100% rename from fuzzing/src/fuzzing.hpp rename to fuzzing/include/fuzzing.hpp diff --git a/fuzzing/include/sorting.hpp b/fuzzing/include/sorting.hpp new file mode 100644 index 000000000..f7e46ca13 --- /dev/null +++ b/fuzzing/include/sorting.hpp @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch +#pragma once + +#include "fuzzing.hpp" + +#include +#include +#include + +#include +#include + +[[nodiscard]] inline auto test_sort(FuzzedDataProvider& p, auto sorter) -> int +{ + auto data = p.ConsumeRemainingBytes(); + auto view = etl::span{data.data(), data.size()}; + + sorter(view.begin(), view.end(), etl::less()); + if (not std::is_sorted(view.begin(), view.end(), etl::less())) { + std::println("Data is not sorted via etl::less. Size = {}", view.size()); + return 1; + } + + sorter(view.begin(), view.end(), etl::greater()); + if (not std::is_sorted(view.begin(), view.end(), etl::greater())) { + std::println("Data is not sorted via etl::greater. Size = {}", view.size()); + return 1; + } + + return 0; +} + +#define SORT_FUZZ_MAIN(sorter) \ + extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int \ + { \ + if (size == 0) { \ + return 0; \ + } \ + auto p = FuzzedDataProvider{data, size}; \ + RUN(test_sort(p, [](auto f, auto l, auto cmp) { sorter(f, l, cmp); })); \ + return 0; \ + } diff --git a/fuzzing/run.sh b/fuzzing/run.sh new file mode 100755 index 000000000..a281a9b42 --- /dev/null +++ b/fuzzing/run.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# SPDX-License-Identifier: BSL-1.0 +# SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +set -e + +export CC="clang-21" +export CXX="clang++-21" + +export CXXFLAGS="-march=native" +export CMAKE_BUILD_TYPE="RelWithDebInfo" +export CMAKE_GENERATOR="Ninja" + +BUILD_DIR="cmake-build-fuzzing" +BRANCH_COVERAGE=1 + +rm -rf "$BUILD_DIR" + +cmake -S fuzzing -B "$BUILD_DIR" -D CMAKE_CXX_STANDARD=26 -D CMAKE_CXX_SCAN_FOR_MODULES=OFF +cmake --build "$BUILD_DIR" + +lcov --gcov-tool ./scripts/llvm-gcov.sh -c -i -d "$BUILD_DIR" --base-directory fuzzing -o "$BUILD_DIR/base_cov.info" --ignore-errors inconsistent --rc branch_coverage=$BRANCH_COVERAGE + +ctest --test-dir "$BUILD_DIR" --output-on-failure -j $(nproc) + +lcov --gcov-tool ./scripts/llvm-gcov.sh -c -d "$BUILD_DIR" --base-directory fuzzing -o "$BUILD_DIR/fuzz_cov.info" --ignore-errors inconsistent --rc branch_coverage=$BRANCH_COVERAGE +lcov --gcov-tool ./scripts/llvm-gcov.sh -a "$BUILD_DIR/base_cov.info" -a "$BUILD_DIR/fuzz_cov.info" -o "$BUILD_DIR/cov.info" --ignore-errors inconsistent --rc branch_coverage=$BRANCH_COVERAGE +lcov --gcov-tool ./scripts/llvm-gcov.sh --remove "$BUILD_DIR/cov.info" "*fuzzing*" -o "$BUILD_DIR/cov.info" --ignore-errors inconsistent --rc branch_coverage=$BRANCH_COVERAGE +lcov --gcov-tool ./scripts/llvm-gcov.sh --remove "$BUILD_DIR/cov.info" "*clang*" -o "$BUILD_DIR/cov.info" --ignore-errors inconsistent --rc branch_coverage=$BRANCH_COVERAGE +lcov --gcov-tool ./scripts/llvm-gcov.sh --remove "$BUILD_DIR/cov.info" "*c++*" -o "$BUILD_DIR/cov.info" --ignore-errors inconsistent --rc branch_coverage=$BRANCH_COVERAGE + +genhtml "$BUILD_DIR/cov.info" --output-directory "$BUILD_DIR/html" --ignore-errors inconsistent --rc genhtml_branch_coverage=$BRANCH_COVERAGE diff --git a/fuzzing/src/algorithm.bubble_sort.fuzz.cpp b/fuzzing/src/algorithm.bubble_sort.fuzz.cpp new file mode 100644 index 000000000..82681c7f7 --- /dev/null +++ b/fuzzing/src/algorithm.bubble_sort.fuzz.cpp @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "sorting.hpp" + +SORT_FUZZ_MAIN(etl::bubble_sort) diff --git a/fuzzing/src/algorithm.equal.fuzz.cpp b/fuzzing/src/algorithm.equal.fuzz.cpp new file mode 100644 index 000000000..96de4311a --- /dev/null +++ b/fuzzing/src/algorithm.equal.fuzz.cpp @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include +#include + +#include + +template +[[nodiscard]] auto fuzz_equal(FuzzedDataProvider& p) -> int +{ + auto generator = [&p] { return p.ConsumeIntegral(); }; + auto lhs = etl::static_vector{}; + etl::generate_n(etl::back_inserter(lhs), lhs.capacity(), generator); + + auto rhs = etl::static_vector{}; + etl::generate_n(etl::back_inserter(rhs), rhs.capacity(), generator); + + auto e = etl::equal(begin(lhs), end(lhs), begin(rhs), end(rhs)); + auto s = std::equal(begin(lhs), end(lhs), begin(rhs), end(rhs)); + if (e != s) { + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_equal(p)); + return 0; +} diff --git a/fuzzing/src/algorithm.exchange_sort.fuzz.cpp b/fuzzing/src/algorithm.exchange_sort.fuzz.cpp new file mode 100644 index 000000000..db49861ef --- /dev/null +++ b/fuzzing/src/algorithm.exchange_sort.fuzz.cpp @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "sorting.hpp" + +SORT_FUZZ_MAIN(etl::exchange_sort) diff --git a/fuzzing/src/algorithm.fuzz.cpp b/fuzzing/src/algorithm.fuzz.cpp deleted file mode 100644 index 7e6b9debb..000000000 --- a/fuzzing/src/algorithm.fuzz.cpp +++ /dev/null @@ -1,215 +0,0 @@ -// SPDX-License-Identifier: BSL-1.0 -// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch - -#include "fuzzing.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -template -[[nodiscard]] auto test_sort_integers(FuzzedDataProvider& p) -> int -{ - auto generator = [&p] { return p.ConsumeIntegral(); }; - auto vec = etl::static_vector{}; - etl::generate_n(etl::back_inserter(vec), vec.capacity(), generator); - - auto etlSet = etl::static_set{begin(vec), end(vec)}; - auto stdSet = std::set{begin(vec), end(vec)}; - if (etlSet.size() != stdSet.size()) { - return 1; - } - - etl::sort(begin(vec), end(vec)); - if (not etl::is_sorted(begin(vec), end(vec))) { - return 1; - } - - return 0; -} - -template -[[nodiscard]] auto test_sort_floats(FuzzedDataProvider& p) -> int -{ - auto generator = [&p] { return p.ConsumeFloatingPoint(); }; - auto vec = etl::static_vector{}; - etl::generate_n(etl::back_inserter(vec), vec.capacity(), generator); - - auto etlSet = etl::static_set{begin(vec), end(vec)}; - auto stdSet = std::set{begin(vec), end(vec)}; - if (etlSet.size() != stdSet.size()) { - return 1; - } - - etl::sort(begin(vec), end(vec)); - if (not etl::is_sorted(begin(vec), end(vec))) { - return 1; - } - - return 0; -} - -template -[[nodiscard]] auto test_search_integers(FuzzedDataProvider& p) -> int -{ - auto generator = [&p] { return p.ConsumeIntegral(); }; - auto src = etl::static_vector{}; - etl::generate_n(etl::back_inserter(src), src.capacity(), generator); - - auto objs = etl::static_vector{}; - etl::generate_n(etl::back_inserter(objs), objs.capacity(), generator); - - auto e = etl::search(begin(src), end(src), begin(objs), end(objs)); - auto s = std::search(begin(src), end(src), begin(objs), end(objs)); - if (e != s) { - return 1; - } - - return 0; -} - -template -[[nodiscard]] auto test_mismatch_integers(FuzzedDataProvider& p) -> int -{ - auto generator = [&p] { return p.ConsumeIntegral(); }; - auto src = etl::static_vector{}; - etl::generate_n(etl::back_inserter(src), src.capacity(), generator); - - auto objs = etl::static_vector{}; - etl::generate_n(etl::back_inserter(objs), objs.capacity(), generator); - - auto e = etl::mismatch(begin(src), end(src), begin(objs), end(objs)); - auto s = std::mismatch(begin(src), end(src), begin(objs), end(objs)); - if ((e.first != s.first) or (e.second != s.second)) { - return 1; - } - - return 0; -} - -template -[[nodiscard]] auto test_max_element_integers(FuzzedDataProvider& p) -> int -{ - auto generator = [&p] { return p.ConsumeIntegral(); }; - auto src = etl::static_vector{}; - etl::generate_n(etl::back_inserter(src), src.capacity(), generator); - - auto e = etl::max_element(begin(src), end(src)); - auto s = std::max_element(begin(src), end(src)); - if (e != s) { - return 1; - } - - return 0; -} - -template -[[nodiscard]] auto test_equal_integers(FuzzedDataProvider& p) -> int -{ - auto generator = [&p] { return p.ConsumeIntegral(); }; - auto lhs = etl::static_vector{}; - etl::generate_n(etl::back_inserter(lhs), lhs.capacity(), generator); - - auto rhs = etl::static_vector{}; - etl::generate_n(etl::back_inserter(rhs), rhs.capacity(), generator); - - auto e = etl::equal(begin(lhs), end(lhs), begin(rhs), end(rhs)); - auto s = std::equal(begin(lhs), end(lhs), begin(rhs), end(rhs)); - if (e != s) { - return 1; - } - - return 0; -} - -[[nodiscard]] auto test_string(FuzzedDataProvider& p) -> int -{ - auto const chars = p.ConsumeBytesWithTerminator(127, 0); - - auto etlString = etl::inplace_string<128>{}; - etl::copy(chars.begin(), chars.end(), etl::back_inserter(etlString)); - - auto stdString = std::string{chars.begin(), chars.end()}; - - if (etlString.size() != stdString.size()) { - return 1; - } - if (etl::strlen(chars.data()) != std::strlen(chars.data())) { - return 1; - } - - return 0; -} - -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int -{ - if (size == 0) { - return 0; - } - auto p = FuzzedDataProvider{data, size}; - - RUN(test_sort_integers(p)); - RUN(test_sort_integers(p)); - RUN(test_sort_integers(p)); - RUN(test_sort_integers(p)); - - RUN(test_sort_integers(p)); - RUN(test_sort_integers(p)); - RUN(test_sort_integers(p)); - RUN(test_sort_integers(p)); - - RUN(test_sort_floats(p)); - RUN(test_sort_floats(p)); - RUN(test_sort_floats(p)); - - RUN(test_search_integers(p)); - RUN(test_search_integers(p)); - RUN(test_search_integers(p)); - RUN(test_search_integers(p)); - - RUN(test_search_integers(p)); - RUN(test_search_integers(p)); - RUN(test_search_integers(p)); - RUN(test_search_integers(p)); - - RUN(test_mismatch_integers(p)); - RUN(test_mismatch_integers(p)); - RUN(test_mismatch_integers(p)); - RUN(test_mismatch_integers(p)); - - RUN(test_mismatch_integers(p)); - RUN(test_mismatch_integers(p)); - RUN(test_mismatch_integers(p)); - RUN(test_mismatch_integers(p)); - - RUN(test_max_element_integers(p)); - RUN(test_max_element_integers(p)); - RUN(test_max_element_integers(p)); - RUN(test_max_element_integers(p)); - - RUN(test_max_element_integers(p)); - RUN(test_max_element_integers(p)); - RUN(test_max_element_integers(p)); - RUN(test_max_element_integers(p)); - - RUN(test_equal_integers(p)); - RUN(test_equal_integers(p)); - RUN(test_equal_integers(p)); - RUN(test_equal_integers(p)); - - RUN(test_equal_integers(p)); - RUN(test_equal_integers(p)); - RUN(test_equal_integers(p)); - RUN(test_equal_integers(p)); - - RUN(test_string(p)); - - return 0; -} diff --git a/fuzzing/src/algorithm.gnome_sort.fuzz.cpp b/fuzzing/src/algorithm.gnome_sort.fuzz.cpp new file mode 100644 index 000000000..a5eaa160e --- /dev/null +++ b/fuzzing/src/algorithm.gnome_sort.fuzz.cpp @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "sorting.hpp" + +SORT_FUZZ_MAIN(etl::gnome_sort) diff --git a/fuzzing/src/algorithm.insertion_sort.fuzz.cpp b/fuzzing/src/algorithm.insertion_sort.fuzz.cpp new file mode 100644 index 000000000..f484f3274 --- /dev/null +++ b/fuzzing/src/algorithm.insertion_sort.fuzz.cpp @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "sorting.hpp" + +SORT_FUZZ_MAIN(etl::insertion_sort) diff --git a/fuzzing/src/algorithm.max_element.fuzz.cpp b/fuzzing/src/algorithm.max_element.fuzz.cpp new file mode 100644 index 000000000..d12ed03c0 --- /dev/null +++ b/fuzzing/src/algorithm.max_element.fuzz.cpp @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include +#include + +#include + +template +[[nodiscard]] auto fuzz_max_element(FuzzedDataProvider& p) -> int +{ + auto generator = [&p] { return p.ConsumeIntegral(); }; + auto src = etl::static_vector{}; + etl::generate_n(etl::back_inserter(src), src.capacity(), generator); + + auto e = etl::max_element(begin(src), end(src)); + auto s = std::max_element(begin(src), end(src)); + if (e != s) { + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_max_element(p)); + + return 0; +} diff --git a/fuzzing/src/algorithm.merge_sort.fuzz.cpp b/fuzzing/src/algorithm.merge_sort.fuzz.cpp new file mode 100644 index 000000000..6f28524d9 --- /dev/null +++ b/fuzzing/src/algorithm.merge_sort.fuzz.cpp @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "sorting.hpp" + +SORT_FUZZ_MAIN(etl::merge_sort) diff --git a/fuzzing/src/algorithm.mismatch.fuzz.cpp b/fuzzing/src/algorithm.mismatch.fuzz.cpp new file mode 100644 index 000000000..7d56b752f --- /dev/null +++ b/fuzzing/src/algorithm.mismatch.fuzz.cpp @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include +#include + +template +[[nodiscard]] auto fuzz_mismatch(FuzzedDataProvider& p) -> int +{ + auto generator = [&p] { return p.ConsumeIntegral(); }; + auto src = etl::static_vector{}; + etl::generate_n(etl::back_inserter(src), src.capacity(), generator); + + auto objs = etl::static_vector{}; + etl::generate_n(etl::back_inserter(objs), objs.capacity(), generator); + + auto e = etl::mismatch(src.begin(), src.end(), objs.begin(), objs.end()); + auto s = std::mismatch(src.begin(), src.end(), objs.begin(), objs.end()); + if ((e.first != s.first) or (e.second != s.second)) { + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_mismatch(p)); + + return 0; +} diff --git a/fuzzing/src/algorithm.quick_sort.fuzz.cpp b/fuzzing/src/algorithm.quick_sort.fuzz.cpp new file mode 100644 index 000000000..a585b373d --- /dev/null +++ b/fuzzing/src/algorithm.quick_sort.fuzz.cpp @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "sorting.hpp" + +SORT_FUZZ_MAIN(etl::quick_sort) diff --git a/fuzzing/src/algorithm.search.fuzz.cpp b/fuzzing/src/algorithm.search.fuzz.cpp new file mode 100644 index 000000000..250d33f88 --- /dev/null +++ b/fuzzing/src/algorithm.search.fuzz.cpp @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include +#include + +template +[[nodiscard]] auto fuzz_search(FuzzedDataProvider& p) -> int +{ + auto generator = [&p] { return p.ConsumeIntegral(); }; + auto src = etl::static_vector{}; + etl::generate_n(etl::back_inserter(src), src.capacity(), generator); + + auto objs = etl::static_vector{}; + etl::generate_n(etl::back_inserter(objs), objs.capacity(), generator); + + auto e = etl::search(src.begin(), src.end(), objs.begin(), objs.end()); + auto s = std::search(src.begin(), src.end(), objs.begin(), objs.end()); + if (e != s) { + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_search(p)); + + return 0; +} diff --git a/fuzzing/src/bit.bit_ceil.fuzz.cpp b/fuzzing/src/bit.bit_ceil.fuzz.cpp new file mode 100644 index 000000000..059b380d5 --- /dev/null +++ b/fuzzing/src/bit.bit_ceil.fuzz.cpp @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include + +template +[[nodiscard]] auto fuzz_bit_ceil(FuzzedDataProvider& p) -> int +{ + auto const num = p.ConsumeIntegral(); + auto const s = std::bit_ceil(num); + auto const e = etl::bit_ceil(num); + return (e != s) ? 1 : 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_bit_ceil(p)); + RUN(fuzz_bit_ceil(p)); + RUN(fuzz_bit_ceil(p)); + RUN(fuzz_bit_ceil(p)); + RUN(fuzz_bit_ceil(p)); + return 0; +} diff --git a/fuzzing/src/bit.bit_floor.fuzz.cpp b/fuzzing/src/bit.bit_floor.fuzz.cpp new file mode 100644 index 000000000..a6d9f86bd --- /dev/null +++ b/fuzzing/src/bit.bit_floor.fuzz.cpp @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include + +template +[[nodiscard]] auto fuzz_bit_floor(FuzzedDataProvider& p) -> int +{ + auto const num = p.ConsumeIntegral(); + auto const s = std::bit_floor(num); + auto const e = etl::bit_floor(num); + return (e != s) ? 1 : 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_bit_floor(p)); + RUN(fuzz_bit_floor(p)); + RUN(fuzz_bit_floor(p)); + RUN(fuzz_bit_floor(p)); + RUN(fuzz_bit_floor(p)); + return 0; +} diff --git a/fuzzing/src/bit.bit_width.fuzz.cpp b/fuzzing/src/bit.bit_width.fuzz.cpp new file mode 100644 index 000000000..676726eee --- /dev/null +++ b/fuzzing/src/bit.bit_width.fuzz.cpp @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include + +template +[[nodiscard]] auto fuzz_bit_width(FuzzedDataProvider& p) -> int +{ + auto const num = p.ConsumeIntegral(); + auto const s = std::bit_width(num); + auto const e = etl::bit_width(num); + return (e != s) ? 1 : 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_bit_width(p)); + RUN(fuzz_bit_width(p)); + RUN(fuzz_bit_width(p)); + RUN(fuzz_bit_width(p)); + RUN(fuzz_bit_width(p)); + return 0; +} diff --git a/fuzzing/src/bit.byteswap.fuzz.cpp b/fuzzing/src/bit.byteswap.fuzz.cpp new file mode 100644 index 000000000..88dc0d400 --- /dev/null +++ b/fuzzing/src/bit.byteswap.fuzz.cpp @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include + +#include + +template +[[nodiscard]] auto fuzz_byteswap(FuzzedDataProvider& p) -> int +{ + auto const num = p.ConsumeIntegral(); + auto const s = std::byteswap(num); + auto const e = etl::byteswap(num); + auto const f = etl::detail::byteswap_fallback(num); + return (e != s or f != s) ? 1 : 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_byteswap(p)); + RUN(fuzz_byteswap(p)); + RUN(fuzz_byteswap(p)); + return 0; +} diff --git a/fuzzing/src/bit.countl_one.fuzz.cpp b/fuzzing/src/bit.countl_one.fuzz.cpp new file mode 100644 index 000000000..33beb6cfa --- /dev/null +++ b/fuzzing/src/bit.countl_one.fuzz.cpp @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include + +template +[[nodiscard]] auto fuzz_countl_one(FuzzedDataProvider& p) -> int +{ + auto const num = p.ConsumeIntegral(); + auto const s = std::countl_one(num); + auto const e = etl::countl_one(num); + return (e != s) ? 1 : 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_countl_one(p)); + RUN(fuzz_countl_one(p)); + RUN(fuzz_countl_one(p)); + RUN(fuzz_countl_one(p)); + RUN(fuzz_countl_one(p)); + return 0; +} diff --git a/fuzzing/src/bit.countl_zero.fuzz.cpp b/fuzzing/src/bit.countl_zero.fuzz.cpp new file mode 100644 index 000000000..c89d9803e --- /dev/null +++ b/fuzzing/src/bit.countl_zero.fuzz.cpp @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include + +template +[[nodiscard]] auto fuzz_countl_zero(FuzzedDataProvider& p) -> int +{ + auto const num = p.ConsumeIntegral(); + auto const s = std::countl_zero(num); + auto const e = etl::countl_zero(num); + return (e != s) ? 1 : 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_countl_zero(p)); + RUN(fuzz_countl_zero(p)); + RUN(fuzz_countl_zero(p)); + RUN(fuzz_countl_zero(p)); + RUN(fuzz_countl_zero(p)); + return 0; +} diff --git a/fuzzing/src/bit.countr_one.fuzz.cpp b/fuzzing/src/bit.countr_one.fuzz.cpp new file mode 100644 index 000000000..e98f1019f --- /dev/null +++ b/fuzzing/src/bit.countr_one.fuzz.cpp @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include + +template +[[nodiscard]] auto fuzz_countr_one(FuzzedDataProvider& p) -> int +{ + auto const num = p.ConsumeIntegral(); + auto const s = std::countr_one(num); + auto const e = etl::countr_one(num); + return (e != s) ? 1 : 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_countr_one(p)); + RUN(fuzz_countr_one(p)); + RUN(fuzz_countr_one(p)); + RUN(fuzz_countr_one(p)); + RUN(fuzz_countr_one(p)); + return 0; +} diff --git a/fuzzing/src/bit.countr_zero.fuzz.cpp b/fuzzing/src/bit.countr_zero.fuzz.cpp new file mode 100644 index 000000000..9f7d7c291 --- /dev/null +++ b/fuzzing/src/bit.countr_zero.fuzz.cpp @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include + +template +[[nodiscard]] auto fuzz_countr_zero(FuzzedDataProvider& p) -> int +{ + auto const num = p.ConsumeIntegral(); + auto const s = std::countr_zero(num); + auto const e = etl::countr_zero(num); + return (e != s) ? 1 : 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_countr_zero(p)); + RUN(fuzz_countr_zero(p)); + RUN(fuzz_countr_zero(p)); + RUN(fuzz_countr_zero(p)); + RUN(fuzz_countr_zero(p)); + return 0; +} diff --git a/fuzzing/src/bit.has_single_bit.fuzz.cpp b/fuzzing/src/bit.has_single_bit.fuzz.cpp new file mode 100644 index 000000000..f292af96a --- /dev/null +++ b/fuzzing/src/bit.has_single_bit.fuzz.cpp @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include + +template +[[nodiscard]] auto fuzz_has_single_bit(FuzzedDataProvider& p) -> int +{ + auto const num = p.ConsumeIntegral(); + auto const s = std::has_single_bit(num); + auto const e = etl::has_single_bit(num); + + return (e != s) ? 1 : 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_has_single_bit(p)); + RUN(fuzz_has_single_bit(p)); + RUN(fuzz_has_single_bit(p)); + RUN(fuzz_has_single_bit(p)); + RUN(fuzz_has_single_bit(p)); + return 0; +} diff --git a/fuzzing/src/bit.popcount.fuzz.cpp b/fuzzing/src/bit.popcount.fuzz.cpp new file mode 100644 index 000000000..667070cbc --- /dev/null +++ b/fuzzing/src/bit.popcount.fuzz.cpp @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include + +template +[[nodiscard]] auto fuzz_popcount(FuzzedDataProvider& p) -> int +{ + auto const num = p.ConsumeIntegral(); + auto const s = std::popcount(num); + auto const e = etl::popcount(num); + auto const f = etl::detail::popcount_fallback(num); + + return (e != s or f != s) ? 1 : 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_popcount(p)); + RUN(fuzz_popcount(p)); + RUN(fuzz_popcount(p)); + RUN(fuzz_popcount(p)); + RUN(fuzz_popcount(p)); + return 0; +} diff --git a/fuzzing/src/from_chars.fuzz.cpp b/fuzzing/src/charconv.from_chars.fuzz.cpp similarity index 100% rename from fuzzing/src/from_chars.fuzz.cpp rename to fuzzing/src/charconv.from_chars.fuzz.cpp diff --git a/fuzzing/src/to_chars.fuzz.cpp b/fuzzing/src/charconv.to_chars.fuzz.cpp similarity index 100% rename from fuzzing/src/to_chars.fuzz.cpp rename to fuzzing/src/charconv.to_chars.fuzz.cpp diff --git a/fuzzing/src/random.uniform_int_distribution.fuzz.cpp b/fuzzing/src/random.uniform_int_distribution.fuzz.cpp new file mode 100644 index 000000000..181574fd2 --- /dev/null +++ b/fuzzing/src/random.uniform_int_distribution.fuzz.cpp @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include + +#include + +template +[[nodiscard]] auto fuzz_uniform_int_distribution(FuzzedDataProvider& p) -> int +{ + static constexpr auto min = etl::numeric_limits::lowest(); + static constexpr auto max = etl::numeric_limits::max(); + + auto const dist_min = p.ConsumeIntegralInRange(min, max); + if (dist_min == max) { + return 0; + } + + auto const dist_max = p.ConsumeIntegralInRange(dist_min, max); + if (dist_min == dist_max) { + return 0; + } + + auto urng = etl::xoshiro128plusplus{p.ConsumeIntegral()}; + auto dist = etl::uniform_int_distribution{dist_min, dist_max}; + + auto const val = dist(urng); + return (val < dist_min or val > dist_max) ? 1 : 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + + auto p = FuzzedDataProvider{data, size}; + + RUN(fuzz_uniform_int_distribution(p)); + RUN(fuzz_uniform_int_distribution(p)); + // RUN(fuzz_uniform_int_distribution(p)); + // RUN(fuzz_uniform_int_distribution(p)); + + RUN(fuzz_uniform_int_distribution(p)); + RUN(fuzz_uniform_int_distribution(p)); + // RUN(fuzz_uniform_int_distribution(p)); + // RUN(fuzz_uniform_int_distribution(p)); + + return 0; +} diff --git a/fuzzing/src/random.uniform_real_distribution.fuzz.cpp b/fuzzing/src/random.uniform_real_distribution.fuzz.cpp new file mode 100644 index 000000000..f28ff33a8 --- /dev/null +++ b/fuzzing/src/random.uniform_real_distribution.fuzz.cpp @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include + +#include + +template +[[nodiscard]] auto fuzz_uniform_real_distribution(FuzzedDataProvider& p) -> int +{ + static constexpr auto min = etl::numeric_limits::lowest(); + static constexpr auto max = etl::numeric_limits::max(); + + auto const dist_min = p.ConsumeFloatingPointInRange(min, max); + auto const dist_max = p.ConsumeFloatingPointInRange(min, max); + if (dist_max <= dist_min) { + return 0; + } + + auto urng = etl::xoshiro128starstar{p.ConsumeIntegral()}; + auto dist = etl::uniform_real_distribution{dist_min, dist_max}; + if (auto const val = dist(urng); val < dist_min or val > dist_max) { + std::println("dist_min: {}, dist_max: {}, val: {}", dist_min, dist_max, val); + return 1; + } + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + + auto p = FuzzedDataProvider{data, size}; + + RUN(fuzz_uniform_real_distribution(p)); + RUN(fuzz_uniform_real_distribution(p)); + + return 0; +} diff --git a/fuzzing/src/string.fuzz.cpp b/fuzzing/src/string.fuzz.cpp new file mode 100644 index 000000000..530d391c8 --- /dev/null +++ b/fuzzing/src/string.fuzz.cpp @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include +#include +#include + +#include + +[[nodiscard]] auto test_string(FuzzedDataProvider& p) -> int +{ + auto const chars = p.ConsumeBytesWithTerminator(127, 0); + + auto etlString = etl::inplace_string<128>{}; + etl::copy(chars.begin(), chars.end(), etl::back_inserter(etlString)); + + auto stdString = std::string{chars.begin(), chars.end()}; + + if (etlString.size() != stdString.size()) { + return 1; + } + if (etl::strlen(chars.data()) != std::strlen(chars.data())) { + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + auto p = FuzzedDataProvider{data, size}; + + RUN(test_string(p)); + + return 0; +} From e47e85c5cc83fab85310acb69499e7f4d783de86 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Wed, 1 Oct 2025 00:52:52 +0200 Subject: [PATCH 13/39] [algorithm] Fix exchange_sort for empty ranges --- include/etl/_algorithm/exchange_sort.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/etl/_algorithm/exchange_sort.hpp b/include/etl/_algorithm/exchange_sort.hpp index c555b2498..48434086d 100644 --- a/include/etl/_algorithm/exchange_sort.hpp +++ b/include/etl/_algorithm/exchange_sort.hpp @@ -18,6 +18,10 @@ namespace etl { template constexpr auto exchange_sort(RandomIt first, RandomIt last, Compare comp) -> void { + if (first == last) { + return; + } + for (auto i = first; i < etl::prev(last); ++i) { for (auto j = etl::next(i); j < last; ++j) { if (comp(*j, *i)) { From 19f22cdd8205a8a06196f570e5d995e60eba09a1 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Wed, 1 Oct 2025 00:53:39 +0200 Subject: [PATCH 14/39] [fuzzing] More tests --- fuzzing/CMakeLists.txt | 18 ++++++++ fuzzing/include/sorting.hpp | 3 -- fuzzing/src/algorithm.adjacent_find.fuzz.cpp | 30 +++++++++++++ fuzzing/src/algorithm.binary_search.fuzz.cpp | 31 +++++++++++++ fuzzing/src/algorithm.is_permutation.fuzz.cpp | 33 ++++++++++++++ ...algorithm.lexicographical_compare.fuzz.cpp | 33 ++++++++++++++ fuzzing/src/cmath.lerp.fuzz.cpp | 45 +++++++++++++++++++ 7 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 fuzzing/src/algorithm.adjacent_find.fuzz.cpp create mode 100644 fuzzing/src/algorithm.binary_search.fuzz.cpp create mode 100644 fuzzing/src/algorithm.is_permutation.fuzz.cpp create mode 100644 fuzzing/src/algorithm.lexicographical_compare.fuzz.cpp create mode 100644 fuzzing/src/cmath.lerp.fuzz.cpp diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index 05ad80db9..11286d950 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -24,16 +24,33 @@ function(tetl_add_fuzz_test _target) add_executable(${target_name} "src/${target_name}.cpp") target_include_directories(${target_name} PRIVATE "./include" "../include") + target_compile_options(${target_name} PRIVATE + "-Werror" + "-Weverything" + "-Wno-c++98-compat-pedantic" + "-Wno-c++98-compat" + "-Wno-ctad-maybe-unsupported" + "-Wno-exit-time-destructors" + "-Wno-float-equal" + "-Wno-implicit-int-conversion" + "-Wno-missing-prototypes" + "-Wno-padded" + "-Wno-unsafe-buffer-usage" + ) add_test(NAME "${target_name}" COMMAND ${target_name} -max_total_time=10) set_tests_properties("${target_name}" PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=raw/%p-%m.profraw") endfunction() +tetl_add_fuzz_test("algorithm.adjacent_find") tetl_add_fuzz_test("algorithm.bubble_sort") +tetl_add_fuzz_test("algorithm.binary_search") tetl_add_fuzz_test("algorithm.equal") tetl_add_fuzz_test("algorithm.exchange_sort") tetl_add_fuzz_test("algorithm.gnome_sort") tetl_add_fuzz_test("algorithm.insertion_sort") +tetl_add_fuzz_test("algorithm.is_permutation") +tetl_add_fuzz_test("algorithm.lexicographical_compare") tetl_add_fuzz_test("algorithm.max_element") tetl_add_fuzz_test("algorithm.merge_sort") tetl_add_fuzz_test("algorithm.mismatch") @@ -52,6 +69,7 @@ tetl_add_fuzz_test("bit.popcount") tetl_add_fuzz_test("bitset") tetl_add_fuzz_test("charconv.from_chars") tetl_add_fuzz_test("charconv.to_chars") +tetl_add_fuzz_test("cmath.lerp") tetl_add_fuzz_test("random.uniform_int_distribution") tetl_add_fuzz_test("random.uniform_real_distribution") tetl_add_fuzz_test("string_view") diff --git a/fuzzing/include/sorting.hpp b/fuzzing/include/sorting.hpp index f7e46ca13..91fbc5f27 100644 --- a/fuzzing/include/sorting.hpp +++ b/fuzzing/include/sorting.hpp @@ -34,9 +34,6 @@ #define SORT_FUZZ_MAIN(sorter) \ extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int \ { \ - if (size == 0) { \ - return 0; \ - } \ auto p = FuzzedDataProvider{data, size}; \ RUN(test_sort(p, [](auto f, auto l, auto cmp) { sorter(f, l, cmp); })); \ return 0; \ diff --git a/fuzzing/src/algorithm.adjacent_find.fuzz.cpp b/fuzzing/src/algorithm.adjacent_find.fuzz.cpp new file mode 100644 index 000000000..029067deb --- /dev/null +++ b/fuzzing/src/algorithm.adjacent_find.fuzz.cpp @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include + +#include + +[[nodiscard]] static auto fuzz_adjacent_find(FuzzedDataProvider& p) -> int +{ + auto const bytes = p.ConsumeRemainingBytes(); + auto const view = etl::span{bytes.data(), bytes.size()}; + + auto const e = etl::adjacent_find(view.begin(), view.end()); + auto const s = std::adjacent_find(view.begin(), view.end()); + if (e != s) { + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_adjacent_find(p)); + return 0; +} diff --git a/fuzzing/src/algorithm.binary_search.fuzz.cpp b/fuzzing/src/algorithm.binary_search.fuzz.cpp new file mode 100644 index 000000000..4a9b9bdf8 --- /dev/null +++ b/fuzzing/src/algorithm.binary_search.fuzz.cpp @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include + +#include + +[[nodiscard]] static auto fuzz_binary_search(FuzzedDataProvider& p) -> int +{ + auto const needle = p.ConsumeIntegral(); + auto const haystack = p.ConsumeRemainingBytes(); + auto const view = etl::span{haystack.data(), haystack.size()}; + + auto const e = etl::binary_search(view.begin(), view.end(), needle); + auto const s = std::binary_search(view.begin(), view.end(), needle); + if (e != s) { + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_binary_search(p)); + return 0; +} diff --git a/fuzzing/src/algorithm.is_permutation.fuzz.cpp b/fuzzing/src/algorithm.is_permutation.fuzz.cpp new file mode 100644 index 000000000..60f351bad --- /dev/null +++ b/fuzzing/src/algorithm.is_permutation.fuzz.cpp @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include + +#include + +[[nodiscard]] static auto fuzz_is_permutation(FuzzedDataProvider& p) -> int +{ + auto const a = p.ConsumeBytes(64); + auto const b = p.ConsumeBytes(64); + + auto const va = etl::span{a.data(), a.size()}; + auto const vb = etl::span{b.data(), b.size()}; + + auto const e = etl::is_permutation(va.begin(), va.end(), vb.begin(), vb.end()); + auto const s = std::is_permutation(va.begin(), va.end(), vb.begin(), vb.end()); + if (e != s) { + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_is_permutation(p)); + return 0; +} diff --git a/fuzzing/src/algorithm.lexicographical_compare.fuzz.cpp b/fuzzing/src/algorithm.lexicographical_compare.fuzz.cpp new file mode 100644 index 000000000..7163641b9 --- /dev/null +++ b/fuzzing/src/algorithm.lexicographical_compare.fuzz.cpp @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include + +#include + +[[nodiscard]] static auto fuzz_lexicographical_compare(FuzzedDataProvider& p) -> int +{ + auto const a = p.ConsumeBytes(64); + auto const b = p.ConsumeBytes(64); + + auto const va = etl::span{a.data(), a.size()}; + auto const vb = etl::span{b.data(), b.size()}; + + auto const e = etl::lexicographical_compare(va.begin(), va.end(), vb.begin(), vb.end()); + auto const s = std::lexicographical_compare(va.begin(), va.end(), vb.begin(), vb.end()); + if (e != s) { + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_lexicographical_compare(p)); + return 0; +} diff --git a/fuzzing/src/cmath.lerp.fuzz.cpp b/fuzzing/src/cmath.lerp.fuzz.cpp new file mode 100644 index 000000000..a994834db --- /dev/null +++ b/fuzzing/src/cmath.lerp.fuzz.cpp @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include + +template +[[nodiscard]] auto fuzz_lerp(FuzzedDataProvider& p) -> int +{ + auto const a = p.ConsumeFloatingPoint(); + auto const b = p.ConsumeFloatingPoint(); + auto const t = p.ConsumeFloatingPoint(); + + auto const s = std::lerp(a, b, t); + auto const e = etl::lerp(a, b, t); + + if (std::isfinite(s) != std::isfinite(e)) { + return 1; + } + + if (std::isnan(s) or std::isinf(s)) { + return 0; + } + + if (s != e) { + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + if (size == 0) { + return 0; + } + + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_lerp(p)); + RUN(fuzz_lerp(p)); + return 0; +} From 6275b58dc1e9e0d379aa9427167149e3ed4dc854 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Thu, 2 Oct 2025 14:30:02 +0200 Subject: [PATCH 15/39] [fuzzing] More algorithm & string_view tests --- fuzzing/CMakeLists.txt | 21 ++++- fuzzing/run.sh | 2 +- fuzzing/src/algorithm.equal_range.fuzz.cpp | 31 +++++++ fuzzing/src/algorithm.max_element.fuzz.cpp | 19 ++--- fuzzing/src/algorithm.min_element.fuzz.cpp | 30 +++++++ fuzzing/src/algorithm.minmax_element.fuzz.cpp | 30 +++++++ fuzzing/src/algorithm.mismatch.fuzz.cpp | 4 - fuzzing/src/algorithm.partition.fuzz.cpp | 38 +++++++++ fuzzing/src/algorithm.search.fuzz.cpp | 12 ++- fuzzing/src/algorithm.shift_left.fuzz.cpp | 41 ++++++++++ fuzzing/src/algorithm.shift_right.fuzz.cpp | 41 ++++++++++ fuzzing/src/bit.bit_ceil.fuzz.cpp | 4 - fuzzing/src/bit.bit_floor.fuzz.cpp | 4 - fuzzing/src/bit.bit_width.fuzz.cpp | 4 - fuzzing/src/bit.byteswap.fuzz.cpp | 4 - fuzzing/src/bit.countl_one.fuzz.cpp | 4 - fuzzing/src/bit.countl_zero.fuzz.cpp | 4 - fuzzing/src/bit.countr_one.fuzz.cpp | 4 - fuzzing/src/bit.countr_zero.fuzz.cpp | 4 - fuzzing/src/bit.has_single_bit.fuzz.cpp | 4 - fuzzing/src/bit.popcount.fuzz.cpp | 4 - fuzzing/src/bitset.fuzz.cpp | 17 ++-- fuzzing/src/numeric.midpoint.fuzz.cpp | 49 +++++++++++ fuzzing/src/string_view.contains.fuzz.cpp | 35 ++++++++ fuzzing/src/string_view.ends_with.fuzz.cpp | 35 ++++++++ fuzzing/src/string_view.find.fuzz.cpp | 35 ++++++++ .../string_view.find_first_not_of.fuzz.cpp | 35 ++++++++ .../src/string_view.find_first_of.fuzz.cpp | 35 ++++++++ .../src/string_view.find_last_not_of.fuzz.cpp | 35 ++++++++ fuzzing/src/string_view.find_last_of.fuzz.cpp | 35 ++++++++ fuzzing/src/string_view.fuzz.cpp | 82 ------------------- fuzzing/src/string_view.rfind.fuzz.cpp | 35 ++++++++ fuzzing/src/string_view.starts_with.fuzz.cpp | 35 ++++++++ include/etl/_algorithm/shift_right.hpp | 22 +++-- 34 files changed, 625 insertions(+), 169 deletions(-) create mode 100644 fuzzing/src/algorithm.equal_range.fuzz.cpp create mode 100644 fuzzing/src/algorithm.min_element.fuzz.cpp create mode 100644 fuzzing/src/algorithm.minmax_element.fuzz.cpp create mode 100644 fuzzing/src/algorithm.partition.fuzz.cpp create mode 100644 fuzzing/src/algorithm.shift_left.fuzz.cpp create mode 100644 fuzzing/src/algorithm.shift_right.fuzz.cpp create mode 100644 fuzzing/src/numeric.midpoint.fuzz.cpp create mode 100644 fuzzing/src/string_view.contains.fuzz.cpp create mode 100644 fuzzing/src/string_view.ends_with.fuzz.cpp create mode 100644 fuzzing/src/string_view.find.fuzz.cpp create mode 100644 fuzzing/src/string_view.find_first_not_of.fuzz.cpp create mode 100644 fuzzing/src/string_view.find_first_of.fuzz.cpp create mode 100644 fuzzing/src/string_view.find_last_not_of.fuzz.cpp create mode 100644 fuzzing/src/string_view.find_last_of.fuzz.cpp delete mode 100644 fuzzing/src/string_view.fuzz.cpp create mode 100644 fuzzing/src/string_view.rfind.fuzz.cpp create mode 100644 fuzzing/src/string_view.starts_with.fuzz.cpp diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index 11286d950..b3e8669d5 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -38,13 +38,14 @@ function(tetl_add_fuzz_test _target) "-Wno-unsafe-buffer-usage" ) - add_test(NAME "${target_name}" COMMAND ${target_name} -max_total_time=10) + add_test(NAME "${target_name}" COMMAND ${target_name} -max_total_time=60) set_tests_properties("${target_name}" PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=raw/%p-%m.profraw") endfunction() tetl_add_fuzz_test("algorithm.adjacent_find") -tetl_add_fuzz_test("algorithm.bubble_sort") tetl_add_fuzz_test("algorithm.binary_search") +tetl_add_fuzz_test("algorithm.bubble_sort") +tetl_add_fuzz_test("algorithm.equal_range") tetl_add_fuzz_test("algorithm.equal") tetl_add_fuzz_test("algorithm.exchange_sort") tetl_add_fuzz_test("algorithm.gnome_sort") @@ -53,9 +54,14 @@ tetl_add_fuzz_test("algorithm.is_permutation") tetl_add_fuzz_test("algorithm.lexicographical_compare") tetl_add_fuzz_test("algorithm.max_element") tetl_add_fuzz_test("algorithm.merge_sort") +tetl_add_fuzz_test("algorithm.min_element") +tetl_add_fuzz_test("algorithm.minmax_element") tetl_add_fuzz_test("algorithm.mismatch") +tetl_add_fuzz_test("algorithm.partition") tetl_add_fuzz_test("algorithm.quick_sort") tetl_add_fuzz_test("algorithm.search") +tetl_add_fuzz_test("algorithm.shift_left") +# tetl_add_fuzz_test("algorithm.shift_right") tetl_add_fuzz_test("bit.bit_ceil") tetl_add_fuzz_test("bit.bit_floor") tetl_add_fuzz_test("bit.bit_width") @@ -70,7 +76,16 @@ tetl_add_fuzz_test("bitset") tetl_add_fuzz_test("charconv.from_chars") tetl_add_fuzz_test("charconv.to_chars") tetl_add_fuzz_test("cmath.lerp") +tetl_add_fuzz_test("numeric.midpoint") tetl_add_fuzz_test("random.uniform_int_distribution") tetl_add_fuzz_test("random.uniform_real_distribution") -tetl_add_fuzz_test("string_view") +tetl_add_fuzz_test("string_view.contains") +tetl_add_fuzz_test("string_view.ends_with") +tetl_add_fuzz_test("string_view.find_first_of") +tetl_add_fuzz_test("string_view.find_first_not_of") +# tetl_add_fuzz_test("string_view.find_last_of") +tetl_add_fuzz_test("string_view.find_last_not_of") +tetl_add_fuzz_test("string_view.find") +tetl_add_fuzz_test("string_view.rfind") +tetl_add_fuzz_test("string_view.starts_with") tetl_add_fuzz_test("string") diff --git a/fuzzing/run.sh b/fuzzing/run.sh index a281a9b42..ca79c435a 100755 --- a/fuzzing/run.sh +++ b/fuzzing/run.sh @@ -12,7 +12,7 @@ export CMAKE_BUILD_TYPE="RelWithDebInfo" export CMAKE_GENERATOR="Ninja" BUILD_DIR="cmake-build-fuzzing" -BRANCH_COVERAGE=1 +BRANCH_COVERAGE=0 rm -rf "$BUILD_DIR" diff --git a/fuzzing/src/algorithm.equal_range.fuzz.cpp b/fuzzing/src/algorithm.equal_range.fuzz.cpp new file mode 100644 index 000000000..73f792667 --- /dev/null +++ b/fuzzing/src/algorithm.equal_range.fuzz.cpp @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include + +#include + +[[nodiscard]] auto fuzz_equal_range(FuzzedDataProvider& p) -> int +{ + auto const needle = p.ConsumeIntegral(); + auto const bytes = p.ConsumeRemainingBytes(); + auto const view = etl::span{bytes.data(), bytes.size()}; + + auto const [el, eu] = etl::equal_range(view.begin(), view.end(), needle); + auto const [sl, su] = std::equal_range(view.begin(), view.end(), needle); + if (el != sl or eu != su) { + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_equal_range(p)); + return 0; +} diff --git a/fuzzing/src/algorithm.max_element.fuzz.cpp b/fuzzing/src/algorithm.max_element.fuzz.cpp index d12ed03c0..3354a52e5 100644 --- a/fuzzing/src/algorithm.max_element.fuzz.cpp +++ b/fuzzing/src/algorithm.max_element.fuzz.cpp @@ -4,20 +4,17 @@ #include "fuzzing.hpp" #include -#include -#include +#include #include -template [[nodiscard]] auto fuzz_max_element(FuzzedDataProvider& p) -> int { - auto generator = [&p] { return p.ConsumeIntegral(); }; - auto src = etl::static_vector{}; - etl::generate_n(etl::back_inserter(src), src.capacity(), generator); + auto const bytes = p.ConsumeRemainingBytes(); + auto const view = etl::span{bytes.data(), bytes.size()}; - auto e = etl::max_element(begin(src), end(src)); - auto s = std::max_element(begin(src), end(src)); + auto const e = etl::max_element(view.begin(), view.end()); + auto const s = std::max_element(view.begin(), view.end()); if (e != s) { return 1; } @@ -27,11 +24,7 @@ template extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int { - if (size == 0) { - return 0; - } auto p = FuzzedDataProvider{data, size}; - RUN(fuzz_max_element(p)); - + RUN(fuzz_max_element(p)); return 0; } diff --git a/fuzzing/src/algorithm.min_element.fuzz.cpp b/fuzzing/src/algorithm.min_element.fuzz.cpp new file mode 100644 index 000000000..bf5a109f8 --- /dev/null +++ b/fuzzing/src/algorithm.min_element.fuzz.cpp @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include + +#include + +[[nodiscard]] auto fuzz_min_element(FuzzedDataProvider& p) -> int +{ + auto const bytes = p.ConsumeRemainingBytes(); + auto const view = etl::span{bytes.data(), bytes.size()}; + + auto const e = etl::min_element(view.begin(), view.end()); + auto const s = std::min_element(view.begin(), view.end()); + if (e != s) { + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_min_element(p)); + return 0; +} diff --git a/fuzzing/src/algorithm.minmax_element.fuzz.cpp b/fuzzing/src/algorithm.minmax_element.fuzz.cpp new file mode 100644 index 000000000..a19aae950 --- /dev/null +++ b/fuzzing/src/algorithm.minmax_element.fuzz.cpp @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include + +#include + +[[nodiscard]] auto fuzz_minmax_element(FuzzedDataProvider& p) -> int +{ + auto const bytes = p.ConsumeRemainingBytes(); + auto const view = etl::span{bytes.data(), bytes.size()}; + + auto const [emin, emax] = etl::minmax_element(view.begin(), view.end()); + auto const [smin, smax] = std::minmax_element(view.begin(), view.end()); + if (emin != smin or emax != smax) { + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_minmax_element(p)); + return 0; +} diff --git a/fuzzing/src/algorithm.mismatch.fuzz.cpp b/fuzzing/src/algorithm.mismatch.fuzz.cpp index 7d56b752f..f9d90a723 100644 --- a/fuzzing/src/algorithm.mismatch.fuzz.cpp +++ b/fuzzing/src/algorithm.mismatch.fuzz.cpp @@ -28,11 +28,7 @@ template extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int { - if (size == 0) { - return 0; - } auto p = FuzzedDataProvider{data, size}; RUN(fuzz_mismatch(p)); - return 0; } diff --git a/fuzzing/src/algorithm.partition.fuzz.cpp b/fuzzing/src/algorithm.partition.fuzz.cpp new file mode 100644 index 000000000..6733c278e --- /dev/null +++ b/fuzzing/src/algorithm.partition.fuzz.cpp @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include + +#include + +[[nodiscard]] auto fuzz_partition(FuzzedDataProvider& p) -> int +{ + auto ebytes = p.ConsumeRemainingBytes(); + auto sbytes = ebytes; + + auto const eview = etl::span{ebytes.data(), ebytes.size()}; + auto const sview = etl::span{sbytes.data(), sbytes.size()}; + + auto const predicate = [](unsigned char x) -> bool { return x < 42; }; + auto const e = etl::partition(eview.begin(), eview.end(), predicate); + auto const s = std::partition(sview.begin(), sview.end(), predicate); + if (std::distance(eview.begin(), e) != std::distance(sview.begin(), s)) { + return 1; + } + + if (not etl::is_partitioned(eview.begin(), eview.end(), predicate)) { + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_partition(p)); + return 0; +} diff --git a/fuzzing/src/algorithm.search.fuzz.cpp b/fuzzing/src/algorithm.search.fuzz.cpp index 250d33f88..a3b5f8267 100644 --- a/fuzzing/src/algorithm.search.fuzz.cpp +++ b/fuzzing/src/algorithm.search.fuzz.cpp @@ -4,6 +4,7 @@ #include "fuzzing.hpp" #include +#include #include #include @@ -17,9 +18,10 @@ template auto objs = etl::static_vector{}; etl::generate_n(etl::back_inserter(objs), objs.capacity(), generator); - auto e = etl::search(src.begin(), src.end(), objs.begin(), objs.end()); - auto s = std::search(src.begin(), src.end(), objs.begin(), objs.end()); - if (e != s) { + auto const s = std::search(src.begin(), src.end(), objs.begin(), objs.end()); + auto const e = etl::search(src.begin(), src.end(), objs.begin(), objs.end()); + auto const d = etl::search(src.begin(), src.end(), etl::default_searcher(objs.begin(), objs.end())); + if (e != s or d != s) { return 1; } @@ -28,11 +30,7 @@ template extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int { - if (size == 0) { - return 0; - } auto p = FuzzedDataProvider{data, size}; RUN(fuzz_search(p)); - return 0; } diff --git a/fuzzing/src/algorithm.shift_left.fuzz.cpp b/fuzzing/src/algorithm.shift_left.fuzz.cpp new file mode 100644 index 000000000..e4357e891 --- /dev/null +++ b/fuzzing/src/algorithm.shift_left.fuzz.cpp @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include +#include +#include + +#include +#include + +[[nodiscard]] auto fuzz_shift_left(FuzzedDataProvider& p) -> int +{ + auto shift = p.ConsumeIntegralInRange(0, etl::numeric_limits::max()); + auto ebytes = p.ConsumeRemainingBytes(); + auto sbytes = ebytes; + + auto const eview = etl::span{ebytes.data(), ebytes.size()}; + auto const sview = etl::span{sbytes.data(), sbytes.size()}; + + auto const e = etl::shift_left(eview.begin(), eview.end(), shift); + auto const s = std::shift_left(sview.begin(), sview.end(), shift); + + auto const ed = std::distance(eview.begin(), e); + auto const sd = std::distance(sview.begin(), s); + if ((ed != sd) or not std::equal(eview.begin(), e, sview.begin(), s)) { + std::println(stderr, "size: {}, shift: {}, s: {}, e: {}", eview.size(), shift, sd, ed); + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_shift_left(p)); + return 0; +} diff --git a/fuzzing/src/algorithm.shift_right.fuzz.cpp b/fuzzing/src/algorithm.shift_right.fuzz.cpp new file mode 100644 index 000000000..cef667288 --- /dev/null +++ b/fuzzing/src/algorithm.shift_right.fuzz.cpp @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include +#include +#include + +#include +#include + +[[nodiscard]] auto fuzz_shift_right(FuzzedDataProvider& p) -> int +{ + auto shift = p.ConsumeIntegralInRange(0, etl::numeric_limits::max()); + auto ebytes = p.ConsumeRemainingBytes(); + auto sbytes = ebytes; + + auto const eview = etl::span{ebytes.data(), ebytes.size()}; + auto const sview = etl::span{sbytes.data(), sbytes.size()}; + + auto const e = etl::shift_right(eview.begin(), eview.end(), shift); + auto const s = std::shift_right(sview.begin(), sview.end(), shift); + + auto const ed = std::distance(eview.begin(), e); + auto const sd = std::distance(sview.begin(), s); + if ((ed != sd) or not std::equal(e, eview.end(), s, sview.end())) { + std::println(stderr, "size: {}, shift: {}, s: {}, e: {}", eview.size(), shift, sd, ed); + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_shift_right(p)); + return 0; +} diff --git a/fuzzing/src/bit.bit_ceil.fuzz.cpp b/fuzzing/src/bit.bit_ceil.fuzz.cpp index 059b380d5..f75cdb199 100644 --- a/fuzzing/src/bit.bit_ceil.fuzz.cpp +++ b/fuzzing/src/bit.bit_ceil.fuzz.cpp @@ -18,10 +18,6 @@ template extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int { - if (size == 0) { - return 0; - } - auto p = FuzzedDataProvider{data, size}; RUN(fuzz_bit_ceil(p)); RUN(fuzz_bit_ceil(p)); diff --git a/fuzzing/src/bit.bit_floor.fuzz.cpp b/fuzzing/src/bit.bit_floor.fuzz.cpp index a6d9f86bd..3a6312bde 100644 --- a/fuzzing/src/bit.bit_floor.fuzz.cpp +++ b/fuzzing/src/bit.bit_floor.fuzz.cpp @@ -18,10 +18,6 @@ template extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int { - if (size == 0) { - return 0; - } - auto p = FuzzedDataProvider{data, size}; RUN(fuzz_bit_floor(p)); RUN(fuzz_bit_floor(p)); diff --git a/fuzzing/src/bit.bit_width.fuzz.cpp b/fuzzing/src/bit.bit_width.fuzz.cpp index 676726eee..3690570a6 100644 --- a/fuzzing/src/bit.bit_width.fuzz.cpp +++ b/fuzzing/src/bit.bit_width.fuzz.cpp @@ -18,10 +18,6 @@ template extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int { - if (size == 0) { - return 0; - } - auto p = FuzzedDataProvider{data, size}; RUN(fuzz_bit_width(p)); RUN(fuzz_bit_width(p)); diff --git a/fuzzing/src/bit.byteswap.fuzz.cpp b/fuzzing/src/bit.byteswap.fuzz.cpp index 88dc0d400..a49b93c53 100644 --- a/fuzzing/src/bit.byteswap.fuzz.cpp +++ b/fuzzing/src/bit.byteswap.fuzz.cpp @@ -20,10 +20,6 @@ template extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int { - if (size == 0) { - return 0; - } - auto p = FuzzedDataProvider{data, size}; RUN(fuzz_byteswap(p)); RUN(fuzz_byteswap(p)); diff --git a/fuzzing/src/bit.countl_one.fuzz.cpp b/fuzzing/src/bit.countl_one.fuzz.cpp index 33beb6cfa..0f8942798 100644 --- a/fuzzing/src/bit.countl_one.fuzz.cpp +++ b/fuzzing/src/bit.countl_one.fuzz.cpp @@ -18,10 +18,6 @@ template extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int { - if (size == 0) { - return 0; - } - auto p = FuzzedDataProvider{data, size}; RUN(fuzz_countl_one(p)); RUN(fuzz_countl_one(p)); diff --git a/fuzzing/src/bit.countl_zero.fuzz.cpp b/fuzzing/src/bit.countl_zero.fuzz.cpp index c89d9803e..6534214b4 100644 --- a/fuzzing/src/bit.countl_zero.fuzz.cpp +++ b/fuzzing/src/bit.countl_zero.fuzz.cpp @@ -18,10 +18,6 @@ template extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int { - if (size == 0) { - return 0; - } - auto p = FuzzedDataProvider{data, size}; RUN(fuzz_countl_zero(p)); RUN(fuzz_countl_zero(p)); diff --git a/fuzzing/src/bit.countr_one.fuzz.cpp b/fuzzing/src/bit.countr_one.fuzz.cpp index e98f1019f..d32c1eda4 100644 --- a/fuzzing/src/bit.countr_one.fuzz.cpp +++ b/fuzzing/src/bit.countr_one.fuzz.cpp @@ -18,10 +18,6 @@ template extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int { - if (size == 0) { - return 0; - } - auto p = FuzzedDataProvider{data, size}; RUN(fuzz_countr_one(p)); RUN(fuzz_countr_one(p)); diff --git a/fuzzing/src/bit.countr_zero.fuzz.cpp b/fuzzing/src/bit.countr_zero.fuzz.cpp index 9f7d7c291..0d2fed5c4 100644 --- a/fuzzing/src/bit.countr_zero.fuzz.cpp +++ b/fuzzing/src/bit.countr_zero.fuzz.cpp @@ -18,10 +18,6 @@ template extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int { - if (size == 0) { - return 0; - } - auto p = FuzzedDataProvider{data, size}; RUN(fuzz_countr_zero(p)); RUN(fuzz_countr_zero(p)); diff --git a/fuzzing/src/bit.has_single_bit.fuzz.cpp b/fuzzing/src/bit.has_single_bit.fuzz.cpp index f292af96a..03bf109a4 100644 --- a/fuzzing/src/bit.has_single_bit.fuzz.cpp +++ b/fuzzing/src/bit.has_single_bit.fuzz.cpp @@ -19,10 +19,6 @@ template extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int { - if (size == 0) { - return 0; - } - auto p = FuzzedDataProvider{data, size}; RUN(fuzz_has_single_bit(p)); RUN(fuzz_has_single_bit(p)); diff --git a/fuzzing/src/bit.popcount.fuzz.cpp b/fuzzing/src/bit.popcount.fuzz.cpp index 667070cbc..35e3a44c4 100644 --- a/fuzzing/src/bit.popcount.fuzz.cpp +++ b/fuzzing/src/bit.popcount.fuzz.cpp @@ -20,10 +20,6 @@ template extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int { - if (size == 0) { - return 0; - } - auto p = FuzzedDataProvider{data, size}; RUN(fuzz_popcount(p)); RUN(fuzz_popcount(p)); diff --git a/fuzzing/src/bitset.fuzz.cpp b/fuzzing/src/bitset.fuzz.cpp index 7d3f36929..d9e9ece09 100644 --- a/fuzzing/src/bitset.fuzz.cpp +++ b/fuzzing/src/bitset.fuzz.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include template auto fuzz_bitset(FuzzedDataProvider& p) -> int @@ -29,18 +29,18 @@ auto fuzz_bitset(FuzzedDataProvider& p) -> int auto const slong = sset.to_ullong(); if ((eview != sview) or (elong != slong)) { - std::printf("etl::bitset::to_ullong\n"); - std::printf("val: '%llu'\n", static_cast(val)); - std::printf("estr: '%s'\nsstr: '%s'\n", estr.c_str(), sstr.c_str()); - std::printf("elong: '%llu' slong: '%llu'\n", elong, slong); + std::println("etl::bitset::to_ullong"); + std::println("val: '{}'", static_cast(val)); + std::println("estr: '{}'\nsstr: '{}'", estr.c_str(), sstr); + std::println("elong: '{}' slong: '{}'", elong, slong); return 1; } auto const efromstr = etl::bitset{estr.c_str()}; if (eset != efromstr) { - std::printf("etl::bitset(string_view)\n"); - std::printf("estr: '%s'\nefromstr: '%s'\n", estr.c_str(), efromstr.template to_string().c_str()); + std::println("etl::bitset(string_view)"); + std::println("estr: '{}'\nefromstr: '{}'", estr.c_str(), efromstr.template to_string().c_str()); return 1; } @@ -49,9 +49,6 @@ auto fuzz_bitset(FuzzedDataProvider& p) -> int extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { - if (size == 0) { - return 0; - } auto p = FuzzedDataProvider{data, size}; RUN(fuzz_bitset<24>(p)); RUN(fuzz_bitset<32>(p)); diff --git a/fuzzing/src/numeric.midpoint.fuzz.cpp b/fuzzing/src/numeric.midpoint.fuzz.cpp new file mode 100644 index 000000000..f6b2aaf9a --- /dev/null +++ b/fuzzing/src/numeric.midpoint.fuzz.cpp @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include + +#include +#include + +template +[[nodiscard]] auto fuzz_midpoint(FuzzedDataProvider& p) -> int +{ + auto const [a, b] = [&p] { + if constexpr (etl::integral) { + return std::pair{p.ConsumeIntegral(), p.ConsumeIntegral()}; + } else if constexpr (etl::floating_point) { + return std::pair{p.ConsumeFloatingPoint(), p.ConsumeFloatingPoint()}; + } else { + static_assert(false); + } + }(); + + auto const s = std::midpoint(a, b); + auto const e = etl::midpoint(a, b); + return s != e ? 1 : 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + + RUN(fuzz_midpoint(p)); + RUN(fuzz_midpoint(p)); + RUN(fuzz_midpoint(p)); + RUN(fuzz_midpoint(p)); + RUN(fuzz_midpoint(p)); + + RUN(fuzz_midpoint(p)); + RUN(fuzz_midpoint(p)); + RUN(fuzz_midpoint(p)); + RUN(fuzz_midpoint(p)); + RUN(fuzz_midpoint(p)); + + RUN(fuzz_midpoint(p)); + RUN(fuzz_midpoint(p)); + return 0; +} diff --git a/fuzzing/src/string_view.contains.fuzz.cpp b/fuzzing/src/string_view.contains.fuzz.cpp new file mode 100644 index 000000000..a12ad1b28 --- /dev/null +++ b/fuzzing/src/string_view.contains.fuzz.cpp @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include + +auto fuzz_string_view_contains(FuzzedDataProvider& p) -> int +{ + auto const haystack = p.ConsumeRandomLengthString(64); + auto const needle = p.ConsumeRandomLengthString(64); + + auto const eview = etl::string_view{haystack.data(), haystack.size()}; + auto const sview = std::string_view{haystack.data(), haystack.size()}; + + auto const epos = eview.contains(needle.c_str()); + auto const spos = sview.contains(needle.c_str()); + if (epos != spos) { + std::println("etl::string_view::contains"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_string_view_contains(p)); + return 0; +} diff --git a/fuzzing/src/string_view.ends_with.fuzz.cpp b/fuzzing/src/string_view.ends_with.fuzz.cpp new file mode 100644 index 000000000..e90654fb0 --- /dev/null +++ b/fuzzing/src/string_view.ends_with.fuzz.cpp @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include + +auto fuzz_string_view_starts_with(FuzzedDataProvider& p) -> int +{ + auto const haystack = p.ConsumeRandomLengthString(64); + auto const needle = p.ConsumeRandomLengthString(64); + + auto const eview = etl::string_view{haystack.data(), haystack.size()}; + auto const sview = std::string_view{haystack.data(), haystack.size()}; + + auto const epos = eview.starts_with(needle.c_str()); + auto const spos = sview.starts_with(needle.c_str()); + if (epos != spos) { + std::println("etl::string_view::starts_with"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_string_view_starts_with(p)); + return 0; +} diff --git a/fuzzing/src/string_view.find.fuzz.cpp b/fuzzing/src/string_view.find.fuzz.cpp new file mode 100644 index 000000000..4d5645c48 --- /dev/null +++ b/fuzzing/src/string_view.find.fuzz.cpp @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include + +auto fuzz_string_view_find(FuzzedDataProvider& p) -> int +{ + auto const haystack = p.ConsumeRandomLengthString(64); + auto const needle = p.ConsumeRandomLengthString(64); + + auto const eview = etl::string_view{haystack.data(), haystack.size()}; + auto const sview = std::string_view{haystack.data(), haystack.size()}; + + auto const epos = eview.find(needle.c_str()); + auto const spos = sview.find(needle.c_str()); + if (epos != spos) { + std::println("etl::string_view::find"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_string_view_find(p)); + return 0; +} diff --git a/fuzzing/src/string_view.find_first_not_of.fuzz.cpp b/fuzzing/src/string_view.find_first_not_of.fuzz.cpp new file mode 100644 index 000000000..f63ad3a7e --- /dev/null +++ b/fuzzing/src/string_view.find_first_not_of.fuzz.cpp @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include + +auto fuzz_string_view_find_first_not_of(FuzzedDataProvider& p) -> int +{ + auto const haystack = p.ConsumeRandomLengthString(64); + auto const needle = p.ConsumeRandomLengthString(64); + + auto const eview = etl::string_view{haystack.data(), haystack.size()}; + auto const sview = std::string_view{haystack.data(), haystack.size()}; + + auto const epos = eview.find_first_not_of(needle.c_str()); + auto const spos = sview.find_first_not_of(needle.c_str()); + if (epos != spos) { + std::println("etl::string_view::find_first_not_of"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_string_view_find_first_not_of(p)); + return 0; +} diff --git a/fuzzing/src/string_view.find_first_of.fuzz.cpp b/fuzzing/src/string_view.find_first_of.fuzz.cpp new file mode 100644 index 000000000..3abf10c32 --- /dev/null +++ b/fuzzing/src/string_view.find_first_of.fuzz.cpp @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include + +auto fuzz_string_view_find_first_of(FuzzedDataProvider& p) -> int +{ + auto const haystack = p.ConsumeRandomLengthString(64); + auto const needle = p.ConsumeRandomLengthString(64); + + auto const eview = etl::string_view{haystack.data(), haystack.size()}; + auto const sview = std::string_view{haystack.data(), haystack.size()}; + + auto const epos = eview.find_first_of(needle.c_str()); + auto const spos = sview.find_first_of(needle.c_str()); + if (epos != spos) { + std::println("etl::string_view::find_first_of"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_string_view_find_first_of(p)); + return 0; +} diff --git a/fuzzing/src/string_view.find_last_not_of.fuzz.cpp b/fuzzing/src/string_view.find_last_not_of.fuzz.cpp new file mode 100644 index 000000000..873afcb04 --- /dev/null +++ b/fuzzing/src/string_view.find_last_not_of.fuzz.cpp @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include + +auto fuzz_string_view_find_last_not_of(FuzzedDataProvider& p) -> int +{ + auto const haystack = p.ConsumeRandomLengthString(64); + auto const needle = p.ConsumeRandomLengthString(64); + + auto const eview = etl::string_view{haystack.data(), haystack.size()}; + auto const sview = std::string_view{haystack.data(), haystack.size()}; + + auto const epos = eview.find_last_not_of(needle.c_str()); + auto const spos = sview.find_last_not_of(needle.c_str()); + if (epos != spos) { + std::println("etl::string_view::find_last_not_of"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_string_view_find_last_not_of(p)); + return 0; +} diff --git a/fuzzing/src/string_view.find_last_of.fuzz.cpp b/fuzzing/src/string_view.find_last_of.fuzz.cpp new file mode 100644 index 000000000..f98e9fdd6 --- /dev/null +++ b/fuzzing/src/string_view.find_last_of.fuzz.cpp @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include + +auto fuzz_string_view_find_last_of(FuzzedDataProvider& p) -> int +{ + auto const haystack = p.ConsumeRandomLengthString(64); + auto const needle = p.ConsumeRandomLengthString(64); + + auto const eview = etl::string_view{haystack.data(), haystack.size()}; + auto const sview = std::string_view{haystack.data(), haystack.size()}; + + auto const epos = eview.find_last_of(needle.c_str()); + auto const spos = sview.find_last_of(needle.c_str()); + if (epos != spos) { + std::println("etl::string_view::find_last_of"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_string_view_find_last_of(p)); + return 0; +} diff --git a/fuzzing/src/string_view.fuzz.cpp b/fuzzing/src/string_view.fuzz.cpp deleted file mode 100644 index cc01ec068..000000000 --- a/fuzzing/src/string_view.fuzz.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: BSL-1.0 -// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch - -#include "fuzzing.hpp" - -#include - -#include -#include - -// auto fuzz_string_view_compare(FuzzedDataProvider& p) -> int -// { -// auto sign = [](int x) { return x == 0 ? 0 : (x < 0 ? -1 : 1); }; - -// auto const a = p.ConsumeRandomLengthString(64); -// auto const b = p.ConsumeRandomLengthString(64); - -// auto const eview = etl::string_view{a.data(), a.size()}; -// auto const sview = std::string_view{a.data(), a.size()}; - -// auto const ecmp = eview.compare(b.c_str()); -// auto const scmp = sview.compare(b.c_str()); - -// if (sign(ecmp) != sign(scmp)) { -// std::printf("etl::string_view::compare\n"); -// std::printf("this: '%s' str: '%s'\n", a.c_str(), b.c_str()); -// std::printf("len(this): '%zu' len(str): '%zu'\n", a.size(), b.size()); -// std::printf("ecmp: '%d' scmp: '%d'\n", ecmp, scmp); -// return 1; -// } -// return 0; -// } - -auto fuzz_string_view_find(FuzzedDataProvider& p) -> int -{ - auto const haystack = p.ConsumeRandomLengthString(64); - auto const needle = p.ConsumeRandomLengthString(64); - - auto const eview = etl::string_view{haystack.data(), haystack.size()}; - auto const sview = std::string_view{haystack.data(), haystack.size()}; - - auto const epos = eview.find(needle.c_str()); - auto const spos = sview.find(needle.c_str()); - if (epos != spos) { - std::printf("etl::string_view::find\n"); - std::printf("haystack: '%s' needle: '%s'\n", haystack.c_str(), needle.c_str()); - std::printf("epos: '%zu' spos: '%zu'\n", epos, spos); - return 1; - } - return 0; -} - -auto fuzz_string_view_rfind(FuzzedDataProvider& p) -> int -{ - auto const haystack = p.ConsumeRandomLengthString(64); - auto const needle = p.ConsumeRandomLengthString(64); - - auto const eview = etl::string_view{haystack.data(), haystack.size()}; - auto const sview = std::string_view{haystack.data(), haystack.size()}; - - auto const epos = eview.rfind(needle.c_str()); - auto const spos = sview.rfind(needle.c_str()); - if (epos != spos) { - std::printf("etl::string_view::rfind\n"); - std::printf("haystack: '%s' needle: '%s'\n", haystack.c_str(), needle.c_str()); - std::printf("epos: '%zu' spos: '%zu'\n", epos, spos); - return 1; - } - return 0; -} - -extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int -{ - if (size == 0) { - return 0; - } - auto p = FuzzedDataProvider{data, size}; - // RUN(fuzz_string_view_compare(p)); - RUN(fuzz_string_view_find(p)); - RUN(fuzz_string_view_rfind(p)); - return 0; -} diff --git a/fuzzing/src/string_view.rfind.fuzz.cpp b/fuzzing/src/string_view.rfind.fuzz.cpp new file mode 100644 index 000000000..afc102b4c --- /dev/null +++ b/fuzzing/src/string_view.rfind.fuzz.cpp @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include + +auto fuzz_string_view_rfind(FuzzedDataProvider& p) -> int +{ + auto const haystack = p.ConsumeRandomLengthString(64); + auto const needle = p.ConsumeRandomLengthString(64); + + auto const eview = etl::string_view{haystack.data(), haystack.size()}; + auto const sview = std::string_view{haystack.data(), haystack.size()}; + + auto const epos = eview.rfind(needle.c_str()); + auto const spos = sview.rfind(needle.c_str()); + if (epos != spos) { + std::println("etl::string_view::rfind"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_string_view_rfind(p)); + return 0; +} diff --git a/fuzzing/src/string_view.starts_with.fuzz.cpp b/fuzzing/src/string_view.starts_with.fuzz.cpp new file mode 100644 index 000000000..e90654fb0 --- /dev/null +++ b/fuzzing/src/string_view.starts_with.fuzz.cpp @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include + +auto fuzz_string_view_starts_with(FuzzedDataProvider& p) -> int +{ + auto const haystack = p.ConsumeRandomLengthString(64); + auto const needle = p.ConsumeRandomLengthString(64); + + auto const eview = etl::string_view{haystack.data(), haystack.size()}; + auto const sview = std::string_view{haystack.data(), haystack.size()}; + + auto const epos = eview.starts_with(needle.c_str()); + auto const spos = sview.starts_with(needle.c_str()); + if (epos != spos) { + std::println("etl::string_view::starts_with"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_string_view_starts_with(p)); + return 0; +} diff --git a/include/etl/_algorithm/shift_right.hpp b/include/etl/_algorithm/shift_right.hpp index 024b0fbe5..c2ac3e49e 100644 --- a/include/etl/_algorithm/shift_right.hpp +++ b/include/etl/_algorithm/shift_right.hpp @@ -33,7 +33,11 @@ constexpr auto shift_right(BidiIt first, BidiIt last, typename etl::iterator_tra { // The standard only checks for n == 0. n < 0 would be undefined behavior. // This implementation does nothing if n < 0. - if (n <= 0 or n >= etl::distance(first, last)) { + if (n <= 0) { + return first; + } + + if (n >= etl::distance(first, last)) { return last; } @@ -43,14 +47,14 @@ constexpr auto shift_right(BidiIt first, BidiIt last, typename etl::iterator_tra *dest = etl::move(*src); } - // Elements outside the new range should be left in a valid but unspecified state. - // If the value type has a default constructor we do a little cleanup. - using value_type = typename etl::iterator_traits::value_type; - if constexpr (is_default_constructible_v) { - for (; dest != first; --dest) { - *dest = value_type{}; - } - } + // // Elements outside the new range should be left in a valid but unspecified state. + // // If the value type has a default constructor we do a little cleanup. + // using value_type = typename etl::iterator_traits::value_type; + // if constexpr (is_default_constructible_v) { + // for (; dest != first; --dest) { + // *dest = value_type{}; + // } + // } return etl::next(first, n); } From 1353e7ae5376c92f29bc83bd8fbc42e1ea20f4fe Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Thu, 2 Oct 2025 14:37:58 +0200 Subject: [PATCH 16/39] [string_view] Fix find_last_of for empty strings --- fuzzing/CMakeLists.txt | 4 ++-- include/etl/_string_view/basic_string_view.hpp | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index b3e8669d5..a0dc3eb7c 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -81,10 +81,10 @@ tetl_add_fuzz_test("random.uniform_int_distribution") tetl_add_fuzz_test("random.uniform_real_distribution") tetl_add_fuzz_test("string_view.contains") tetl_add_fuzz_test("string_view.ends_with") -tetl_add_fuzz_test("string_view.find_first_of") tetl_add_fuzz_test("string_view.find_first_not_of") -# tetl_add_fuzz_test("string_view.find_last_of") +tetl_add_fuzz_test("string_view.find_first_of") tetl_add_fuzz_test("string_view.find_last_not_of") +tetl_add_fuzz_test("string_view.find_last_of") tetl_add_fuzz_test("string_view.find") tetl_add_fuzz_test("string_view.rfind") tetl_add_fuzz_test("string_view.starts_with") diff --git a/include/etl/_string_view/basic_string_view.hpp b/include/etl/_string_view/basic_string_view.hpp index 1f1a94cb2..cd012b0d5 100644 --- a/include/etl/_string_view/basic_string_view.hpp +++ b/include/etl/_string_view/basic_string_view.hpp @@ -616,6 +616,9 @@ struct basic_string_view { /// substring, or npos if no such character is found. [[nodiscard]] constexpr auto find_last_of(basic_string_view v, size_type pos = npos) const noexcept -> size_type { + if (empty()) { + return npos; + } auto offset = etl::clamp(pos, 0, size() - 1); do { // NOLINT(cppcoreguidelines-avoid-do-while) auto const current = unsafe_at(offset); From 80630fa08cdfcd609058866c332f4a5d52c4d9f8 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Thu, 2 Oct 2025 14:44:00 +0200 Subject: [PATCH 17/39] [fuzzing] Fix copy-paste error in string_view.ends_with --- fuzzing/src/string_view.ends_with.fuzz.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fuzzing/src/string_view.ends_with.fuzz.cpp b/fuzzing/src/string_view.ends_with.fuzz.cpp index e90654fb0..3c0bc8294 100644 --- a/fuzzing/src/string_view.ends_with.fuzz.cpp +++ b/fuzzing/src/string_view.ends_with.fuzz.cpp @@ -8,7 +8,7 @@ #include #include -auto fuzz_string_view_starts_with(FuzzedDataProvider& p) -> int +auto fuzz_string_view_ends_with(FuzzedDataProvider& p) -> int { auto const haystack = p.ConsumeRandomLengthString(64); auto const needle = p.ConsumeRandomLengthString(64); @@ -16,10 +16,10 @@ auto fuzz_string_view_starts_with(FuzzedDataProvider& p) -> int auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; - auto const epos = eview.starts_with(needle.c_str()); - auto const spos = sview.starts_with(needle.c_str()); + auto const epos = eview.ends_with(needle.c_str()); + auto const spos = sview.ends_with(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::starts_with"); + std::println("etl::string_view::ends_with"); std::println("haystack: '{}' needle: '{}'", haystack, needle); std::println("epos: '{}' spos: '{}'", epos, spos); return 1; @@ -30,6 +30,6 @@ auto fuzz_string_view_starts_with(FuzzedDataProvider& p) -> int extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; - RUN(fuzz_string_view_starts_with(p)); + RUN(fuzz_string_view_ends_with(p)); return 0; } From 42eccf539ec40a4ed8e45be24ad79cd791912629 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Thu, 2 Oct 2025 15:05:32 +0200 Subject: [PATCH 18/39] [algorithm] Reenable temporary gcc shift_right fix --- include/etl/_algorithm/shift_right.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/etl/_algorithm/shift_right.hpp b/include/etl/_algorithm/shift_right.hpp index c2ac3e49e..17f643eef 100644 --- a/include/etl/_algorithm/shift_right.hpp +++ b/include/etl/_algorithm/shift_right.hpp @@ -47,14 +47,14 @@ constexpr auto shift_right(BidiIt first, BidiIt last, typename etl::iterator_tra *dest = etl::move(*src); } - // // Elements outside the new range should be left in a valid but unspecified state. - // // If the value type has a default constructor we do a little cleanup. - // using value_type = typename etl::iterator_traits::value_type; - // if constexpr (is_default_constructible_v) { - // for (; dest != first; --dest) { - // *dest = value_type{}; - // } - // } + // Elements outside the new range should be left in a valid but unspecified state. + // If the value type has a default constructor we do a little cleanup. + using value_type = typename etl::iterator_traits::value_type; + if constexpr (is_default_constructible_v) { + for (; dest != first; --dest) { + *dest = value_type{}; + } + } return etl::next(first, n); } From 7594e3907d7db8e81ec3d1442f65bfa817b413e6 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Thu, 2 Oct 2025 15:05:56 +0200 Subject: [PATCH 19/39] [string_view] Fix find_last_not_of for empty strings --- include/etl/_string_view/basic_string_view.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/etl/_string_view/basic_string_view.hpp b/include/etl/_string_view/basic_string_view.hpp index cd012b0d5..560bf6f9e 100644 --- a/include/etl/_string_view/basic_string_view.hpp +++ b/include/etl/_string_view/basic_string_view.hpp @@ -678,6 +678,10 @@ struct basic_string_view { /// characters in the given string, or npos if no such character is found. [[nodiscard]] constexpr auto find_last_not_of(basic_string_view v, size_type pos = npos) const noexcept -> size_type { + if (empty()) { + return npos; + } + auto offset = etl::clamp(pos, 0, size() - 1); do { // NOLINT(cppcoreguidelines-avoid-do-while) auto equals = [&](auto ch) { return ch == unsafe_at(offset); }; From 38988545ddd79aaea53c081d83c5b97d8c057ef1 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Thu, 2 Oct 2025 15:10:00 +0200 Subject: [PATCH 20/39] [fuzzing] More string_view fuzzing --- fuzzing/src/string_view.contains.fuzz.cpp | 13 ++++++++++++- fuzzing/src/string_view.ends_with.fuzz.cpp | 13 ++++++++++++- fuzzing/src/string_view.find.fuzz.cpp | 13 ++++++++++++- fuzzing/src/string_view.find_first_not_of.fuzz.cpp | 13 ++++++++++++- fuzzing/src/string_view.find_first_of.fuzz.cpp | 13 ++++++++++++- fuzzing/src/string_view.find_last_not_of.fuzz.cpp | 13 ++++++++++++- fuzzing/src/string_view.find_last_of.fuzz.cpp | 13 ++++++++++++- fuzzing/src/string_view.rfind.fuzz.cpp | 13 ++++++++++++- fuzzing/src/string_view.starts_with.fuzz.cpp | 13 ++++++++++++- 9 files changed, 108 insertions(+), 9 deletions(-) diff --git a/fuzzing/src/string_view.contains.fuzz.cpp b/fuzzing/src/string_view.contains.fuzz.cpp index a12ad1b28..04206435d 100644 --- a/fuzzing/src/string_view.contains.fuzz.cpp +++ b/fuzzing/src/string_view.contains.fuzz.cpp @@ -16,10 +16,21 @@ auto fuzz_string_view_contains(FuzzedDataProvider& p) -> int auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; + if (not needle.empty()) { + auto const epos = eview.contains(needle[0]); + auto const spos = sview.contains(needle[0]); + if (epos != spos) { + std::println("etl::string_view::contains(char)"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + } + auto const epos = eview.contains(needle.c_str()); auto const spos = sview.contains(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::contains"); + std::println("etl::string_view::contains(char const*)"); std::println("haystack: '{}' needle: '{}'", haystack, needle); std::println("epos: '{}' spos: '{}'", epos, spos); return 1; diff --git a/fuzzing/src/string_view.ends_with.fuzz.cpp b/fuzzing/src/string_view.ends_with.fuzz.cpp index 3c0bc8294..1faef457d 100644 --- a/fuzzing/src/string_view.ends_with.fuzz.cpp +++ b/fuzzing/src/string_view.ends_with.fuzz.cpp @@ -16,10 +16,21 @@ auto fuzz_string_view_ends_with(FuzzedDataProvider& p) -> int auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; + if (not needle.empty()) { + auto const epos = eview.ends_with(needle[0]); + auto const spos = sview.ends_with(needle[0]); + if (epos != spos) { + std::println("etl::string_view::ends_with(char)"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + } + auto const epos = eview.ends_with(needle.c_str()); auto const spos = sview.ends_with(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::ends_with"); + std::println("etl::string_view::ends_with(char const*)"); std::println("haystack: '{}' needle: '{}'", haystack, needle); std::println("epos: '{}' spos: '{}'", epos, spos); return 1; diff --git a/fuzzing/src/string_view.find.fuzz.cpp b/fuzzing/src/string_view.find.fuzz.cpp index 4d5645c48..ac95dee39 100644 --- a/fuzzing/src/string_view.find.fuzz.cpp +++ b/fuzzing/src/string_view.find.fuzz.cpp @@ -16,10 +16,21 @@ auto fuzz_string_view_find(FuzzedDataProvider& p) -> int auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; + if (not needle.empty()) { + auto const epos = eview.find(needle[0]); + auto const spos = sview.find(needle[0]); + if (epos != spos) { + std::println("etl::string_view::find(char)"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + } + auto const epos = eview.find(needle.c_str()); auto const spos = sview.find(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::find"); + std::println("etl::string_view::find(char const*)"); std::println("haystack: '{}' needle: '{}'", haystack, needle); std::println("epos: '{}' spos: '{}'", epos, spos); return 1; diff --git a/fuzzing/src/string_view.find_first_not_of.fuzz.cpp b/fuzzing/src/string_view.find_first_not_of.fuzz.cpp index f63ad3a7e..a86f83337 100644 --- a/fuzzing/src/string_view.find_first_not_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_first_not_of.fuzz.cpp @@ -16,10 +16,21 @@ auto fuzz_string_view_find_first_not_of(FuzzedDataProvider& p) -> int auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; + if (not needle.empty()) { + auto const epos = eview.find_first_not_of(needle[0]); + auto const spos = sview.find_first_not_of(needle[0]); + if (epos != spos) { + std::println("etl::string_view::find_first_not_of(char)"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + } + auto const epos = eview.find_first_not_of(needle.c_str()); auto const spos = sview.find_first_not_of(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::find_first_not_of"); + std::println("etl::string_view::find_first_not_of(char const*)"); std::println("haystack: '{}' needle: '{}'", haystack, needle); std::println("epos: '{}' spos: '{}'", epos, spos); return 1; diff --git a/fuzzing/src/string_view.find_first_of.fuzz.cpp b/fuzzing/src/string_view.find_first_of.fuzz.cpp index 3abf10c32..9ed6a8344 100644 --- a/fuzzing/src/string_view.find_first_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_first_of.fuzz.cpp @@ -16,10 +16,21 @@ auto fuzz_string_view_find_first_of(FuzzedDataProvider& p) -> int auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; + if (not needle.empty()) { + auto const epos = eview.find_first_of(needle[0]); + auto const spos = sview.find_first_of(needle[0]); + if (epos != spos) { + std::println("etl::string_view::find_first_of(char)"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + } + auto const epos = eview.find_first_of(needle.c_str()); auto const spos = sview.find_first_of(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::find_first_of"); + std::println("etl::string_view::find_first_of(char const*)"); std::println("haystack: '{}' needle: '{}'", haystack, needle); std::println("epos: '{}' spos: '{}'", epos, spos); return 1; diff --git a/fuzzing/src/string_view.find_last_not_of.fuzz.cpp b/fuzzing/src/string_view.find_last_not_of.fuzz.cpp index 873afcb04..5968aae0c 100644 --- a/fuzzing/src/string_view.find_last_not_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_last_not_of.fuzz.cpp @@ -16,10 +16,21 @@ auto fuzz_string_view_find_last_not_of(FuzzedDataProvider& p) -> int auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; + if (not needle.empty()) { + auto const epos = eview.find_last_not_of(needle[0]); + auto const spos = sview.find_last_not_of(needle[0]); + if (epos != spos) { + std::println("etl::string_view::find_last_not_of(char)"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + } + auto const epos = eview.find_last_not_of(needle.c_str()); auto const spos = sview.find_last_not_of(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::find_last_not_of"); + std::println("etl::string_view::find_last_not_of(char const*)"); std::println("haystack: '{}' needle: '{}'", haystack, needle); std::println("epos: '{}' spos: '{}'", epos, spos); return 1; diff --git a/fuzzing/src/string_view.find_last_of.fuzz.cpp b/fuzzing/src/string_view.find_last_of.fuzz.cpp index f98e9fdd6..e9103988e 100644 --- a/fuzzing/src/string_view.find_last_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_last_of.fuzz.cpp @@ -16,10 +16,21 @@ auto fuzz_string_view_find_last_of(FuzzedDataProvider& p) -> int auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; + if (not needle.empty()) { + auto const epos = eview.find_last_of(needle[0]); + auto const spos = sview.find_last_of(needle[0]); + if (epos != spos) { + std::println("etl::string_view::find_last_of(char)"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + } + auto const epos = eview.find_last_of(needle.c_str()); auto const spos = sview.find_last_of(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::find_last_of"); + std::println("etl::string_view::find_last_of(char const*)"); std::println("haystack: '{}' needle: '{}'", haystack, needle); std::println("epos: '{}' spos: '{}'", epos, spos); return 1; diff --git a/fuzzing/src/string_view.rfind.fuzz.cpp b/fuzzing/src/string_view.rfind.fuzz.cpp index afc102b4c..990c86aa1 100644 --- a/fuzzing/src/string_view.rfind.fuzz.cpp +++ b/fuzzing/src/string_view.rfind.fuzz.cpp @@ -16,10 +16,21 @@ auto fuzz_string_view_rfind(FuzzedDataProvider& p) -> int auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; + if (not needle.empty()) { + auto const epos = eview.rfind(needle[0]); + auto const spos = sview.rfind(needle[0]); + if (epos != spos) { + std::println("etl::string_view::rfind(char)"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + } + auto const epos = eview.rfind(needle.c_str()); auto const spos = sview.rfind(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::rfind"); + std::println("etl::string_view::rfind(char const*)"); std::println("haystack: '{}' needle: '{}'", haystack, needle); std::println("epos: '{}' spos: '{}'", epos, spos); return 1; diff --git a/fuzzing/src/string_view.starts_with.fuzz.cpp b/fuzzing/src/string_view.starts_with.fuzz.cpp index e90654fb0..09c677e46 100644 --- a/fuzzing/src/string_view.starts_with.fuzz.cpp +++ b/fuzzing/src/string_view.starts_with.fuzz.cpp @@ -16,10 +16,21 @@ auto fuzz_string_view_starts_with(FuzzedDataProvider& p) -> int auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; + if (not needle.empty()) { + auto const epos = eview.starts_with(needle[0]); + auto const spos = sview.starts_with(needle[0]); + if (epos != spos) { + std::println("etl::string_view::starts_with(char)"); + std::println("haystack: '{}' needle: '{}'", haystack, needle); + std::println("epos: '{}' spos: '{}'", epos, spos); + return 1; + } + } + auto const epos = eview.starts_with(needle.c_str()); auto const spos = sview.starts_with(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::starts_with"); + std::println("etl::string_view::starts_with(char const*)"); std::println("haystack: '{}' needle: '{}'", haystack, needle); std::println("epos: '{}' spos: '{}'", epos, spos); return 1; From a258c8a435a887767716e0c581810b8cce7ba812 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Thu, 2 Oct 2025 15:11:34 +0200 Subject: [PATCH 21/39] Fix build-atfe.sh compile step --- scripts/build-atfe.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build-atfe.sh b/scripts/build-atfe.sh index e52decb39..f44e8d9f9 100755 --- a/scripts/build-atfe.sh +++ b/scripts/build-atfe.sh @@ -13,5 +13,5 @@ cmake -S . -B cmake-build-atfe \ -D CMAKE_CXX_SCAN_FOR_MODULES=OFF \ -D TETL_BUILD_CONTRACT_CHECKS=OFF -cmake --build cmake-build-atfe --target help +cmake --build cmake-build-atfe --target all ctest --test-dir cmake-build-atfe --output-on-failure -j 16 From 2e6551466eee508a9da753fd10cee893aa4d9f4b Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Thu, 2 Oct 2025 15:51:14 +0200 Subject: [PATCH 22/39] [algorithm] Fix naming in quick_sort --- include/etl/_algorithm/quick_sort.hpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/include/etl/_algorithm/quick_sort.hpp b/include/etl/_algorithm/quick_sort.hpp index 244db7b35..82c872f67 100644 --- a/include/etl/_algorithm/quick_sort.hpp +++ b/include/etl/_algorithm/quick_sort.hpp @@ -16,18 +16,17 @@ namespace detail { template constexpr auto lomuto_partition(RandomIt first, RandomIt last, Compare comp) -> RandomIt { - // pivot = last - 1 - auto pivot_it = etl::prev(last); - auto i = first; + auto pivot = etl::prev(last); + auto i = first; - for (auto j = first; j != pivot_it; ++j) { - if (comp(*j, *pivot_it)) { + for (auto j = first; j != pivot; ++j) { + if (comp(*j, *pivot)) { etl::iter_swap(i, j); ++i; } } - etl::iter_swap(i, pivot_it); + etl::iter_swap(i, pivot); return i; // final pivot position } From f2f3b335970cc2433b1f65d95c1ffdb0fe746da9 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Thu, 2 Oct 2025 16:22:01 +0200 Subject: [PATCH 23/39] [algorithm] Implement nth_element --- include/etl/_algorithm/nth_element.hpp | 68 ++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/include/etl/_algorithm/nth_element.hpp b/include/etl/_algorithm/nth_element.hpp index 9bf810b05..d7d33530a 100644 --- a/include/etl/_algorithm/nth_element.hpp +++ b/include/etl/_algorithm/nth_element.hpp @@ -4,11 +4,58 @@ #ifndef TETL_ALGORITHM_NTH_ELEMENT_HPP #define TETL_ALGORITHM_NTH_ELEMENT_HPP +#include #include -#include +#include +#include +#include namespace etl { +namespace detail { + +template +constexpr auto median_of_three(Iter a, Iter b, Iter c, Compare comp) -> Iter +{ + if (comp(*a, *b)) { + if (comp(*b, *c)) { + return b; // a < b < c + } else if (comp(*a, *c)) { + return c; // a < c <= b + } + return a; // c <= a < b + } + + // !(a < b) + if (comp(*a, *c)) { + return a; // b <= a < c + } else if (comp(*b, *c)) { + return c; // b < c <= a + } + return b; // c <= b <= a +} + +template +constexpr auto unguarded_partition(RandomIt first, RandomIt last, RandomIt pivot, Compare comp) -> RandomIt +{ + while (true) { + while (comp(*first, *pivot)) { + ++first; + } + --last; + while (comp(*pivot, *last)) { + --last; + } + if (not(first < last)) { + return first; + } + etl::iter_swap(first, last); + ++first; + } +} + +} // namespace detail + /// \brief nth_element is a partial sorting algorithm that rearranges elements /// in `[first, last)` such that: /// - The element pointed at by nth is changed to whatever element would occur @@ -22,16 +69,27 @@ namespace etl { template constexpr auto nth_element(RandomIt first, RandomIt nth, RandomIt last, Compare comp) -> void { - // TODO: Improve. Currently forwards to regular sort. - etl::ignore_unused(nth); + constexpr auto small_threshold = 16; + + while (last - first > small_threshold) { + auto const middle = etl::next(first, (last - first) / 2); + auto const pivot = etl::detail::median_of_three(first, middle, etl::prev(last), comp); + auto const cut = etl::detail::unguarded_partition(first, last, pivot, comp); + + if (nth < cut) { + last = cut; // recurse left + } else { + first = cut; // recurse right + } + } + etl::sort(first, last, comp); } template constexpr auto nth_element(RandomIt first, RandomIt nth, RandomIt last) -> void { - etl::ignore_unused(nth); - etl::sort(first, last); + etl::nth_element(first, nth, last, etl::less()); } } // namespace etl From e77ca76a62a6a18b857a1c1689075967939b211c Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Thu, 2 Oct 2025 16:37:17 +0200 Subject: [PATCH 24/39] [scripts] Add utility to compare sort algorithms --- scripts/sorting.cpp | 151 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 scripts/sorting.cpp diff --git a/scripts/sorting.cpp b/scripts/sorting.cpp new file mode 100644 index 000000000..0cd3baa8b --- /dev/null +++ b/scripts/sorting.cpp @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +// Count compare, copy, move & swap operations in sort algorithms. +// Run from root of git repo: +// clang++ -std=c++23 -O3 -march=native -I include scripts/sorting.cpp -o sorting +// ./sorting + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +struct SortCounters { + inline static uint64_t comps = 0; + inline static uint64_t swaps = 0; // times your swap(T&,T&) was used + inline static uint64_t copies = 0; // copy-ctor or copy-assign + inline static uint64_t moves = 0; // move-ctor or move-assign + + static void reset() + { + comps = swaps = copies = moves = 0; + } +}; + +template +struct Instrumented { + T v; + + Instrumented() = default; + Instrumented(T const& x) + : v(x) + { + } + Instrumented(T&& x) noexcept(etl::is_nothrow_move_constructible_v) + : v(etl::move(x)) + { + } + + Instrumented(Instrumented const& o) + : v(o.v) + { + ++SortCounters::copies; + } + Instrumented(Instrumented&& o) noexcept(etl::is_nothrow_move_constructible_v) + : v(etl::move(o.v)) + { + ++SortCounters::moves; + } + + auto operator=(Instrumented const& o) -> Instrumented& + { + v = o.v; + ++SortCounters::copies; + return *this; + } + auto operator=(Instrumented&& o) noexcept(etl::is_nothrow_move_assignable_v) -> Instrumented& + { + v = etl::move(o.v); + ++SortCounters::moves; + return *this; + } + + friend auto operator<(Instrumented const& lhs, Instrumented const& rhs) -> bool + { + ++SortCounters::comps; + return lhs.v < rhs.v; + } + + friend auto swap(Instrumented& lhs, Instrumented& rhs) noexcept(noexcept(etl::swap(lhs.v, rhs.v))) -> void + { + using etl::swap; + swap(lhs.v, rhs.v); + ++SortCounters::swaps; + } +}; + +// handy lower bound log2(n!) to compare with comparison sorts’ theoretical minimum +inline double log2_factorial(size_t n) +{ + double s = 0.0; + for (size_t i = 2; i <= n; ++i) { + s += std::log2((double)i); + } + return s; +} + +template +void run_case(char const* label, SortFn sorter, size_t n) +{ + std::vector> a; + a.reserve(n); + std::mt19937 rng(123456789); + for (size_t i = 0; i < n; ++i) { + a.emplace_back(int(rng())); + } + + SortCounters::reset(); + auto aview = etl::span>{a.data(), a.size()}; + sorter(aview.begin(), aview.end()); // call your sorter or std::sort + + double const lb = log2_factorial(n); // ~ n log2 n - 1.44 n + double const nlogn = n * std::log2((double)n); // rough model + std::println( + "{} n={} comps={} comps/(n^2)={:.3f} comps/(nlog2n)={:.3f} comps/log2(n!)={:.3f} swaps={} copies={} moves={}", + label, + n, + SortCounters::comps, + SortCounters::comps / static_cast(n * n), + SortCounters::comps / std::max(1.0, nlogn), + SortCounters::comps / std::max(1.0, lb), + SortCounters::swaps, + SortCounters::copies, + SortCounters::moves + ); +} + +int main() +{ + for (size_t n : {1u << 2, 1u << 4, 1u << 8, 1u << 12, 1u << 14}) { + std::puts("--------------------------------------------------------------"); + run_case("std::sort ", [](auto f, auto l) { std::sort(f, l); }, n); + run_case("etl::sort ", [](auto f, auto l) { etl::sort(f, l); }, n); + + std::puts("---------"); + run_case("std::stable_sort ", [](auto f, auto l) { std::stable_sort(f, l); }, n); + run_case("etl::stable_sort ", [](auto f, auto l) { etl::stable_sort(f, l); }, n); + + std::puts("---------"); + run_case("etl::merge_sort ", [](auto f, auto l) { etl::merge_sort(f, l); }, n); + run_case("etl::quick_sort ", [](auto f, auto l) { etl::quick_sort(f, l); }, n); + run_case("etl::insertion_sort", [](auto f, auto l) { etl::insertion_sort(f, l); }, n); + run_case("etl::bubble_sort ", [](auto f, auto l) { etl::bubble_sort(f, l); }, n); + run_case("etl::exchange_sort ", [](auto f, auto l) { etl::exchange_sort(f, l); }, n); + run_case("etl::gnome_sort ", [](auto f, auto l) { etl::gnome_sort(f, l); }, n); + + std::puts("---------"); + run_case("std::nth_element ", [](auto f, auto l) { std::nth_element(f, etl::midpoint(f, l), l); }, n); + run_case("etl::nth_element ", [](auto f, auto l) { etl::nth_element(f, etl::midpoint(f, l), l); }, n); + } +} From 74d3ddf125bdf52ab54cdc5bc1fb66f3a0eb8ff8 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Thu, 2 Oct 2025 16:38:44 +0200 Subject: [PATCH 25/39] [algorithm] Fix naming in nth_element --- include/etl/_algorithm/nth_element.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/etl/_algorithm/nth_element.hpp b/include/etl/_algorithm/nth_element.hpp index d7d33530a..ec5fff0f8 100644 --- a/include/etl/_algorithm/nth_element.hpp +++ b/include/etl/_algorithm/nth_element.hpp @@ -69,9 +69,9 @@ constexpr auto unguarded_partition(RandomIt first, RandomIt last, RandomIt pivot template constexpr auto nth_element(RandomIt first, RandomIt nth, RandomIt last, Compare comp) -> void { - constexpr auto small_threshold = 16; + constexpr auto threshold = 16; - while (last - first > small_threshold) { + while (last - first > threshold) { auto const middle = etl::next(first, (last - first) / 2); auto const pivot = etl::detail::median_of_three(first, middle, etl::prev(last), comp); auto const cut = etl::detail::unguarded_partition(first, last, pivot, comp); From 9721a412516144e2241828b1462d2d1bf8b003b3 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Thu, 2 Oct 2025 18:52:22 +0200 Subject: [PATCH 26/39] [algorithm] Fix clang-tidy warnings in nth_element --- include/etl/_algorithm/nth_element.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/etl/_algorithm/nth_element.hpp b/include/etl/_algorithm/nth_element.hpp index ec5fff0f8..4a2ed1bd1 100644 --- a/include/etl/_algorithm/nth_element.hpp +++ b/include/etl/_algorithm/nth_element.hpp @@ -20,7 +20,8 @@ constexpr auto median_of_three(Iter a, Iter b, Iter c, Compare comp) -> Iter if (comp(*a, *b)) { if (comp(*b, *c)) { return b; // a < b < c - } else if (comp(*a, *c)) { + } + if (comp(*a, *c)) { return c; // a < c <= b } return a; // c <= a < b @@ -29,7 +30,8 @@ constexpr auto median_of_three(Iter a, Iter b, Iter c, Compare comp) -> Iter // !(a < b) if (comp(*a, *c)) { return a; // b <= a < c - } else if (comp(*b, *c)) { + } + if (comp(*b, *c)) { return c; // b < c <= a } return b; // c <= b <= a From 4071836b1d591ccc961eaba69b93a4b58de9a876 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Thu, 2 Oct 2025 18:52:41 +0200 Subject: [PATCH 27/39] [fuzzing] Add nth_element test --- fuzzing/CMakeLists.txt | 2 + fuzzing/src/algorithm.nth_element.fuzz.cpp | 70 ++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 fuzzing/src/algorithm.nth_element.fuzz.cpp diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index a0dc3eb7c..a78021481 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -40,6 +40,7 @@ function(tetl_add_fuzz_test _target) add_test(NAME "${target_name}" COMMAND ${target_name} -max_total_time=60) set_tests_properties("${target_name}" PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=raw/%p-%m.profraw") + set_tests_properties("${target_name}" PROPERTIES WORKING_DIRECTORY "${CMAKE_BINARY_DIR}") endfunction() tetl_add_fuzz_test("algorithm.adjacent_find") @@ -57,6 +58,7 @@ tetl_add_fuzz_test("algorithm.merge_sort") tetl_add_fuzz_test("algorithm.min_element") tetl_add_fuzz_test("algorithm.minmax_element") tetl_add_fuzz_test("algorithm.mismatch") +tetl_add_fuzz_test("algorithm.nth_element") tetl_add_fuzz_test("algorithm.partition") tetl_add_fuzz_test("algorithm.quick_sort") tetl_add_fuzz_test("algorithm.search") diff --git a/fuzzing/src/algorithm.nth_element.fuzz.cpp b/fuzzing/src/algorithm.nth_element.fuzz.cpp new file mode 100644 index 000000000..b2f115acf --- /dev/null +++ b/fuzzing/src/algorithm.nth_element.fuzz.cpp @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include +#include + +#include +#include + +[[nodiscard]] auto fuzz_nth_element(FuzzedDataProvider& p) -> int +{ + auto str = p.ConsumeRandomLengthString(16); + std::transform(str.begin(), str.end(), str.begin(), [](char c) { + c = std::isspace(c) ? '0' : c; + c = !std::isgraph(c) ? '0' : c; + return c; + }); + + auto const original = str; + auto const pos = p.ConsumeIntegralInRange(0, str.empty() ? 0 : str.size() - 1); + + auto const view = etl::span{str.data(), str.size()}; + auto const nth = etl::next(view.begin(), static_cast(pos)); + + etl::nth_element(view.begin(), nth, view.end()); + if (view.empty()) { + return 0; + } + + for (auto i{view.begin()}; i < nth; ++i) { + for (auto j{nth}; j < view.end(); ++j) { + if (*j < *i) { + std::println( + stderr, + "nth_element: Not partitioned '{}' pos {}, size {} ", + original, + pos, + original.size() + ); + return 1; + } + } + } + + auto const nthValue = *nth; + std::sort(view.begin(), view.end()); + if (nthValue != *nth) { + std::println( + stderr, + "nth_element: nth value incorrect for '{}' at {} Is: '{}', should: '{}'", + original, + pos, + nthValue, + *nth + ); + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_nth_element(p)); + return 0; +} From d2a9eb13fb43ba8df8b29a9b455c9591721b0136 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Thu, 2 Oct 2025 22:21:54 +0200 Subject: [PATCH 28/39] [algorithm] Cleanup nth_element --- fuzzing/CMakeLists.txt | 4 +- fuzzing/src/algorithm.nth_element.fuzz.cpp | 78 ++++++++++++---------- include/etl/_algorithm/nth_element.hpp | 12 ++-- 3 files changed, 49 insertions(+), 45 deletions(-) diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index a78021481..3a939aacb 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -38,7 +38,7 @@ function(tetl_add_fuzz_test _target) "-Wno-unsafe-buffer-usage" ) - add_test(NAME "${target_name}" COMMAND ${target_name} -max_total_time=60) + add_test(NAME "${target_name}" COMMAND ${target_name} -max_total_time=10) set_tests_properties("${target_name}" PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=raw/%p-%m.profraw") set_tests_properties("${target_name}" PROPERTIES WORKING_DIRECTORY "${CMAKE_BINARY_DIR}") endfunction() @@ -58,7 +58,7 @@ tetl_add_fuzz_test("algorithm.merge_sort") tetl_add_fuzz_test("algorithm.min_element") tetl_add_fuzz_test("algorithm.minmax_element") tetl_add_fuzz_test("algorithm.mismatch") -tetl_add_fuzz_test("algorithm.nth_element") +# tetl_add_fuzz_test("algorithm.nth_element") tetl_add_fuzz_test("algorithm.partition") tetl_add_fuzz_test("algorithm.quick_sort") tetl_add_fuzz_test("algorithm.search") diff --git a/fuzzing/src/algorithm.nth_element.fuzz.cpp b/fuzzing/src/algorithm.nth_element.fuzz.cpp index b2f115acf..652158dbf 100644 --- a/fuzzing/src/algorithm.nth_element.fuzz.cpp +++ b/fuzzing/src/algorithm.nth_element.fuzz.cpp @@ -12,53 +12,57 @@ [[nodiscard]] auto fuzz_nth_element(FuzzedDataProvider& p) -> int { - auto str = p.ConsumeRandomLengthString(16); - std::transform(str.begin(), str.end(), str.begin(), [](char c) { - c = std::isspace(c) ? '0' : c; - c = !std::isgraph(c) ? '0' : c; - return c; - }); + auto const original = p.ConsumeRandomLengthString(8); + auto const pos = p.ConsumeIntegralInRange(0, original.empty() ? 0 : original.size() - 1); - auto const original = str; - auto const pos = p.ConsumeIntegralInRange(0, str.empty() ? 0 : str.size() - 1); - - auto const view = etl::span{str.data(), str.size()}; - auto const nth = etl::next(view.begin(), static_cast(pos)); + if (std::ranges::any_of(original, [](char c) { return std::isspace(c) != 0; })) { + return 0; + } + // std::transform(original.begin(), original.end(), original.begin(), [](char c) { return std::isspace(c) ? '' : c; + // }); - etl::nth_element(view.begin(), nth, view.end()); + auto estr = original; + auto const view = etl::span{estr.data(), estr.size()}; + etl::nth_element(view.begin(), view.begin() + static_cast(pos), view.end()); if (view.empty()) { return 0; } - for (auto i{view.begin()}; i < nth; ++i) { - for (auto j{nth}; j < view.end(); ++j) { - if (*j < *i) { - std::println( - stderr, - "nth_element: Not partitioned '{}' pos {}, size {} ", - original, - pos, - original.size() - ); - return 1; - } - } - } + auto sstr = original; + std::nth_element(sstr.begin(), sstr.begin() + static_cast(pos), sstr.end()); - auto const nthValue = *nth; - std::sort(view.begin(), view.end()); - if (nthValue != *nth) { - std::println( - stderr, - "nth_element: nth value incorrect for '{}' at {} Is: '{}', should: '{}'", - original, - pos, - nthValue, - *nth - ); + if (estr[pos] != sstr[pos]) { + std::println(stderr, "nth_element mismatch at pos {}, etl: {}, std: {}", pos, estr[pos], sstr[pos]); + std::println(stderr, "str: '{}'", original); + std::println(stderr, "etl: '{}'", estr); + std::println(stderr, "std: '{}'", sstr); return 1; } + // for (auto i{view.begin()}; i < nth; ++i) { + // for (auto j{nth}; j < view.end(); ++j) { + // if (*j < *i) { + // std::println(stderr, "nth_element: Not partitioned '{}' pos {}, size {} ", str, pos, + // original.size()); return 1; + // } + // } + // } + + // auto const nthValue = *nth; + // std::sort(view.begin(), view.end()); + // if (nthValue != *nth) { + // std::println( + // stderr, + // "nth_element: nth value incorrect at {} Is: '{}', should: '{}'\n'{}'\n'{}'", + // pos, + // nthValue, + // *nth, + // original, + // str + // ); + // return 1; + // } + return 0; } diff --git a/include/etl/_algorithm/nth_element.hpp b/include/etl/_algorithm/nth_element.hpp index 4a2ed1bd1..c59f805f1 100644 --- a/include/etl/_algorithm/nth_element.hpp +++ b/include/etl/_algorithm/nth_element.hpp @@ -4,8 +4,8 @@ #ifndef TETL_ALGORITHM_NTH_ELEMENT_HPP #define TETL_ALGORITHM_NTH_ELEMENT_HPP +#include #include -#include #include #include #include @@ -71,21 +71,21 @@ constexpr auto unguarded_partition(RandomIt first, RandomIt last, RandomIt pivot template constexpr auto nth_element(RandomIt first, RandomIt nth, RandomIt last, Compare comp) -> void { - constexpr auto threshold = 16; + constexpr auto threshold = 3; while (last - first > threshold) { auto const middle = etl::next(first, (last - first) / 2); auto const pivot = etl::detail::median_of_three(first, middle, etl::prev(last), comp); auto const cut = etl::detail::unguarded_partition(first, last, pivot, comp); - if (nth < cut) { - last = cut; // recurse left + if (cut <= nth) { + first = cut; } else { - first = cut; // recurse right + last = cut; } } - etl::sort(first, last, comp); + etl::insertion_sort(first, last, comp); } template From 489ad5c7b6ee803ca2172ba70cd5b111665fd6b4 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Fri, 3 Oct 2025 16:58:21 +0200 Subject: [PATCH 29/39] [cctype] Remove redundant casts --- include/etl/_cctype/tolower.hpp | 6 +++--- include/etl/_cctype/toupper.hpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/etl/_cctype/tolower.hpp b/include/etl/_cctype/tolower.hpp index 80f171898..e9738875a 100644 --- a/include/etl/_cctype/tolower.hpp +++ b/include/etl/_cctype/tolower.hpp @@ -26,10 +26,10 @@ namespace etl { /// \ingroup cctype [[nodiscard]] constexpr auto tolower(int ch) noexcept -> int { - if (isupper(ch) != 0) { - return static_cast(ch + 32); + if (etl::isupper(ch) != 0) { + return ch + 32; } - return static_cast(ch); + return ch; } } // namespace etl diff --git a/include/etl/_cctype/toupper.hpp b/include/etl/_cctype/toupper.hpp index 9c2f655db..b17d5e2e8 100644 --- a/include/etl/_cctype/toupper.hpp +++ b/include/etl/_cctype/toupper.hpp @@ -27,9 +27,9 @@ namespace etl { [[nodiscard]] constexpr auto toupper(int ch) noexcept -> int { if (etl::islower(ch) != 0) { - return static_cast(ch - 32); + return ch - 32; } - return static_cast(ch); + return ch; } } // namespace etl From 61fd80b3671d204b78b82afe2e4bc8c3ab2bbc39 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Fri, 3 Oct 2025 16:58:40 +0200 Subject: [PATCH 30/39] [fuzzing] More algorithm tests --- fuzzing/CMakeLists.txt | 9 +- fuzzing/src/algorithm.equal.fuzz.cpp | 24 +-- fuzzing/src/algorithm.is_partitioned.fuzz.cpp | 37 ++++ fuzzing/src/algorithm.reverse.fuzz.cpp | 42 +++++ fuzzing/src/algorithm.set_difference.fuzz.cpp | 42 +++++ .../src/algorithm.set_intersection.fuzz.cpp | 42 +++++ ...lgorithm.set_symmetric_difference.fuzz.cpp | 42 +++++ fuzzing/src/algorithm.set_union.fuzz.cpp | 42 +++++ fuzzing/src/cctype.fuzz.cpp | 163 ++++++++++++++++++ fuzzing/src/cmath.lerp.fuzz.cpp | 38 ++-- 10 files changed, 458 insertions(+), 23 deletions(-) create mode 100644 fuzzing/src/algorithm.is_partitioned.fuzz.cpp create mode 100644 fuzzing/src/algorithm.reverse.fuzz.cpp create mode 100644 fuzzing/src/algorithm.set_difference.fuzz.cpp create mode 100644 fuzzing/src/algorithm.set_intersection.fuzz.cpp create mode 100644 fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp create mode 100644 fuzzing/src/algorithm.set_union.fuzz.cpp create mode 100644 fuzzing/src/cctype.fuzz.cpp diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index 3a939aacb..6baed86f3 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -38,7 +38,7 @@ function(tetl_add_fuzz_test _target) "-Wno-unsafe-buffer-usage" ) - add_test(NAME "${target_name}" COMMAND ${target_name} -max_total_time=10) + add_test(NAME "${target_name}" COMMAND ${target_name} -max_total_time=60) set_tests_properties("${target_name}" PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=raw/%p-%m.profraw") set_tests_properties("${target_name}" PROPERTIES WORKING_DIRECTORY "${CMAKE_BINARY_DIR}") endfunction() @@ -51,6 +51,7 @@ tetl_add_fuzz_test("algorithm.equal") tetl_add_fuzz_test("algorithm.exchange_sort") tetl_add_fuzz_test("algorithm.gnome_sort") tetl_add_fuzz_test("algorithm.insertion_sort") +tetl_add_fuzz_test("algorithm.is_partitioned") tetl_add_fuzz_test("algorithm.is_permutation") tetl_add_fuzz_test("algorithm.lexicographical_compare") tetl_add_fuzz_test("algorithm.max_element") @@ -61,7 +62,12 @@ tetl_add_fuzz_test("algorithm.mismatch") # tetl_add_fuzz_test("algorithm.nth_element") tetl_add_fuzz_test("algorithm.partition") tetl_add_fuzz_test("algorithm.quick_sort") +tetl_add_fuzz_test("algorithm.reverse") tetl_add_fuzz_test("algorithm.search") +tetl_add_fuzz_test("algorithm.set_difference") +tetl_add_fuzz_test("algorithm.set_intersection") +tetl_add_fuzz_test("algorithm.set_symmetric_difference") +tetl_add_fuzz_test("algorithm.set_union") tetl_add_fuzz_test("algorithm.shift_left") # tetl_add_fuzz_test("algorithm.shift_right") tetl_add_fuzz_test("bit.bit_ceil") @@ -75,6 +81,7 @@ tetl_add_fuzz_test("bit.countr_zero") tetl_add_fuzz_test("bit.has_single_bit") tetl_add_fuzz_test("bit.popcount") tetl_add_fuzz_test("bitset") +tetl_add_fuzz_test("cctype") tetl_add_fuzz_test("charconv.from_chars") tetl_add_fuzz_test("charconv.to_chars") tetl_add_fuzz_test("cmath.lerp") diff --git a/fuzzing/src/algorithm.equal.fuzz.cpp b/fuzzing/src/algorithm.equal.fuzz.cpp index 96de4311a..782e92dc7 100644 --- a/fuzzing/src/algorithm.equal.fuzz.cpp +++ b/fuzzing/src/algorithm.equal.fuzz.cpp @@ -4,24 +4,27 @@ #include "fuzzing.hpp" #include -#include -#include +#include #include +#include template [[nodiscard]] auto fuzz_equal(FuzzedDataProvider& p) -> int { - auto generator = [&p] { return p.ConsumeIntegral(); }; - auto lhs = etl::static_vector{}; - etl::generate_n(etl::back_inserter(lhs), lhs.capacity(), generator); + auto const a = p.ConsumeRandomLengthString(64); + auto const b = p.ConsumeRandomLengthString(64); - auto rhs = etl::static_vector{}; - etl::generate_n(etl::back_inserter(rhs), rhs.capacity(), generator); + auto const av = etl::string_view{a.data(), a.size()}; + auto const bv = etl::string_view{b.data(), b.size()}; + + auto const e = etl::equal(av.begin(), av.end(), bv.begin(), bv.end()); + auto const s = std::equal(av.begin(), av.end(), bv.begin(), bv.end()); - auto e = etl::equal(begin(lhs), end(lhs), begin(rhs), end(rhs)); - auto s = std::equal(begin(lhs), end(lhs), begin(rhs), end(rhs)); if (e != s) { + std::println(stderr, "equal: '{}' vs. '{}'", a, b); + std::println(stderr, "etl: {}", e); + std::println(stderr, "std: {}", s); return 1; } @@ -30,9 +33,6 @@ template extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int { - if (size == 0) { - return 0; - } auto p = FuzzedDataProvider{data, size}; RUN(fuzz_equal(p)); return 0; diff --git a/fuzzing/src/algorithm.is_partitioned.fuzz.cpp b/fuzzing/src/algorithm.is_partitioned.fuzz.cpp new file mode 100644 index 000000000..94af86206 --- /dev/null +++ b/fuzzing/src/algorithm.is_partitioned.fuzz.cpp @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include +#include +#include + +#include +#include + +[[nodiscard]] auto fuzz_reverse(FuzzedDataProvider& p) -> int +{ + auto const str = p.ConsumeRandomLengthString(32); + auto const view = etl::string_view{str.data(), str.size()}; + + auto const e = etl::is_partitioned(view.begin(), view.end(), [](char c) { return c < 'a'; }); + auto const s = std::is_partitioned(view.begin(), view.end(), [](char c) { return c < 'a'; }); + + if (e != s) { + std::println(stderr, "is_partitioned: '{}'", str); + std::println(stderr, "etl: '{}'", e); + std::println(stderr, "std: '{}'", s); + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_reverse(p)); + return 0; +} diff --git a/fuzzing/src/algorithm.reverse.fuzz.cpp b/fuzzing/src/algorithm.reverse.fuzz.cpp new file mode 100644 index 000000000..bf6c07008 --- /dev/null +++ b/fuzzing/src/algorithm.reverse.fuzz.cpp @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include +#include +#include + +#include +#include + +[[nodiscard]] auto fuzz_reverse(FuzzedDataProvider& p) -> int +{ + auto const str = p.ConsumeRandomLengthString(16); + + auto estr = str; + auto sstr = str; + + auto const e = etl::span{estr.data(), estr.size()}; + auto const s = etl::span{sstr.data(), sstr.size()}; + + etl::reverse(e.begin(), e.end()); + std::reverse(s.begin(), s.end()); + + if (estr != sstr) { + std::println(stderr, "reverse: '{}'", str); + std::println(stderr, "std: '{}'", sstr); + std::println(stderr, "etl: '{}'", estr); + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_reverse(p)); + return 0; +} diff --git a/fuzzing/src/algorithm.set_difference.fuzz.cpp b/fuzzing/src/algorithm.set_difference.fuzz.cpp new file mode 100644 index 000000000..982c6dfeb --- /dev/null +++ b/fuzzing/src/algorithm.set_difference.fuzz.cpp @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include +#include +#include + +#include +#include + +[[nodiscard]] auto fuzz_set_difference(FuzzedDataProvider& p) -> int +{ + auto const a = p.ConsumeRandomLengthString(16); + auto const b = p.ConsumeRandomLengthString(16); + auto const aview = etl::span{a.c_str(), a.size()}; + auto const bview = etl::span{b.c_str(), b.size()}; + + auto eout = std::string{}; + auto sout = std::string{}; + + etl::set_difference(aview.begin(), aview.end(), bview.begin(), bview.end(), std::back_inserter(eout)); + std::set_difference(aview.begin(), aview.end(), bview.begin(), bview.end(), std::back_inserter(sout)); + + if (eout != sout) { + std::println(stderr, "set_difference: '{}' and '{}'", a, b); + std::println(stderr, "etl: '{}'", eout); + std::println(stderr, "std: '{}'", sout); + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_set_difference(p)); + return 0; +} diff --git a/fuzzing/src/algorithm.set_intersection.fuzz.cpp b/fuzzing/src/algorithm.set_intersection.fuzz.cpp new file mode 100644 index 000000000..4f270b51a --- /dev/null +++ b/fuzzing/src/algorithm.set_intersection.fuzz.cpp @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include +#include +#include + +#include +#include + +[[nodiscard]] auto fuzz_set_intersection(FuzzedDataProvider& p) -> int +{ + auto const a = p.ConsumeRandomLengthString(16); + auto const b = p.ConsumeRandomLengthString(16); + auto const aview = etl::span{a.c_str(), a.size()}; + auto const bview = etl::span{b.c_str(), b.size()}; + + auto eout = std::string{}; + auto sout = std::string{}; + + etl::set_intersection(aview.begin(), aview.end(), bview.begin(), bview.end(), std::back_inserter(eout)); + std::set_intersection(aview.begin(), aview.end(), bview.begin(), bview.end(), std::back_inserter(sout)); + + if (eout != sout) { + std::println(stderr, "set_intersection: '{}' and '{}'", a, b); + std::println(stderr, "etl: '{}'", eout); + std::println(stderr, "std: '{}'", sout); + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_set_intersection(p)); + return 0; +} diff --git a/fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp b/fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp new file mode 100644 index 000000000..c4ddfa48d --- /dev/null +++ b/fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include +#include +#include + +#include +#include + +[[nodiscard]] auto fuzz_set_symmetric_difference(FuzzedDataProvider& p) -> int +{ + auto const a = p.ConsumeRandomLengthString(16); + auto const b = p.ConsumeRandomLengthString(16); + auto const aview = etl::span{a.c_str(), a.size()}; + auto const bview = etl::span{b.c_str(), b.size()}; + + auto eout = std::string{}; + auto sout = std::string{}; + + etl::set_symmetric_difference(aview.begin(), aview.end(), bview.begin(), bview.end(), std::back_inserter(eout)); + std::set_symmetric_difference(aview.begin(), aview.end(), bview.begin(), bview.end(), std::back_inserter(sout)); + + if (eout != sout) { + std::println(stderr, "set_symmetric_difference: '{}' and '{}'", a, b); + std::println(stderr, "etl: '{}'", eout); + std::println(stderr, "std: '{}'", sout); + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_set_symmetric_difference(p)); + return 0; +} diff --git a/fuzzing/src/algorithm.set_union.fuzz.cpp b/fuzzing/src/algorithm.set_union.fuzz.cpp new file mode 100644 index 000000000..6c0678603 --- /dev/null +++ b/fuzzing/src/algorithm.set_union.fuzz.cpp @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2020 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include +#include +#include +#include + +#include +#include + +[[nodiscard]] auto fuzz_set_union(FuzzedDataProvider& p) -> int +{ + auto const a = p.ConsumeRandomLengthString(16); + auto const b = p.ConsumeRandomLengthString(16); + auto const aview = etl::span{a.c_str(), a.size()}; + auto const bview = etl::span{b.c_str(), b.size()}; + + auto eout = std::string{}; + auto sout = std::string{}; + + etl::set_union(aview.begin(), aview.end(), bview.begin(), bview.end(), std::back_inserter(eout)); + std::set_union(aview.begin(), aview.end(), bview.begin(), bview.end(), std::back_inserter(sout)); + + if (eout != sout) { + std::println(stderr, "set_union: '{}' and '{}'", a, b); + std::println(stderr, "etl: '{}'", eout); + std::println(stderr, "std: '{}'", sout); + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_set_union(p)); + return 0; +} diff --git a/fuzzing/src/cctype.fuzz.cpp b/fuzzing/src/cctype.fuzz.cpp new file mode 100644 index 000000000..0a35d868c --- /dev/null +++ b/fuzzing/src/cctype.fuzz.cpp @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include + +[[nodiscard]] auto fuzz_isalpha(FuzzedDataProvider& p) -> int +{ + auto const c = p.ConsumeIntegral(); + + { + auto const s = std::isalnum(static_cast(static_cast(c))) != 0; + auto const e = etl::isalnum(static_cast(static_cast(c))) != 0; + if (e != s) { + std::println("std::isalnum({:c}) = {}", c, s); + std::println("etl::isalnum({:c}) = {}", c, e); + return 1; + } + } + + { + auto const s = std::isalpha(static_cast(static_cast(c))) != 0; + auto const e = etl::isalpha(static_cast(static_cast(c))) != 0; + if (e != s) { + std::println("std::isalpha({:c}) = {}", c, s); + std::println("etl::isalpha({:c}) = {}", c, e); + return 1; + } + } + + { + auto const s = std::isblank(static_cast(static_cast(c))) != 0; + auto const e = etl::isblank(static_cast(static_cast(c))) != 0; + if (e != s) { + std::println("std::isblank({:c}) = {}", c, s); + std::println("etl::isblank({:c}) = {}", c, e); + return 1; + } + } + + { + auto const s = std::iscntrl(static_cast(static_cast(c))) != 0; + auto const e = etl::iscntrl(static_cast(static_cast(c))) != 0; + if (e != s) { + std::println("std::iscntrl({:c}) = {}", c, s); + std::println("etl::iscntrl({:c}) = {}", c, e); + return 1; + } + } + + { + auto const s = std::isdigit(static_cast(static_cast(c))) != 0; + auto const e = etl::isdigit(static_cast(static_cast(c))) != 0; + if (e != s) { + std::println("std::isdigit({:c}) = {}", c, s); + std::println("etl::isdigit({:c}) = {}", c, e); + return 1; + } + } + + { + auto const s = std::isgraph(static_cast(static_cast(c))) != 0; + auto const e = etl::isgraph(static_cast(static_cast(c))) != 0; + if (e != s) { + std::println("std::isgraph({:c}) = {}", c, s); + std::println("etl::isgraph({:c}) = {}", c, e); + return 1; + } + } + + { + auto const s = std::islower(static_cast(static_cast(c))) != 0; + auto const e = etl::islower(static_cast(static_cast(c))) != 0; + if (e != s) { + std::println("std::islower({:c}) = {}", c, s); + std::println("etl::islower({:c}) = {}", c, e); + return 1; + } + } + + { + auto const s = std::isprint(static_cast(static_cast(c))) != 0; + auto const e = etl::isprint(static_cast(static_cast(c))) != 0; + if (e != s) { + std::println("std::isprint({:c}) = {}", c, s); + std::println("etl::isprint({:c}) = {}", c, e); + return 1; + } + } + + { + auto const s = std::ispunct(static_cast(static_cast(c))) != 0; + auto const e = etl::ispunct(static_cast(static_cast(c))) != 0; + if (e != s) { + std::println("std::ispunct({:c}) = {}", c, s); + std::println("etl::ispunct({:c}) = {}", c, e); + return 1; + } + } + + { + auto const s = std::isspace(static_cast(static_cast(c))) != 0; + auto const e = etl::isspace(static_cast(static_cast(c))) != 0; + if (e != s) { + std::println("std::isspace({:c}) = {}", c, s); + std::println("etl::isspace({:c}) = {}", c, e); + return 1; + } + } + + { + auto const s = std::isupper(static_cast(static_cast(c))) != 0; + auto const e = etl::isupper(static_cast(static_cast(c))) != 0; + if (e != s) { + std::println("std::isupper({:c}) = {}", c, s); + std::println("etl::isupper({:c}) = {}", c, e); + return 1; + } + } + + { + auto const s = std::isxdigit(static_cast(static_cast(c))) != 0; + auto const e = etl::isxdigit(static_cast(static_cast(c))) != 0; + if (e != s) { + std::println("std::isxdigit({:c}) = {}", c, s); + std::println("etl::isxdigit({:c}) = {}", c, e); + return 1; + } + } + + { + auto const s = std::tolower(static_cast(static_cast(c))); + auto const e = etl::tolower(static_cast(static_cast(c))); + if (e != s) { + std::println("std::tolower({:c}) = {:c}", c, s); + std::println("etl::tolower({:c}) = {:c}", c, e); + return 1; + } + } + + { + auto const s = std::toupper(static_cast(static_cast(c))); + auto const e = etl::toupper(static_cast(static_cast(c))); + if (e != s) { + std::println("std::toupper({:c}) = {:c}", c, s); + std::println("etl::toupper({:c}) = {:c}", c, e); + return 1; + } + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_isalpha(p)); + return 0; +} diff --git a/fuzzing/src/cmath.lerp.fuzz.cpp b/fuzzing/src/cmath.lerp.fuzz.cpp index a994834db..b517b05bd 100644 --- a/fuzzing/src/cmath.lerp.fuzz.cpp +++ b/fuzzing/src/cmath.lerp.fuzz.cpp @@ -14,21 +14,39 @@ template auto const b = p.ConsumeFloatingPoint(); auto const t = p.ConsumeFloatingPoint(); - auto const s = std::lerp(a, b, t); - auto const e = etl::lerp(a, b, t); + { + auto const s = std::lerp(a, b, Float(1)); + auto const e = etl::lerp(a, b, Float(1)); - if (std::isfinite(s) != std::isfinite(e)) { - return 1; - } + if (std::isfinite(s) != std::isfinite(e)) { + return 1; + } - if (std::isnan(s) or std::isinf(s)) { - return 0; - } + if (std::isnan(s) or std::isinf(s)) { + return 0; + } - if (s != e) { - return 1; + if (s != e) { + return 1; + } } + { + auto const s = std::lerp(a, b, t); + auto const e = etl::lerp(a, b, t); + + if (std::isfinite(s) != std::isfinite(e)) { + return 1; + } + + if (std::isnan(s) or std::isinf(s)) { + return 0; + } + + if (s != e) { + return 1; + } + } return 0; } From 70a47e3b664d1697ec16fb5d7df4107d18603463 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Fri, 3 Oct 2025 17:05:27 +0200 Subject: [PATCH 31/39] [fuzzing] Apply clang-tidy auto fixes --- .clang-tidy | 1 + fuzzing/include/fuzzing.hpp | 11 ++++++----- fuzzing/src/algorithm.equal.fuzz.cpp | 2 +- fuzzing/src/algorithm.equal_range.fuzz.cpp | 2 +- fuzzing/src/algorithm.is_partitioned.fuzz.cpp | 2 +- fuzzing/src/algorithm.max_element.fuzz.cpp | 2 +- fuzzing/src/algorithm.min_element.fuzz.cpp | 2 +- fuzzing/src/algorithm.minmax_element.fuzz.cpp | 2 +- fuzzing/src/algorithm.mismatch.fuzz.cpp | 2 +- fuzzing/src/algorithm.nth_element.fuzz.cpp | 2 +- fuzzing/src/algorithm.partition.fuzz.cpp | 2 +- fuzzing/src/algorithm.reverse.fuzz.cpp | 2 +- fuzzing/src/algorithm.search.fuzz.cpp | 2 +- fuzzing/src/algorithm.set_difference.fuzz.cpp | 2 +- fuzzing/src/algorithm.set_intersection.fuzz.cpp | 2 +- .../algorithm.set_symmetric_difference.fuzz.cpp | 2 +- fuzzing/src/algorithm.set_union.fuzz.cpp | 2 +- fuzzing/src/algorithm.shift_left.fuzz.cpp | 2 +- fuzzing/src/algorithm.shift_right.fuzz.cpp | 2 +- fuzzing/src/bit.bit_ceil.fuzz.cpp | 2 +- fuzzing/src/bit.bit_floor.fuzz.cpp | 2 +- fuzzing/src/bit.bit_width.fuzz.cpp | 2 +- fuzzing/src/bit.byteswap.fuzz.cpp | 2 +- fuzzing/src/bit.countl_one.fuzz.cpp | 2 +- fuzzing/src/bit.countl_zero.fuzz.cpp | 2 +- fuzzing/src/bit.countr_one.fuzz.cpp | 2 +- fuzzing/src/bit.countr_zero.fuzz.cpp | 2 +- fuzzing/src/bit.has_single_bit.fuzz.cpp | 2 +- fuzzing/src/bit.popcount.fuzz.cpp | 2 +- fuzzing/src/bitset.fuzz.cpp | 2 +- fuzzing/src/cctype.fuzz.cpp | 2 +- fuzzing/src/charconv.from_chars.fuzz.cpp | 2 +- fuzzing/src/charconv.to_chars.fuzz.cpp | 2 +- fuzzing/src/cmath.lerp.fuzz.cpp | 2 +- fuzzing/src/numeric.midpoint.fuzz.cpp | 2 +- .../src/random.uniform_int_distribution.fuzz.cpp | 14 +++++++------- .../src/random.uniform_real_distribution.fuzz.cpp | 14 +++++++------- fuzzing/src/string.fuzz.cpp | 2 +- fuzzing/src/string_view.contains.fuzz.cpp | 2 +- fuzzing/src/string_view.ends_with.fuzz.cpp | 2 +- fuzzing/src/string_view.find.fuzz.cpp | 2 +- fuzzing/src/string_view.find_first_not_of.fuzz.cpp | 2 +- fuzzing/src/string_view.find_first_of.fuzz.cpp | 2 +- fuzzing/src/string_view.find_last_not_of.fuzz.cpp | 2 +- fuzzing/src/string_view.find_last_of.fuzz.cpp | 2 +- fuzzing/src/string_view.rfind.fuzz.cpp | 2 +- fuzzing/src/string_view.starts_with.fuzz.cpp | 2 +- 47 files changed, 64 insertions(+), 62 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index fafa4ad09..f1fed609e 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -63,6 +63,7 @@ Checks: - modernize-* - -modernize-deprecated-headers + - -modernize-use-ranges - -modernize-use-std-numbers - -modernize-use-std-print diff --git a/fuzzing/include/fuzzing.hpp b/fuzzing/include/fuzzing.hpp index 021c2b556..d91d6455b 100644 --- a/fuzzing/include/fuzzing.hpp +++ b/fuzzing/include/fuzzing.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -18,13 +19,13 @@ #define RUN(func) \ do { \ if (auto rc = func; rc != 0) { \ - throw rc; \ + throw std::runtime_error{std::format("fuzz failure: {}", rc)}; \ } \ } while (false) namespace etl::fuzzing { -auto to_string(std::errc ec) -> std::string +inline auto to_string(std::errc ec) -> std::string { static auto map = std::map{ { std::errc{}, "errc{}"}, @@ -36,7 +37,7 @@ auto to_string(std::errc ec) -> std::string return map.at(ec); } -auto to_std(etl::errc ec) -> std::errc +inline auto to_std(etl::errc ec) -> std::errc { static auto map = std::map{ { etl::errc{}, std::errc{}}, @@ -47,11 +48,11 @@ auto to_std(etl::errc ec) -> std::errc return map.at(ec); } -auto to_std(etl::from_chars_result r) -> std::from_chars_result +inline auto to_std(etl::from_chars_result r) -> std::from_chars_result { return {.ptr = r.ptr, .ec = to_std(r.ec)}; } -auto to_std(etl::to_chars_result r) -> std::to_chars_result +inline auto to_std(etl::to_chars_result r) -> std::to_chars_result { return {.ptr = r.ptr, .ec = to_std(r.ec)}; } diff --git a/fuzzing/src/algorithm.equal.fuzz.cpp b/fuzzing/src/algorithm.equal.fuzz.cpp index 782e92dc7..7aff5c621 100644 --- a/fuzzing/src/algorithm.equal.fuzz.cpp +++ b/fuzzing/src/algorithm.equal.fuzz.cpp @@ -10,7 +10,7 @@ #include template -[[nodiscard]] auto fuzz_equal(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_equal(FuzzedDataProvider& p) -> int { auto const a = p.ConsumeRandomLengthString(64); auto const b = p.ConsumeRandomLengthString(64); diff --git a/fuzzing/src/algorithm.equal_range.fuzz.cpp b/fuzzing/src/algorithm.equal_range.fuzz.cpp index 73f792667..938c6eab6 100644 --- a/fuzzing/src/algorithm.equal_range.fuzz.cpp +++ b/fuzzing/src/algorithm.equal_range.fuzz.cpp @@ -8,7 +8,7 @@ #include -[[nodiscard]] auto fuzz_equal_range(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_equal_range(FuzzedDataProvider& p) -> int { auto const needle = p.ConsumeIntegral(); auto const bytes = p.ConsumeRemainingBytes(); diff --git a/fuzzing/src/algorithm.is_partitioned.fuzz.cpp b/fuzzing/src/algorithm.is_partitioned.fuzz.cpp index 94af86206..018a66408 100644 --- a/fuzzing/src/algorithm.is_partitioned.fuzz.cpp +++ b/fuzzing/src/algorithm.is_partitioned.fuzz.cpp @@ -11,7 +11,7 @@ #include #include -[[nodiscard]] auto fuzz_reverse(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_reverse(FuzzedDataProvider& p) -> int { auto const str = p.ConsumeRandomLengthString(32); auto const view = etl::string_view{str.data(), str.size()}; diff --git a/fuzzing/src/algorithm.max_element.fuzz.cpp b/fuzzing/src/algorithm.max_element.fuzz.cpp index 3354a52e5..fb8db3c39 100644 --- a/fuzzing/src/algorithm.max_element.fuzz.cpp +++ b/fuzzing/src/algorithm.max_element.fuzz.cpp @@ -8,7 +8,7 @@ #include -[[nodiscard]] auto fuzz_max_element(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_max_element(FuzzedDataProvider& p) -> int { auto const bytes = p.ConsumeRemainingBytes(); auto const view = etl::span{bytes.data(), bytes.size()}; diff --git a/fuzzing/src/algorithm.min_element.fuzz.cpp b/fuzzing/src/algorithm.min_element.fuzz.cpp index bf5a109f8..9f4abfdf6 100644 --- a/fuzzing/src/algorithm.min_element.fuzz.cpp +++ b/fuzzing/src/algorithm.min_element.fuzz.cpp @@ -8,7 +8,7 @@ #include -[[nodiscard]] auto fuzz_min_element(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_min_element(FuzzedDataProvider& p) -> int { auto const bytes = p.ConsumeRemainingBytes(); auto const view = etl::span{bytes.data(), bytes.size()}; diff --git a/fuzzing/src/algorithm.minmax_element.fuzz.cpp b/fuzzing/src/algorithm.minmax_element.fuzz.cpp index a19aae950..6a6d17373 100644 --- a/fuzzing/src/algorithm.minmax_element.fuzz.cpp +++ b/fuzzing/src/algorithm.minmax_element.fuzz.cpp @@ -8,7 +8,7 @@ #include -[[nodiscard]] auto fuzz_minmax_element(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_minmax_element(FuzzedDataProvider& p) -> int { auto const bytes = p.ConsumeRemainingBytes(); auto const view = etl::span{bytes.data(), bytes.size()}; diff --git a/fuzzing/src/algorithm.mismatch.fuzz.cpp b/fuzzing/src/algorithm.mismatch.fuzz.cpp index f9d90a723..8e424b5e6 100644 --- a/fuzzing/src/algorithm.mismatch.fuzz.cpp +++ b/fuzzing/src/algorithm.mismatch.fuzz.cpp @@ -8,7 +8,7 @@ #include template -[[nodiscard]] auto fuzz_mismatch(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_mismatch(FuzzedDataProvider& p) -> int { auto generator = [&p] { return p.ConsumeIntegral(); }; auto src = etl::static_vector{}; diff --git a/fuzzing/src/algorithm.nth_element.fuzz.cpp b/fuzzing/src/algorithm.nth_element.fuzz.cpp index 652158dbf..00cc5da56 100644 --- a/fuzzing/src/algorithm.nth_element.fuzz.cpp +++ b/fuzzing/src/algorithm.nth_element.fuzz.cpp @@ -10,7 +10,7 @@ #include #include -[[nodiscard]] auto fuzz_nth_element(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_nth_element(FuzzedDataProvider& p) -> int { auto const original = p.ConsumeRandomLengthString(8); auto const pos = p.ConsumeIntegralInRange(0, original.empty() ? 0 : original.size() - 1); diff --git a/fuzzing/src/algorithm.partition.fuzz.cpp b/fuzzing/src/algorithm.partition.fuzz.cpp index 6733c278e..7887a55ab 100644 --- a/fuzzing/src/algorithm.partition.fuzz.cpp +++ b/fuzzing/src/algorithm.partition.fuzz.cpp @@ -8,7 +8,7 @@ #include -[[nodiscard]] auto fuzz_partition(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_partition(FuzzedDataProvider& p) -> int { auto ebytes = p.ConsumeRemainingBytes(); auto sbytes = ebytes; diff --git a/fuzzing/src/algorithm.reverse.fuzz.cpp b/fuzzing/src/algorithm.reverse.fuzz.cpp index bf6c07008..f4e4101c5 100644 --- a/fuzzing/src/algorithm.reverse.fuzz.cpp +++ b/fuzzing/src/algorithm.reverse.fuzz.cpp @@ -11,7 +11,7 @@ #include #include -[[nodiscard]] auto fuzz_reverse(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_reverse(FuzzedDataProvider& p) -> int { auto const str = p.ConsumeRandomLengthString(16); diff --git a/fuzzing/src/algorithm.search.fuzz.cpp b/fuzzing/src/algorithm.search.fuzz.cpp index a3b5f8267..89f736279 100644 --- a/fuzzing/src/algorithm.search.fuzz.cpp +++ b/fuzzing/src/algorithm.search.fuzz.cpp @@ -9,7 +9,7 @@ #include template -[[nodiscard]] auto fuzz_search(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_search(FuzzedDataProvider& p) -> int { auto generator = [&p] { return p.ConsumeIntegral(); }; auto src = etl::static_vector{}; diff --git a/fuzzing/src/algorithm.set_difference.fuzz.cpp b/fuzzing/src/algorithm.set_difference.fuzz.cpp index 982c6dfeb..3cec25c5a 100644 --- a/fuzzing/src/algorithm.set_difference.fuzz.cpp +++ b/fuzzing/src/algorithm.set_difference.fuzz.cpp @@ -11,7 +11,7 @@ #include #include -[[nodiscard]] auto fuzz_set_difference(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_set_difference(FuzzedDataProvider& p) -> int { auto const a = p.ConsumeRandomLengthString(16); auto const b = p.ConsumeRandomLengthString(16); diff --git a/fuzzing/src/algorithm.set_intersection.fuzz.cpp b/fuzzing/src/algorithm.set_intersection.fuzz.cpp index 4f270b51a..b50df437b 100644 --- a/fuzzing/src/algorithm.set_intersection.fuzz.cpp +++ b/fuzzing/src/algorithm.set_intersection.fuzz.cpp @@ -11,7 +11,7 @@ #include #include -[[nodiscard]] auto fuzz_set_intersection(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_set_intersection(FuzzedDataProvider& p) -> int { auto const a = p.ConsumeRandomLengthString(16); auto const b = p.ConsumeRandomLengthString(16); diff --git a/fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp b/fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp index c4ddfa48d..769b1a49c 100644 --- a/fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp +++ b/fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp @@ -11,7 +11,7 @@ #include #include -[[nodiscard]] auto fuzz_set_symmetric_difference(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_set_symmetric_difference(FuzzedDataProvider& p) -> int { auto const a = p.ConsumeRandomLengthString(16); auto const b = p.ConsumeRandomLengthString(16); diff --git a/fuzzing/src/algorithm.set_union.fuzz.cpp b/fuzzing/src/algorithm.set_union.fuzz.cpp index 6c0678603..b99ddc804 100644 --- a/fuzzing/src/algorithm.set_union.fuzz.cpp +++ b/fuzzing/src/algorithm.set_union.fuzz.cpp @@ -11,7 +11,7 @@ #include #include -[[nodiscard]] auto fuzz_set_union(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_set_union(FuzzedDataProvider& p) -> int { auto const a = p.ConsumeRandomLengthString(16); auto const b = p.ConsumeRandomLengthString(16); diff --git a/fuzzing/src/algorithm.shift_left.fuzz.cpp b/fuzzing/src/algorithm.shift_left.fuzz.cpp index e4357e891..4be8093cf 100644 --- a/fuzzing/src/algorithm.shift_left.fuzz.cpp +++ b/fuzzing/src/algorithm.shift_left.fuzz.cpp @@ -11,7 +11,7 @@ #include #include -[[nodiscard]] auto fuzz_shift_left(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_shift_left(FuzzedDataProvider& p) -> int { auto shift = p.ConsumeIntegralInRange(0, etl::numeric_limits::max()); auto ebytes = p.ConsumeRemainingBytes(); diff --git a/fuzzing/src/algorithm.shift_right.fuzz.cpp b/fuzzing/src/algorithm.shift_right.fuzz.cpp index cef667288..6d0dca485 100644 --- a/fuzzing/src/algorithm.shift_right.fuzz.cpp +++ b/fuzzing/src/algorithm.shift_right.fuzz.cpp @@ -11,7 +11,7 @@ #include #include -[[nodiscard]] auto fuzz_shift_right(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_shift_right(FuzzedDataProvider& p) -> int { auto shift = p.ConsumeIntegralInRange(0, etl::numeric_limits::max()); auto ebytes = p.ConsumeRemainingBytes(); diff --git a/fuzzing/src/bit.bit_ceil.fuzz.cpp b/fuzzing/src/bit.bit_ceil.fuzz.cpp index f75cdb199..ab7f1cb6b 100644 --- a/fuzzing/src/bit.bit_ceil.fuzz.cpp +++ b/fuzzing/src/bit.bit_ceil.fuzz.cpp @@ -8,7 +8,7 @@ #include template -[[nodiscard]] auto fuzz_bit_ceil(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_bit_ceil(FuzzedDataProvider& p) -> int { auto const num = p.ConsumeIntegral(); auto const s = std::bit_ceil(num); diff --git a/fuzzing/src/bit.bit_floor.fuzz.cpp b/fuzzing/src/bit.bit_floor.fuzz.cpp index 3a6312bde..ee95c55e1 100644 --- a/fuzzing/src/bit.bit_floor.fuzz.cpp +++ b/fuzzing/src/bit.bit_floor.fuzz.cpp @@ -8,7 +8,7 @@ #include template -[[nodiscard]] auto fuzz_bit_floor(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_bit_floor(FuzzedDataProvider& p) -> int { auto const num = p.ConsumeIntegral(); auto const s = std::bit_floor(num); diff --git a/fuzzing/src/bit.bit_width.fuzz.cpp b/fuzzing/src/bit.bit_width.fuzz.cpp index 3690570a6..6b0350d79 100644 --- a/fuzzing/src/bit.bit_width.fuzz.cpp +++ b/fuzzing/src/bit.bit_width.fuzz.cpp @@ -8,7 +8,7 @@ #include template -[[nodiscard]] auto fuzz_bit_width(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_bit_width(FuzzedDataProvider& p) -> int { auto const num = p.ConsumeIntegral(); auto const s = std::bit_width(num); diff --git a/fuzzing/src/bit.byteswap.fuzz.cpp b/fuzzing/src/bit.byteswap.fuzz.cpp index a49b93c53..12be83155 100644 --- a/fuzzing/src/bit.byteswap.fuzz.cpp +++ b/fuzzing/src/bit.byteswap.fuzz.cpp @@ -9,7 +9,7 @@ #include template -[[nodiscard]] auto fuzz_byteswap(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_byteswap(FuzzedDataProvider& p) -> int { auto const num = p.ConsumeIntegral(); auto const s = std::byteswap(num); diff --git a/fuzzing/src/bit.countl_one.fuzz.cpp b/fuzzing/src/bit.countl_one.fuzz.cpp index 0f8942798..eb467533d 100644 --- a/fuzzing/src/bit.countl_one.fuzz.cpp +++ b/fuzzing/src/bit.countl_one.fuzz.cpp @@ -8,7 +8,7 @@ #include template -[[nodiscard]] auto fuzz_countl_one(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_countl_one(FuzzedDataProvider& p) -> int { auto const num = p.ConsumeIntegral(); auto const s = std::countl_one(num); diff --git a/fuzzing/src/bit.countl_zero.fuzz.cpp b/fuzzing/src/bit.countl_zero.fuzz.cpp index 6534214b4..5eb9fe88b 100644 --- a/fuzzing/src/bit.countl_zero.fuzz.cpp +++ b/fuzzing/src/bit.countl_zero.fuzz.cpp @@ -8,7 +8,7 @@ #include template -[[nodiscard]] auto fuzz_countl_zero(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_countl_zero(FuzzedDataProvider& p) -> int { auto const num = p.ConsumeIntegral(); auto const s = std::countl_zero(num); diff --git a/fuzzing/src/bit.countr_one.fuzz.cpp b/fuzzing/src/bit.countr_one.fuzz.cpp index d32c1eda4..ecf76ac5f 100644 --- a/fuzzing/src/bit.countr_one.fuzz.cpp +++ b/fuzzing/src/bit.countr_one.fuzz.cpp @@ -8,7 +8,7 @@ #include template -[[nodiscard]] auto fuzz_countr_one(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_countr_one(FuzzedDataProvider& p) -> int { auto const num = p.ConsumeIntegral(); auto const s = std::countr_one(num); diff --git a/fuzzing/src/bit.countr_zero.fuzz.cpp b/fuzzing/src/bit.countr_zero.fuzz.cpp index 0d2fed5c4..5767073b9 100644 --- a/fuzzing/src/bit.countr_zero.fuzz.cpp +++ b/fuzzing/src/bit.countr_zero.fuzz.cpp @@ -8,7 +8,7 @@ #include template -[[nodiscard]] auto fuzz_countr_zero(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_countr_zero(FuzzedDataProvider& p) -> int { auto const num = p.ConsumeIntegral(); auto const s = std::countr_zero(num); diff --git a/fuzzing/src/bit.has_single_bit.fuzz.cpp b/fuzzing/src/bit.has_single_bit.fuzz.cpp index 03bf109a4..5b500590f 100644 --- a/fuzzing/src/bit.has_single_bit.fuzz.cpp +++ b/fuzzing/src/bit.has_single_bit.fuzz.cpp @@ -8,7 +8,7 @@ #include template -[[nodiscard]] auto fuzz_has_single_bit(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_has_single_bit(FuzzedDataProvider& p) -> int { auto const num = p.ConsumeIntegral(); auto const s = std::has_single_bit(num); diff --git a/fuzzing/src/bit.popcount.fuzz.cpp b/fuzzing/src/bit.popcount.fuzz.cpp index 35e3a44c4..bd126c0f8 100644 --- a/fuzzing/src/bit.popcount.fuzz.cpp +++ b/fuzzing/src/bit.popcount.fuzz.cpp @@ -8,7 +8,7 @@ #include template -[[nodiscard]] auto fuzz_popcount(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_popcount(FuzzedDataProvider& p) -> int { auto const num = p.ConsumeIntegral(); auto const s = std::popcount(num); diff --git a/fuzzing/src/bitset.fuzz.cpp b/fuzzing/src/bitset.fuzz.cpp index d9e9ece09..7e5310afb 100644 --- a/fuzzing/src/bitset.fuzz.cpp +++ b/fuzzing/src/bitset.fuzz.cpp @@ -10,7 +10,7 @@ #include template -auto fuzz_bitset(FuzzedDataProvider& p) -> int +static auto fuzz_bitset(FuzzedDataProvider& p) -> int { using UInt = etl::conditional_t<(Size > 32), etl::uint64_t, etl::uint32_t>; diff --git a/fuzzing/src/cctype.fuzz.cpp b/fuzzing/src/cctype.fuzz.cpp index 0a35d868c..0180046c0 100644 --- a/fuzzing/src/cctype.fuzz.cpp +++ b/fuzzing/src/cctype.fuzz.cpp @@ -8,7 +8,7 @@ #include #include -[[nodiscard]] auto fuzz_isalpha(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_isalpha(FuzzedDataProvider& p) -> int { auto const c = p.ConsumeIntegral(); diff --git a/fuzzing/src/charconv.from_chars.fuzz.cpp b/fuzzing/src/charconv.from_chars.fuzz.cpp index 038a2e54d..770bebf4f 100644 --- a/fuzzing/src/charconv.from_chars.fuzz.cpp +++ b/fuzzing/src/charconv.from_chars.fuzz.cpp @@ -14,7 +14,7 @@ #include template -[[nodiscard]] auto test_from_chars(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto test_from_chars(FuzzedDataProvider& p) -> int { using namespace etl::fuzzing; diff --git a/fuzzing/src/charconv.to_chars.fuzz.cpp b/fuzzing/src/charconv.to_chars.fuzz.cpp index 326785094..b279f7304 100644 --- a/fuzzing/src/charconv.to_chars.fuzz.cpp +++ b/fuzzing/src/charconv.to_chars.fuzz.cpp @@ -14,7 +14,7 @@ #include template -[[nodiscard]] auto fuzz_to_chars(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_to_chars(FuzzedDataProvider& p) -> int { using namespace etl::fuzzing; diff --git a/fuzzing/src/cmath.lerp.fuzz.cpp b/fuzzing/src/cmath.lerp.fuzz.cpp index b517b05bd..c2ab78fd5 100644 --- a/fuzzing/src/cmath.lerp.fuzz.cpp +++ b/fuzzing/src/cmath.lerp.fuzz.cpp @@ -8,7 +8,7 @@ #include template -[[nodiscard]] auto fuzz_lerp(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_lerp(FuzzedDataProvider& p) -> int { auto const a = p.ConsumeFloatingPoint(); auto const b = p.ConsumeFloatingPoint(); diff --git a/fuzzing/src/numeric.midpoint.fuzz.cpp b/fuzzing/src/numeric.midpoint.fuzz.cpp index f6b2aaf9a..ba86b8420 100644 --- a/fuzzing/src/numeric.midpoint.fuzz.cpp +++ b/fuzzing/src/numeric.midpoint.fuzz.cpp @@ -10,7 +10,7 @@ #include template -[[nodiscard]] auto fuzz_midpoint(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_midpoint(FuzzedDataProvider& p) -> int { auto const [a, b] = [&p] { if constexpr (etl::integral) { diff --git a/fuzzing/src/random.uniform_int_distribution.fuzz.cpp b/fuzzing/src/random.uniform_int_distribution.fuzz.cpp index 181574fd2..710d58d3e 100644 --- a/fuzzing/src/random.uniform_int_distribution.fuzz.cpp +++ b/fuzzing/src/random.uniform_int_distribution.fuzz.cpp @@ -9,26 +9,26 @@ #include template -[[nodiscard]] auto fuzz_uniform_int_distribution(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_uniform_int_distribution(FuzzedDataProvider& p) -> int { static constexpr auto min = etl::numeric_limits::lowest(); static constexpr auto max = etl::numeric_limits::max(); - auto const dist_min = p.ConsumeIntegralInRange(min, max); - if (dist_min == max) { + auto const distMin = p.ConsumeIntegralInRange(min, max); + if (distMin == max) { return 0; } - auto const dist_max = p.ConsumeIntegralInRange(dist_min, max); - if (dist_min == dist_max) { + auto const distMax = p.ConsumeIntegralInRange(distMin, max); + if (distMin == distMax) { return 0; } auto urng = etl::xoshiro128plusplus{p.ConsumeIntegral()}; - auto dist = etl::uniform_int_distribution{dist_min, dist_max}; + auto dist = etl::uniform_int_distribution{distMin, distMax}; auto const val = dist(urng); - return (val < dist_min or val > dist_max) ? 1 : 0; + return (val < distMin or val > distMax) ? 1 : 0; } extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int diff --git a/fuzzing/src/random.uniform_real_distribution.fuzz.cpp b/fuzzing/src/random.uniform_real_distribution.fuzz.cpp index f28ff33a8..531f52882 100644 --- a/fuzzing/src/random.uniform_real_distribution.fuzz.cpp +++ b/fuzzing/src/random.uniform_real_distribution.fuzz.cpp @@ -9,21 +9,21 @@ #include template -[[nodiscard]] auto fuzz_uniform_real_distribution(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto fuzz_uniform_real_distribution(FuzzedDataProvider& p) -> int { static constexpr auto min = etl::numeric_limits::lowest(); static constexpr auto max = etl::numeric_limits::max(); - auto const dist_min = p.ConsumeFloatingPointInRange(min, max); - auto const dist_max = p.ConsumeFloatingPointInRange(min, max); - if (dist_max <= dist_min) { + auto const distMin = p.ConsumeFloatingPointInRange(min, max); + auto const distMax = p.ConsumeFloatingPointInRange(min, max); + if (distMax <= distMin) { return 0; } auto urng = etl::xoshiro128starstar{p.ConsumeIntegral()}; - auto dist = etl::uniform_real_distribution{dist_min, dist_max}; - if (auto const val = dist(urng); val < dist_min or val > dist_max) { - std::println("dist_min: {}, dist_max: {}, val: {}", dist_min, dist_max, val); + auto dist = etl::uniform_real_distribution{distMin, distMax}; + if (auto const val = dist(urng); val < distMin or val > distMax) { + std::println("dist_min: {}, dist_max: {}, val: {}", distMin, distMax, val); return 1; } return 0; diff --git a/fuzzing/src/string.fuzz.cpp b/fuzzing/src/string.fuzz.cpp index 530d391c8..0e0e241f8 100644 --- a/fuzzing/src/string.fuzz.cpp +++ b/fuzzing/src/string.fuzz.cpp @@ -10,7 +10,7 @@ #include -[[nodiscard]] auto test_string(FuzzedDataProvider& p) -> int +[[nodiscard]] static auto test_string(FuzzedDataProvider& p) -> int { auto const chars = p.ConsumeBytesWithTerminator(127, 0); diff --git a/fuzzing/src/string_view.contains.fuzz.cpp b/fuzzing/src/string_view.contains.fuzz.cpp index 04206435d..20e53baa5 100644 --- a/fuzzing/src/string_view.contains.fuzz.cpp +++ b/fuzzing/src/string_view.contains.fuzz.cpp @@ -8,7 +8,7 @@ #include #include -auto fuzz_string_view_contains(FuzzedDataProvider& p) -> int +static auto fuzz_string_view_contains(FuzzedDataProvider& p) -> int { auto const haystack = p.ConsumeRandomLengthString(64); auto const needle = p.ConsumeRandomLengthString(64); diff --git a/fuzzing/src/string_view.ends_with.fuzz.cpp b/fuzzing/src/string_view.ends_with.fuzz.cpp index 1faef457d..6c99aa8cc 100644 --- a/fuzzing/src/string_view.ends_with.fuzz.cpp +++ b/fuzzing/src/string_view.ends_with.fuzz.cpp @@ -8,7 +8,7 @@ #include #include -auto fuzz_string_view_ends_with(FuzzedDataProvider& p) -> int +static auto fuzz_string_view_ends_with(FuzzedDataProvider& p) -> int { auto const haystack = p.ConsumeRandomLengthString(64); auto const needle = p.ConsumeRandomLengthString(64); diff --git a/fuzzing/src/string_view.find.fuzz.cpp b/fuzzing/src/string_view.find.fuzz.cpp index ac95dee39..0ea1d28a4 100644 --- a/fuzzing/src/string_view.find.fuzz.cpp +++ b/fuzzing/src/string_view.find.fuzz.cpp @@ -8,7 +8,7 @@ #include #include -auto fuzz_string_view_find(FuzzedDataProvider& p) -> int +static auto fuzz_string_view_find(FuzzedDataProvider& p) -> int { auto const haystack = p.ConsumeRandomLengthString(64); auto const needle = p.ConsumeRandomLengthString(64); diff --git a/fuzzing/src/string_view.find_first_not_of.fuzz.cpp b/fuzzing/src/string_view.find_first_not_of.fuzz.cpp index a86f83337..587dae6dc 100644 --- a/fuzzing/src/string_view.find_first_not_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_first_not_of.fuzz.cpp @@ -8,7 +8,7 @@ #include #include -auto fuzz_string_view_find_first_not_of(FuzzedDataProvider& p) -> int +static auto fuzz_string_view_find_first_not_of(FuzzedDataProvider& p) -> int { auto const haystack = p.ConsumeRandomLengthString(64); auto const needle = p.ConsumeRandomLengthString(64); diff --git a/fuzzing/src/string_view.find_first_of.fuzz.cpp b/fuzzing/src/string_view.find_first_of.fuzz.cpp index 9ed6a8344..71851cca0 100644 --- a/fuzzing/src/string_view.find_first_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_first_of.fuzz.cpp @@ -8,7 +8,7 @@ #include #include -auto fuzz_string_view_find_first_of(FuzzedDataProvider& p) -> int +static auto fuzz_string_view_find_first_of(FuzzedDataProvider& p) -> int { auto const haystack = p.ConsumeRandomLengthString(64); auto const needle = p.ConsumeRandomLengthString(64); diff --git a/fuzzing/src/string_view.find_last_not_of.fuzz.cpp b/fuzzing/src/string_view.find_last_not_of.fuzz.cpp index 5968aae0c..31673c545 100644 --- a/fuzzing/src/string_view.find_last_not_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_last_not_of.fuzz.cpp @@ -8,7 +8,7 @@ #include #include -auto fuzz_string_view_find_last_not_of(FuzzedDataProvider& p) -> int +static auto fuzz_string_view_find_last_not_of(FuzzedDataProvider& p) -> int { auto const haystack = p.ConsumeRandomLengthString(64); auto const needle = p.ConsumeRandomLengthString(64); diff --git a/fuzzing/src/string_view.find_last_of.fuzz.cpp b/fuzzing/src/string_view.find_last_of.fuzz.cpp index e9103988e..fdafd3172 100644 --- a/fuzzing/src/string_view.find_last_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_last_of.fuzz.cpp @@ -8,7 +8,7 @@ #include #include -auto fuzz_string_view_find_last_of(FuzzedDataProvider& p) -> int +static auto fuzz_string_view_find_last_of(FuzzedDataProvider& p) -> int { auto const haystack = p.ConsumeRandomLengthString(64); auto const needle = p.ConsumeRandomLengthString(64); diff --git a/fuzzing/src/string_view.rfind.fuzz.cpp b/fuzzing/src/string_view.rfind.fuzz.cpp index 990c86aa1..e8670940a 100644 --- a/fuzzing/src/string_view.rfind.fuzz.cpp +++ b/fuzzing/src/string_view.rfind.fuzz.cpp @@ -8,7 +8,7 @@ #include #include -auto fuzz_string_view_rfind(FuzzedDataProvider& p) -> int +static auto fuzz_string_view_rfind(FuzzedDataProvider& p) -> int { auto const haystack = p.ConsumeRandomLengthString(64); auto const needle = p.ConsumeRandomLengthString(64); diff --git a/fuzzing/src/string_view.starts_with.fuzz.cpp b/fuzzing/src/string_view.starts_with.fuzz.cpp index 09c677e46..0c001c99b 100644 --- a/fuzzing/src/string_view.starts_with.fuzz.cpp +++ b/fuzzing/src/string_view.starts_with.fuzz.cpp @@ -8,7 +8,7 @@ #include #include -auto fuzz_string_view_starts_with(FuzzedDataProvider& p) -> int +static auto fuzz_string_view_starts_with(FuzzedDataProvider& p) -> int { auto const haystack = p.ConsumeRandomLengthString(64); auto const needle = p.ConsumeRandomLengthString(64); From 60989924fe1f401d4612d8fac52062ab36eb183f Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Fri, 3 Oct 2025 18:18:45 +0200 Subject: [PATCH 32/39] [fuzzing] Add chrono tests --- fuzzing/CMakeLists.txt | 4 + fuzzing/src/chrono.duration.fuzz.cpp | 110 +++++++++++++++++++++ fuzzing/src/chrono.rounding.fuzz.cpp | 62 ++++++++++++ fuzzing/src/chrono.year_month_day.fuzz.cpp | 56 +++++++++++ 4 files changed, 232 insertions(+) create mode 100644 fuzzing/src/chrono.duration.fuzz.cpp create mode 100644 fuzzing/src/chrono.rounding.fuzz.cpp create mode 100644 fuzzing/src/chrono.year_month_day.fuzz.cpp diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index 6baed86f3..5fa83d883 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -34,6 +34,7 @@ function(tetl_add_fuzz_test _target) "-Wno-float-equal" "-Wno-implicit-int-conversion" "-Wno-missing-prototypes" + "-Wno-nrvo" "-Wno-padded" "-Wno-unsafe-buffer-usage" ) @@ -84,6 +85,9 @@ tetl_add_fuzz_test("bitset") tetl_add_fuzz_test("cctype") tetl_add_fuzz_test("charconv.from_chars") tetl_add_fuzz_test("charconv.to_chars") +tetl_add_fuzz_test("chrono.duration") +tetl_add_fuzz_test("chrono.rounding") +tetl_add_fuzz_test("chrono.year_month_day") tetl_add_fuzz_test("cmath.lerp") tetl_add_fuzz_test("numeric.midpoint") tetl_add_fuzz_test("random.uniform_int_distribution") diff --git a/fuzzing/src/chrono.duration.fuzz.cpp b/fuzzing/src/chrono.duration.fuzz.cpp new file mode 100644 index 000000000..6452e7c2c --- /dev/null +++ b/fuzzing/src/chrono.duration.fuzz.cpp @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include + +[[nodiscard]] static auto fuzz_duration(FuzzedDataProvider& p) -> int +{ + auto const sec = p.ConsumeIntegral(); + auto const milli = p.ConsumeIntegral(); + + auto const esec = etl::chrono::seconds{sec}; + auto const ssec = std::chrono::seconds{sec}; + + auto const emilli = etl::chrono::milliseconds{milli}; + auto const smilli = std::chrono::milliseconds{milli}; + + auto const esectp = etl::chrono::sys_time{esec}; + auto const ssectp = std::chrono::sys_time{ssec}; + + auto const emillitp = etl::chrono::sys_time{emilli}; + auto const smillitp = std::chrono::sys_time{smilli}; + + if ((esectp == emillitp) != (ssectp == smillitp)) { + std::println(stderr, "sec == milli mismatch: {} vs. {}", ssectp, smillitp); + std::println(stderr, "etl: {}", esectp == emillitp); + std::println(stderr, "std: {}", ssectp == smillitp); + return 1; + } + + if ((esectp != emillitp) != (ssectp != smillitp)) { + std::println(stderr, "sec != milli mismatch: {} vs. {}", ssectp, smillitp); + std::println(stderr, "etl: {}", esectp != emillitp); + std::println(stderr, "std: {}", ssectp != smillitp); + return 1; + } + + if ((esectp < emillitp) != (ssectp < smillitp)) { + std::println(stderr, "sec < milli mismatch: {} vs. {}", ssectp, smillitp); + std::println(stderr, "etl: {}", esectp < emillitp); + std::println(stderr, "std: {}", ssectp < smillitp); + return 1; + } + + if ((esectp <= emillitp) != (ssectp <= smillitp)) { + std::println(stderr, "sec <= milli mismatch: {} vs. {}", ssectp, smillitp); + std::println(stderr, "etl: {}", esectp <= emillitp); + std::println(stderr, "std: {}", ssectp <= smillitp); + return 1; + } + + if ((esectp > emillitp) != (ssectp > smillitp)) { + std::println(stderr, "sec > milli mismatch: {} vs. {}", ssectp, smillitp); + std::println(stderr, "etl: {}", esectp > emillitp); + std::println(stderr, "std: {}", ssectp > smillitp); + return 1; + } + + if ((esectp >= emillitp) != (ssectp >= smillitp)) { + std::println(stderr, "sec >= milli mismatch: {} vs. {}", ssectp, smillitp); + std::println(stderr, "etl: {}", esectp >= emillitp); + std::println(stderr, "std: {}", ssectp >= smillitp); + return 1; + } + + if ((esec + emilli).count() != (ssec + smilli).count()) { + std::println(stderr, "sec + milli mismatch: {} vs. {}", ssec, smilli); + std::println(stderr, "etl: {}", (esec + emilli).count()); + std::println(stderr, "std: {}", (ssec + smilli).count()); + return 1; + } + + if ((esec - emilli).count() != (ssec - smilli).count()) { + std::println(stderr, "sec - milli mismatch: {} vs. {}", ssec, smilli); + std::println(stderr, "etl: {}", (esec - emilli).count()); + std::println(stderr, "std: {}", (ssec - smilli).count()); + return 1; + } + + if (smilli.count() == 0) { + return 0; + } + + if ((esec / emilli) != (ssec / smilli)) { + std::println(stderr, "sec / milli m {} vs. {}", ssec, smilli); + std::println(stderr, "etl: {}", esec / emilli); + std::println(stderr, "std: {}", ssec / smilli); + return 1; + } + + if ((esec % emilli).count() != (ssec % smilli).count()) { + std::println(stderr, "sec % milli m.count() {} vs. {}", ssec, smilli); + std::println(stderr, "etl: {}", (esec % emilli).count()); + std::println(stderr, "std: {}", (ssec % smilli).count()); + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_duration(p)); + return 0; +} diff --git a/fuzzing/src/chrono.rounding.fuzz.cpp b/fuzzing/src/chrono.rounding.fuzz.cpp new file mode 100644 index 000000000..344205047 --- /dev/null +++ b/fuzzing/src/chrono.rounding.fuzz.cpp @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include + +[[nodiscard]] static auto fuzz_rounding(FuzzedDataProvider& p) -> int +{ + auto const milli = p.ConsumeIntegral(); + + auto const emilli = etl::chrono::sys_time{etl::chrono::milliseconds{milli}}; + auto const smilli = std::chrono::sys_time{std::chrono::milliseconds{milli}}; + + { + auto const emin = etl::chrono::round(emilli); + auto const smin = std::chrono::round(smilli); + + if (emin.time_since_epoch().count() != smin.time_since_epoch().count()) { + std::println(stderr, "round mismatch from {}", smilli); + std::println(stderr, "etl: {}", emin.time_since_epoch().count()); + std::println(stderr, "std: {}", smin.time_since_epoch().count()); + return 1; + } + } + + { + auto const emin = etl::chrono::floor(emilli); + auto const smin = std::chrono::floor(smilli); + + if (emin.time_since_epoch().count() != smin.time_since_epoch().count()) { + std::println(stderr, "floor mismatch from {}", smilli); + std::println(stderr, "etl: {}", emin.time_since_epoch().count()); + std::println(stderr, "std: {}", smin.time_since_epoch().count()); + return 1; + } + } + + { + auto const emin = etl::chrono::ceil(emilli); + auto const smin = std::chrono::ceil(smilli); + + if (emin.time_since_epoch().count() != smin.time_since_epoch().count()) { + std::println(stderr, "ceil mismatch from {}", smilli); + std::println(stderr, "etl: {}", emin.time_since_epoch().count()); + std::println(stderr, "std: {}", smin.time_since_epoch().count()); + return 1; + } + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_rounding(p)); + return 0; +} diff --git a/fuzzing/src/chrono.year_month_day.fuzz.cpp b/fuzzing/src/chrono.year_month_day.fuzz.cpp new file mode 100644 index 000000000..bf676bd09 --- /dev/null +++ b/fuzzing/src/chrono.year_month_day.fuzz.cpp @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include + +[[nodiscard]] static auto fuzz_year_month_day(FuzzedDataProvider& p) -> int +{ + auto const y = p.ConsumeIntegral(); + auto const m = p.ConsumeIntegralInRange(0U, 255U); + auto const d = p.ConsumeIntegralInRange(0U, 255U); + + auto const eymd = etl::chrono::year{y} / etl::chrono::month{m} / etl::chrono::day{d}; + auto const symd = std::chrono::year{y} / std::chrono::month{m} / std::chrono::day{d}; + + if (eymd.ok() != symd.ok()) { + std::println(stderr, "etl::chrono::year_month_day::ok() = {}", eymd.ok()); + std::println(stderr, "std::chrono::year_month_day::ok() = {}", symd.ok()); + return 1; + } + + if (not eymd.ok()) { + return 0; + } + + auto const esys = static_cast(eymd); + auto const ssys = static_cast(symd); + + auto const ecount = esys.time_since_epoch().count(); + auto const scount = ssys.time_since_epoch().count(); + + if (ecount != scount) { + std::println(stderr, "etl::chrono::year_month_day::operator sys_days() = {}", ecount); + std::println(stderr, "std::chrono::year_month_day::operator sys_days() = {}", scount); + return 1; + } + + // round-trip + if (eymd != etl::chrono::year_month_day{esys}) { + std::println(stderr, "std::chrono::year_month_day(sys_days) = {}", ecount); + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_year_month_day(p)); + return 0; +} From 3e132d14be8f76e33c4c92d9233715f23c8fc30f Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Fri, 3 Oct 2025 20:22:51 +0200 Subject: [PATCH 33/39] [fuzzing] Cleanup uniform_int_distribution --- .../random.uniform_int_distribution.fuzz.cpp | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/fuzzing/src/random.uniform_int_distribution.fuzz.cpp b/fuzzing/src/random.uniform_int_distribution.fuzz.cpp index 710d58d3e..909538a15 100644 --- a/fuzzing/src/random.uniform_int_distribution.fuzz.cpp +++ b/fuzzing/src/random.uniform_int_distribution.fuzz.cpp @@ -3,32 +3,40 @@ #include "fuzzing.hpp" +#include +#include #include -#include +#include #include +#include template [[nodiscard]] static auto fuzz_uniform_int_distribution(FuzzedDataProvider& p) -> int { - static constexpr auto min = etl::numeric_limits::lowest(); + static constexpr auto min = etl::numeric_limits::min(); static constexpr auto max = etl::numeric_limits::max(); auto const distMin = p.ConsumeIntegralInRange(min, max); - if (distMin == max) { + auto const distMax = p.ConsumeIntegralInRange(distMin, max); + if (distMin == distMax) { return 0; } - auto const distMax = p.ConsumeIntegralInRange(distMin, max); - if (distMin == distMax) { + auto const seed = p.ConsumeIntegral(); + if (seed == 0) { return 0; } - auto urng = etl::xoshiro128plusplus{p.ConsumeIntegral()}; + auto urng = etl::xoshiro128plusplus{seed}; auto dist = etl::uniform_int_distribution{distMin, distMax}; auto const val = dist(urng); - return (val < distMin or val > distMax) ? 1 : 0; + if (std::cmp_less(val, distMin) or std::cmp_greater(val, distMax)) { + std::println(stderr, "dist = uniform_int_distribution({}, {}) = {}", distMin, distMax, val); + return 1; + } + return 0; } extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int @@ -40,12 +48,12 @@ extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t siz auto p = FuzzedDataProvider{data, size}; RUN(fuzz_uniform_int_distribution(p)); - RUN(fuzz_uniform_int_distribution(p)); + // RUN(fuzz_uniform_int_distribution(p)); // RUN(fuzz_uniform_int_distribution(p)); // RUN(fuzz_uniform_int_distribution(p)); - RUN(fuzz_uniform_int_distribution(p)); - RUN(fuzz_uniform_int_distribution(p)); + // RUN(fuzz_uniform_int_distribution(p)); + // RUN(fuzz_uniform_int_distribution(p)); // RUN(fuzz_uniform_int_distribution(p)); // RUN(fuzz_uniform_int_distribution(p)); From 96698dd85020bbff90054bfb0482771d142f0c99 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Fri, 3 Oct 2025 20:39:04 +0200 Subject: [PATCH 34/39] [fuzzing] Cleanup LLVMFuzzerTestOneInput entry point --- fuzzing/src/algorithm.adjacent_find.fuzz.cpp | 2 +- fuzzing/src/algorithm.binary_search.fuzz.cpp | 2 +- fuzzing/src/algorithm.equal.fuzz.cpp | 2 +- fuzzing/src/algorithm.equal_range.fuzz.cpp | 2 +- fuzzing/src/algorithm.is_partitioned.fuzz.cpp | 2 +- fuzzing/src/algorithm.is_permutation.fuzz.cpp | 2 +- fuzzing/src/algorithm.lexicographical_compare.fuzz.cpp | 2 +- fuzzing/src/algorithm.max_element.fuzz.cpp | 2 +- fuzzing/src/algorithm.min_element.fuzz.cpp | 2 +- fuzzing/src/algorithm.minmax_element.fuzz.cpp | 2 +- fuzzing/src/algorithm.mismatch.fuzz.cpp | 2 +- fuzzing/src/algorithm.nth_element.fuzz.cpp | 2 +- fuzzing/src/algorithm.partition.fuzz.cpp | 2 +- fuzzing/src/algorithm.reverse.fuzz.cpp | 2 +- fuzzing/src/algorithm.search.fuzz.cpp | 2 +- fuzzing/src/algorithm.set_difference.fuzz.cpp | 2 +- fuzzing/src/algorithm.set_intersection.fuzz.cpp | 2 +- fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp | 2 +- fuzzing/src/algorithm.set_union.fuzz.cpp | 2 +- fuzzing/src/algorithm.shift_left.fuzz.cpp | 2 +- fuzzing/src/algorithm.shift_right.fuzz.cpp | 2 +- fuzzing/src/bit.bit_ceil.fuzz.cpp | 2 +- fuzzing/src/bit.bit_floor.fuzz.cpp | 2 +- fuzzing/src/bit.bit_width.fuzz.cpp | 2 +- fuzzing/src/bit.byteswap.fuzz.cpp | 2 +- fuzzing/src/bit.countl_one.fuzz.cpp | 2 +- fuzzing/src/bit.countl_zero.fuzz.cpp | 2 +- fuzzing/src/bit.countr_one.fuzz.cpp | 2 +- fuzzing/src/bit.countr_zero.fuzz.cpp | 2 +- fuzzing/src/bit.has_single_bit.fuzz.cpp | 2 +- fuzzing/src/bit.popcount.fuzz.cpp | 2 +- fuzzing/src/cctype.fuzz.cpp | 2 +- fuzzing/src/chrono.duration.fuzz.cpp | 2 +- fuzzing/src/chrono.rounding.fuzz.cpp | 2 +- fuzzing/src/chrono.year_month_day.fuzz.cpp | 2 +- fuzzing/src/cmath.lerp.fuzz.cpp | 2 +- fuzzing/src/numeric.midpoint.fuzz.cpp | 2 +- fuzzing/src/random.uniform_int_distribution.fuzz.cpp | 2 +- fuzzing/src/random.uniform_real_distribution.fuzz.cpp | 2 +- fuzzing/src/string.fuzz.cpp | 2 +- 40 files changed, 40 insertions(+), 40 deletions(-) diff --git a/fuzzing/src/algorithm.adjacent_find.fuzz.cpp b/fuzzing/src/algorithm.adjacent_find.fuzz.cpp index 029067deb..60545f4a2 100644 --- a/fuzzing/src/algorithm.adjacent_find.fuzz.cpp +++ b/fuzzing/src/algorithm.adjacent_find.fuzz.cpp @@ -22,7 +22,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_adjacent_find(p)); diff --git a/fuzzing/src/algorithm.binary_search.fuzz.cpp b/fuzzing/src/algorithm.binary_search.fuzz.cpp index 4a9b9bdf8..207849414 100644 --- a/fuzzing/src/algorithm.binary_search.fuzz.cpp +++ b/fuzzing/src/algorithm.binary_search.fuzz.cpp @@ -23,7 +23,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_binary_search(p)); diff --git a/fuzzing/src/algorithm.equal.fuzz.cpp b/fuzzing/src/algorithm.equal.fuzz.cpp index 7aff5c621..64cb2416e 100644 --- a/fuzzing/src/algorithm.equal.fuzz.cpp +++ b/fuzzing/src/algorithm.equal.fuzz.cpp @@ -31,7 +31,7 @@ template return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_equal(p)); diff --git a/fuzzing/src/algorithm.equal_range.fuzz.cpp b/fuzzing/src/algorithm.equal_range.fuzz.cpp index 938c6eab6..34d5984af 100644 --- a/fuzzing/src/algorithm.equal_range.fuzz.cpp +++ b/fuzzing/src/algorithm.equal_range.fuzz.cpp @@ -23,7 +23,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_equal_range(p)); diff --git a/fuzzing/src/algorithm.is_partitioned.fuzz.cpp b/fuzzing/src/algorithm.is_partitioned.fuzz.cpp index 018a66408..2c378c581 100644 --- a/fuzzing/src/algorithm.is_partitioned.fuzz.cpp +++ b/fuzzing/src/algorithm.is_partitioned.fuzz.cpp @@ -29,7 +29,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_reverse(p)); diff --git a/fuzzing/src/algorithm.is_permutation.fuzz.cpp b/fuzzing/src/algorithm.is_permutation.fuzz.cpp index 60f351bad..a13388891 100644 --- a/fuzzing/src/algorithm.is_permutation.fuzz.cpp +++ b/fuzzing/src/algorithm.is_permutation.fuzz.cpp @@ -25,7 +25,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_is_permutation(p)); diff --git a/fuzzing/src/algorithm.lexicographical_compare.fuzz.cpp b/fuzzing/src/algorithm.lexicographical_compare.fuzz.cpp index 7163641b9..719542747 100644 --- a/fuzzing/src/algorithm.lexicographical_compare.fuzz.cpp +++ b/fuzzing/src/algorithm.lexicographical_compare.fuzz.cpp @@ -25,7 +25,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_lexicographical_compare(p)); diff --git a/fuzzing/src/algorithm.max_element.fuzz.cpp b/fuzzing/src/algorithm.max_element.fuzz.cpp index fb8db3c39..5d52b8381 100644 --- a/fuzzing/src/algorithm.max_element.fuzz.cpp +++ b/fuzzing/src/algorithm.max_element.fuzz.cpp @@ -22,7 +22,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_max_element(p)); diff --git a/fuzzing/src/algorithm.min_element.fuzz.cpp b/fuzzing/src/algorithm.min_element.fuzz.cpp index 9f4abfdf6..cb61667b3 100644 --- a/fuzzing/src/algorithm.min_element.fuzz.cpp +++ b/fuzzing/src/algorithm.min_element.fuzz.cpp @@ -22,7 +22,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_min_element(p)); diff --git a/fuzzing/src/algorithm.minmax_element.fuzz.cpp b/fuzzing/src/algorithm.minmax_element.fuzz.cpp index 6a6d17373..c5a5002c8 100644 --- a/fuzzing/src/algorithm.minmax_element.fuzz.cpp +++ b/fuzzing/src/algorithm.minmax_element.fuzz.cpp @@ -22,7 +22,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_minmax_element(p)); diff --git a/fuzzing/src/algorithm.mismatch.fuzz.cpp b/fuzzing/src/algorithm.mismatch.fuzz.cpp index 8e424b5e6..2ce4f35b4 100644 --- a/fuzzing/src/algorithm.mismatch.fuzz.cpp +++ b/fuzzing/src/algorithm.mismatch.fuzz.cpp @@ -26,7 +26,7 @@ template return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_mismatch(p)); diff --git a/fuzzing/src/algorithm.nth_element.fuzz.cpp b/fuzzing/src/algorithm.nth_element.fuzz.cpp index 00cc5da56..b90245edc 100644 --- a/fuzzing/src/algorithm.nth_element.fuzz.cpp +++ b/fuzzing/src/algorithm.nth_element.fuzz.cpp @@ -66,7 +66,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_nth_element(p)); diff --git a/fuzzing/src/algorithm.partition.fuzz.cpp b/fuzzing/src/algorithm.partition.fuzz.cpp index 7887a55ab..a6211bfa9 100644 --- a/fuzzing/src/algorithm.partition.fuzz.cpp +++ b/fuzzing/src/algorithm.partition.fuzz.cpp @@ -30,7 +30,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_partition(p)); diff --git a/fuzzing/src/algorithm.reverse.fuzz.cpp b/fuzzing/src/algorithm.reverse.fuzz.cpp index f4e4101c5..2bb65a9b5 100644 --- a/fuzzing/src/algorithm.reverse.fuzz.cpp +++ b/fuzzing/src/algorithm.reverse.fuzz.cpp @@ -34,7 +34,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_reverse(p)); diff --git a/fuzzing/src/algorithm.search.fuzz.cpp b/fuzzing/src/algorithm.search.fuzz.cpp index 89f736279..e3b2e3adb 100644 --- a/fuzzing/src/algorithm.search.fuzz.cpp +++ b/fuzzing/src/algorithm.search.fuzz.cpp @@ -28,7 +28,7 @@ template return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_search(p)); diff --git a/fuzzing/src/algorithm.set_difference.fuzz.cpp b/fuzzing/src/algorithm.set_difference.fuzz.cpp index 3cec25c5a..18c258df7 100644 --- a/fuzzing/src/algorithm.set_difference.fuzz.cpp +++ b/fuzzing/src/algorithm.set_difference.fuzz.cpp @@ -34,7 +34,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_set_difference(p)); diff --git a/fuzzing/src/algorithm.set_intersection.fuzz.cpp b/fuzzing/src/algorithm.set_intersection.fuzz.cpp index b50df437b..7f67e1579 100644 --- a/fuzzing/src/algorithm.set_intersection.fuzz.cpp +++ b/fuzzing/src/algorithm.set_intersection.fuzz.cpp @@ -34,7 +34,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_set_intersection(p)); diff --git a/fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp b/fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp index 769b1a49c..1ec4af539 100644 --- a/fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp +++ b/fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp @@ -34,7 +34,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_set_symmetric_difference(p)); diff --git a/fuzzing/src/algorithm.set_union.fuzz.cpp b/fuzzing/src/algorithm.set_union.fuzz.cpp index b99ddc804..851eef5b7 100644 --- a/fuzzing/src/algorithm.set_union.fuzz.cpp +++ b/fuzzing/src/algorithm.set_union.fuzz.cpp @@ -34,7 +34,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_set_union(p)); diff --git a/fuzzing/src/algorithm.shift_left.fuzz.cpp b/fuzzing/src/algorithm.shift_left.fuzz.cpp index 4be8093cf..c4babce87 100644 --- a/fuzzing/src/algorithm.shift_left.fuzz.cpp +++ b/fuzzing/src/algorithm.shift_left.fuzz.cpp @@ -33,7 +33,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_shift_left(p)); diff --git a/fuzzing/src/algorithm.shift_right.fuzz.cpp b/fuzzing/src/algorithm.shift_right.fuzz.cpp index 6d0dca485..a5dfa0391 100644 --- a/fuzzing/src/algorithm.shift_right.fuzz.cpp +++ b/fuzzing/src/algorithm.shift_right.fuzz.cpp @@ -33,7 +33,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_shift_right(p)); diff --git a/fuzzing/src/bit.bit_ceil.fuzz.cpp b/fuzzing/src/bit.bit_ceil.fuzz.cpp index ab7f1cb6b..2eb0c3e3d 100644 --- a/fuzzing/src/bit.bit_ceil.fuzz.cpp +++ b/fuzzing/src/bit.bit_ceil.fuzz.cpp @@ -16,7 +16,7 @@ template return (e != s) ? 1 : 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_bit_ceil(p)); diff --git a/fuzzing/src/bit.bit_floor.fuzz.cpp b/fuzzing/src/bit.bit_floor.fuzz.cpp index ee95c55e1..3ebfb3a63 100644 --- a/fuzzing/src/bit.bit_floor.fuzz.cpp +++ b/fuzzing/src/bit.bit_floor.fuzz.cpp @@ -16,7 +16,7 @@ template return (e != s) ? 1 : 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_bit_floor(p)); diff --git a/fuzzing/src/bit.bit_width.fuzz.cpp b/fuzzing/src/bit.bit_width.fuzz.cpp index 6b0350d79..d7256521b 100644 --- a/fuzzing/src/bit.bit_width.fuzz.cpp +++ b/fuzzing/src/bit.bit_width.fuzz.cpp @@ -16,7 +16,7 @@ template return (e != s) ? 1 : 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_bit_width(p)); diff --git a/fuzzing/src/bit.byteswap.fuzz.cpp b/fuzzing/src/bit.byteswap.fuzz.cpp index 12be83155..b098a9cc8 100644 --- a/fuzzing/src/bit.byteswap.fuzz.cpp +++ b/fuzzing/src/bit.byteswap.fuzz.cpp @@ -18,7 +18,7 @@ template return (e != s or f != s) ? 1 : 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_byteswap(p)); diff --git a/fuzzing/src/bit.countl_one.fuzz.cpp b/fuzzing/src/bit.countl_one.fuzz.cpp index eb467533d..732d80da5 100644 --- a/fuzzing/src/bit.countl_one.fuzz.cpp +++ b/fuzzing/src/bit.countl_one.fuzz.cpp @@ -16,7 +16,7 @@ template return (e != s) ? 1 : 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_countl_one(p)); diff --git a/fuzzing/src/bit.countl_zero.fuzz.cpp b/fuzzing/src/bit.countl_zero.fuzz.cpp index 5eb9fe88b..74bda2fc9 100644 --- a/fuzzing/src/bit.countl_zero.fuzz.cpp +++ b/fuzzing/src/bit.countl_zero.fuzz.cpp @@ -16,7 +16,7 @@ template return (e != s) ? 1 : 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_countl_zero(p)); diff --git a/fuzzing/src/bit.countr_one.fuzz.cpp b/fuzzing/src/bit.countr_one.fuzz.cpp index ecf76ac5f..a8d40d06f 100644 --- a/fuzzing/src/bit.countr_one.fuzz.cpp +++ b/fuzzing/src/bit.countr_one.fuzz.cpp @@ -16,7 +16,7 @@ template return (e != s) ? 1 : 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_countr_one(p)); diff --git a/fuzzing/src/bit.countr_zero.fuzz.cpp b/fuzzing/src/bit.countr_zero.fuzz.cpp index 5767073b9..ea39de699 100644 --- a/fuzzing/src/bit.countr_zero.fuzz.cpp +++ b/fuzzing/src/bit.countr_zero.fuzz.cpp @@ -16,7 +16,7 @@ template return (e != s) ? 1 : 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_countr_zero(p)); diff --git a/fuzzing/src/bit.has_single_bit.fuzz.cpp b/fuzzing/src/bit.has_single_bit.fuzz.cpp index 5b500590f..befa559c2 100644 --- a/fuzzing/src/bit.has_single_bit.fuzz.cpp +++ b/fuzzing/src/bit.has_single_bit.fuzz.cpp @@ -17,7 +17,7 @@ template return (e != s) ? 1 : 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_has_single_bit(p)); diff --git a/fuzzing/src/bit.popcount.fuzz.cpp b/fuzzing/src/bit.popcount.fuzz.cpp index bd126c0f8..06cd82858 100644 --- a/fuzzing/src/bit.popcount.fuzz.cpp +++ b/fuzzing/src/bit.popcount.fuzz.cpp @@ -18,7 +18,7 @@ template return (e != s or f != s) ? 1 : 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_popcount(p)); diff --git a/fuzzing/src/cctype.fuzz.cpp b/fuzzing/src/cctype.fuzz.cpp index 0180046c0..b936efd84 100644 --- a/fuzzing/src/cctype.fuzz.cpp +++ b/fuzzing/src/cctype.fuzz.cpp @@ -155,7 +155,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_isalpha(p)); diff --git a/fuzzing/src/chrono.duration.fuzz.cpp b/fuzzing/src/chrono.duration.fuzz.cpp index 6452e7c2c..5ceaed568 100644 --- a/fuzzing/src/chrono.duration.fuzz.cpp +++ b/fuzzing/src/chrono.duration.fuzz.cpp @@ -102,7 +102,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_duration(p)); diff --git a/fuzzing/src/chrono.rounding.fuzz.cpp b/fuzzing/src/chrono.rounding.fuzz.cpp index 344205047..e7c310485 100644 --- a/fuzzing/src/chrono.rounding.fuzz.cpp +++ b/fuzzing/src/chrono.rounding.fuzz.cpp @@ -54,7 +54,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_rounding(p)); diff --git a/fuzzing/src/chrono.year_month_day.fuzz.cpp b/fuzzing/src/chrono.year_month_day.fuzz.cpp index bf676bd09..5c993c73d 100644 --- a/fuzzing/src/chrono.year_month_day.fuzz.cpp +++ b/fuzzing/src/chrono.year_month_day.fuzz.cpp @@ -48,7 +48,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; RUN(fuzz_year_month_day(p)); diff --git a/fuzzing/src/cmath.lerp.fuzz.cpp b/fuzzing/src/cmath.lerp.fuzz.cpp index c2ab78fd5..253c9ea0f 100644 --- a/fuzzing/src/cmath.lerp.fuzz.cpp +++ b/fuzzing/src/cmath.lerp.fuzz.cpp @@ -50,7 +50,7 @@ template return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { if (size == 0) { return 0; diff --git a/fuzzing/src/numeric.midpoint.fuzz.cpp b/fuzzing/src/numeric.midpoint.fuzz.cpp index ba86b8420..aa34670bf 100644 --- a/fuzzing/src/numeric.midpoint.fuzz.cpp +++ b/fuzzing/src/numeric.midpoint.fuzz.cpp @@ -27,7 +27,7 @@ template return s != e ? 1 : 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { auto p = FuzzedDataProvider{data, size}; diff --git a/fuzzing/src/random.uniform_int_distribution.fuzz.cpp b/fuzzing/src/random.uniform_int_distribution.fuzz.cpp index 909538a15..9d54c8350 100644 --- a/fuzzing/src/random.uniform_int_distribution.fuzz.cpp +++ b/fuzzing/src/random.uniform_int_distribution.fuzz.cpp @@ -39,7 +39,7 @@ template return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { if (size == 0) { return 0; diff --git a/fuzzing/src/random.uniform_real_distribution.fuzz.cpp b/fuzzing/src/random.uniform_real_distribution.fuzz.cpp index 531f52882..323670767 100644 --- a/fuzzing/src/random.uniform_real_distribution.fuzz.cpp +++ b/fuzzing/src/random.uniform_real_distribution.fuzz.cpp @@ -29,7 +29,7 @@ template return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { if (size == 0) { return 0; diff --git a/fuzzing/src/string.fuzz.cpp b/fuzzing/src/string.fuzz.cpp index 0e0e241f8..09ac91356 100644 --- a/fuzzing/src/string.fuzz.cpp +++ b/fuzzing/src/string.fuzz.cpp @@ -29,7 +29,7 @@ return 0; } -extern "C" auto LLVMFuzzerTestOneInput(etl::uint8_t const* data, etl::size_t size) -> int +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int { if (size == 0) { return 0; From 2338172ae0ca21b9cbac6246bce701ab3d04e532 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Fri, 3 Oct 2025 23:28:04 +0200 Subject: [PATCH 35/39] [fuzzing] Add cstring tests --- fuzzing/CMakeLists.txt | 4 +++ fuzzing/src/cstring.strcmp.fuzz.cpp | 48 +++++++++++++++++++++++++ fuzzing/src/cstring.strlen.fuzz.cpp | 35 ++++++++++++++++++ fuzzing/src/cstring.strncmp.fuzz.cpp | 49 +++++++++++++++++++++++++ fuzzing/src/cstring.strstr.fuzz.cpp | 43 ++++++++++++++++++++++ include/etl/_cstring/strcmp.hpp | 2 +- include/etl/_cstring/strncmp.hpp | 2 +- include/etl/_cstring/strstr.hpp | 4 +-- include/etl/_cwchar/wcsstr.hpp | 4 +-- include/etl/_strings/cstr.hpp | 53 +++++++++++++++------------- 10 files changed, 214 insertions(+), 30 deletions(-) create mode 100644 fuzzing/src/cstring.strcmp.fuzz.cpp create mode 100644 fuzzing/src/cstring.strlen.fuzz.cpp create mode 100644 fuzzing/src/cstring.strncmp.fuzz.cpp create mode 100644 fuzzing/src/cstring.strstr.fuzz.cpp diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt index 5fa83d883..ec1019e27 100644 --- a/fuzzing/CMakeLists.txt +++ b/fuzzing/CMakeLists.txt @@ -89,6 +89,10 @@ tetl_add_fuzz_test("chrono.duration") tetl_add_fuzz_test("chrono.rounding") tetl_add_fuzz_test("chrono.year_month_day") tetl_add_fuzz_test("cmath.lerp") +tetl_add_fuzz_test("cstring.strcmp") +tetl_add_fuzz_test("cstring.strlen") +tetl_add_fuzz_test("cstring.strncmp") +tetl_add_fuzz_test("cstring.strstr") tetl_add_fuzz_test("numeric.midpoint") tetl_add_fuzz_test("random.uniform_int_distribution") tetl_add_fuzz_test("random.uniform_real_distribution") diff --git a/fuzzing/src/cstring.strcmp.fuzz.cpp b/fuzzing/src/cstring.strcmp.fuzz.cpp new file mode 100644 index 000000000..a47598630 --- /dev/null +++ b/fuzzing/src/cstring.strcmp.fuzz.cpp @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include +#include + +[[nodiscard]] static constexpr auto sign(int x) -> int +{ + if (x > 0) { + return 1; + } + if (x < 0) { + return -1; + } + return 0; +} + +[[nodiscard]] static auto fuzz_strcmp(FuzzedDataProvider& p) -> int +{ + auto const lhs = p.ConsumeRandomLengthString(64); + auto const rhs = p.ConsumeRandomLengthString(64); + + auto const s = std::strcmp(lhs.c_str(), rhs.c_str()); + auto const e = etl::strcmp(lhs.c_str(), rhs.c_str()); + auto const ef = etl::detail::strcmp(lhs.c_str(), rhs.c_str()); + + if ((sign(e) != sign(s)) or (sign(ef) != sign(s))) { + std::println(stderr, "strcmp('{}', '{}')", lhs, rhs); + std::println(stderr, "std = {}", s); + std::println(stderr, "etl = {}", e); + std::println(stderr, "etl::detail = {}", ef); + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_strcmp(p)); + return 0; +} diff --git a/fuzzing/src/cstring.strlen.fuzz.cpp b/fuzzing/src/cstring.strlen.fuzz.cpp new file mode 100644 index 000000000..bfac0a7e3 --- /dev/null +++ b/fuzzing/src/cstring.strlen.fuzz.cpp @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include + +[[nodiscard]] static auto fuzz_strlen(FuzzedDataProvider& p) -> int +{ + auto const str = p.ConsumeRandomLengthString(64); + + auto const s = std::strlen(str.c_str()); + auto const e = etl::strlen(str.c_str()); + auto const ef = etl::detail::strlen(str.c_str()); + + if ((e != s) or (ef != s)) { + std::println(stderr, "strlen(\"{}\")", str); + std::println(stderr, "std = {}", s); + std::println(stderr, "etl = {}", e); + std::println(stderr, "etl::detail = {}", ef); + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_strlen(p)); + return 0; +} diff --git a/fuzzing/src/cstring.strncmp.fuzz.cpp b/fuzzing/src/cstring.strncmp.fuzz.cpp new file mode 100644 index 000000000..918795b0a --- /dev/null +++ b/fuzzing/src/cstring.strncmp.fuzz.cpp @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include +#include + +[[nodiscard]] static constexpr auto sign(int x) -> int +{ + if (x > 0) { + return 1; + } + if (x < 0) { + return -1; + } + return 0; +} + +[[nodiscard]] static auto fuzz_strncmp(FuzzedDataProvider& p) -> int +{ + auto const lhs = p.ConsumeRandomLengthString(64); + auto const rhs = p.ConsumeRandomLengthString(64); + auto const count = std::min(lhs.size(), rhs.size()); + + auto const s = std::strncmp(lhs.c_str(), rhs.c_str(), count); + auto const e = etl::strncmp(lhs.c_str(), rhs.c_str(), count); + auto const ef = etl::detail::strncmp(lhs.c_str(), rhs.c_str(), count); + + if ((sign(e) != sign(s)) or (sign(ef) != sign(s))) { + std::println(stderr, "strncmp('{}', '{}')", lhs, rhs); + std::println(stderr, "std = {}", s); + std::println(stderr, "etl = {}", e); + std::println(stderr, "etl::detail = {}", ef); + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_strncmp(p)); + return 0; +} diff --git a/fuzzing/src/cstring.strstr.fuzz.cpp b/fuzzing/src/cstring.strstr.fuzz.cpp new file mode 100644 index 000000000..2510ec98e --- /dev/null +++ b/fuzzing/src/cstring.strstr.fuzz.cpp @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: BSL-1.0 +// SPDX-FileCopyrightText: Copyright (C) 2025 Tobias Hienzsch + +#include "fuzzing.hpp" + +#include + +#include +#include +#include + +[[nodiscard]] static auto fuzz_strstr(FuzzedDataProvider& p) -> int +{ + auto const haystack = p.ConsumeRandomLengthString(64); + auto const needle = p.ConsumeRandomLengthString(64); + + auto const s = std::strstr(haystack.c_str(), needle.c_str()); + auto const e = etl::strstr(haystack.c_str(), needle.c_str()); + auto const ef = etl::detail::strstr(haystack.c_str(), needle.c_str()); + + if ((e != s) or (ef != s)) { + std::println(stderr, "strstr('{}', '{}')", haystack, needle); + if (s == nullptr) { + std::println(stderr, "std = {}", s == nullptr); + std::println(stderr, "etl = {}", e == nullptr); + std::println(stderr, "etl::detail = {}", ef == nullptr); + } else { + std::println(stderr, "std = {}", s - haystack.c_str()); + std::println(stderr, "etl = {}", e - haystack.c_str()); + std::println(stderr, "etl::detail = {}", ef - haystack.c_str()); + } + return 1; + } + + return 0; +} + +extern "C" auto LLVMFuzzerTestOneInput(std::uint8_t const* data, std::size_t size) -> int +{ + auto p = FuzzedDataProvider{data, size}; + RUN(fuzz_strstr(p)); + return 0; +} diff --git a/include/etl/_cstring/strcmp.hpp b/include/etl/_cstring/strcmp.hpp index 9f1f9cd9d..bfca41c61 100644 --- a/include/etl/_cstring/strcmp.hpp +++ b/include/etl/_cstring/strcmp.hpp @@ -23,7 +23,7 @@ namespace etl { #if __has_builtin(__builtin_strcmp) return __builtin_strcmp(lhs, rhs); #else - return etl::detail::strcmp(lhs, rhs); + return etl::detail::strcmp(lhs, rhs); #endif } diff --git a/include/etl/_cstring/strncmp.hpp b/include/etl/_cstring/strncmp.hpp index 6656e7809..50d646d17 100644 --- a/include/etl/_cstring/strncmp.hpp +++ b/include/etl/_cstring/strncmp.hpp @@ -25,7 +25,7 @@ namespace etl { #if __has_builtin(__builtin_strncmp) return __builtin_strncmp(lhs, rhs, count); #else - return etl::detail::strncmp(lhs, rhs, count); + return etl::detail::strncmp(lhs, rhs, count); #endif } diff --git a/include/etl/_cstring/strstr.hpp b/include/etl/_cstring/strstr.hpp index 7cf5ffdf5..e0df58027 100644 --- a/include/etl/_cstring/strstr.hpp +++ b/include/etl/_cstring/strstr.hpp @@ -17,12 +17,12 @@ namespace etl { /// \ingroup cstring [[nodiscard]] constexpr auto strstr(char* haystack, char* needle) noexcept -> char* { - return etl::detail::strstr_impl(haystack, needle); + return etl::detail::strstr(haystack, needle); } [[nodiscard]] constexpr auto strstr(char const* haystack, char const* needle) noexcept -> char const* { - return etl::detail::strstr_impl(haystack, needle); + return etl::detail::strstr(haystack, needle); } /// @} diff --git a/include/etl/_cwchar/wcsstr.hpp b/include/etl/_cwchar/wcsstr.hpp index 58645da3f..b4dfacfbc 100644 --- a/include/etl/_cwchar/wcsstr.hpp +++ b/include/etl/_cwchar/wcsstr.hpp @@ -15,7 +15,7 @@ namespace etl { /// https://en.cppreference.com/w/cpp/string/wide/wcspbrk [[nodiscard]] constexpr auto wcsstr(wchar_t* haystack, wchar_t* needle) noexcept -> wchar_t* { - return etl::detail::strstr_impl(haystack, needle); + return etl::detail::strstr(haystack, needle); } /// \brief Finds the first occurrence of the wide string needle in the wide @@ -25,7 +25,7 @@ namespace etl { /// https://en.cppreference.com/w/cpp/string/wide/wcspbrk [[nodiscard]] constexpr auto wcsstr(wchar_t const* haystack, wchar_t const* needle) noexcept -> wchar_t const* { - return etl::detail::strstr_impl(haystack, needle); + return etl::detail::strstr(haystack, needle); } } // namespace etl #endif // TETL_CWCHAR_WCSSTR_HPP diff --git a/include/etl/_strings/cstr.hpp b/include/etl/_strings/cstr.hpp index 1e7cc3c6f..d37b2b125 100644 --- a/include/etl/_strings/cstr.hpp +++ b/include/etl/_strings/cstr.hpp @@ -61,32 +61,25 @@ template return dest; } -template +template [[nodiscard]] constexpr auto strcmp(CharT const* lhs, CharT const* rhs) -> int { - for (; *lhs != CharT(0); ++lhs, ++rhs) { - if (*lhs != *rhs) { - break; - } + while (*lhs and (*lhs == *rhs)) { + lhs++; + rhs++; } - return static_cast(*lhs) - static_cast(*rhs); + return static_cast(static_cast(*lhs) - static_cast(*rhs)); } -template +template [[nodiscard]] constexpr auto strncmp(CharT const* lhs, CharT const* rhs, SizeT const count) -> int { - CharT u1{}; - CharT u2{}; - - auto localCount = count; - while (localCount-- > 0) { - u1 = static_cast(*lhs++); - u2 = static_cast(*rhs++); - if (u1 != u2) { - return static_cast(u1 - u2); - } - if (u1 == CharT(0)) { - return 0; + for (auto i = SizeT(0); i < count; ++i) { + auto const l = static_cast(*lhs++); + auto const r = static_cast(*rhs++); + auto const diff = static_cast(l - r); + if (l == CharT(0) or diff != 0) { + return diff; } } @@ -170,14 +163,26 @@ template } template -[[nodiscard]] constexpr auto strstr_impl(CharT* haystack, CharT* needle) noexcept -> CharT* +[[nodiscard]] constexpr auto strstr(CharT* haystack, CharT* needle) noexcept -> CharT* { - while (*haystack != CharT(0)) { - if ((*haystack == *needle) and (strcmp(haystack, needle) == 0)) { - return haystack; + if (not *needle) { + return haystack; + } + + for (auto const* h = haystack; *h; h++) { + auto const* hIt = h; + auto const* nIt = needle; + + while (*hIt and *nIt and *hIt == *nIt) { + hIt++; + nIt++; + } + + if (not *nIt) { // reached end of needle, found match + return haystack + (h - haystack); } - haystack++; } + return nullptr; } From a7c366318548256259dff7cc89cb38ef12d6ad29 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Sat, 4 Oct 2025 10:16:12 +0200 Subject: [PATCH 36/39] [fuzzing] Increase input lengths --- fuzzing/src/algorithm.equal.fuzz.cpp | 4 ++-- fuzzing/src/algorithm.is_partitioned.fuzz.cpp | 2 +- .../algorithm.lexicographical_compare.fuzz.cpp | 10 +++++----- fuzzing/src/algorithm.mismatch.fuzz.cpp | 12 ++++-------- fuzzing/src/algorithm.reverse.fuzz.cpp | 2 +- fuzzing/src/algorithm.search.fuzz.cpp | 18 ++++++++---------- fuzzing/src/algorithm.set_difference.fuzz.cpp | 4 ++-- .../src/algorithm.set_intersection.fuzz.cpp | 4 ++-- ...algorithm.set_symmetric_difference.fuzz.cpp | 4 ++-- fuzzing/src/algorithm.set_union.fuzz.cpp | 4 ++-- fuzzing/src/charconv.from_chars.fuzz.cpp | 2 +- fuzzing/src/cstring.strcmp.fuzz.cpp | 4 ++-- fuzzing/src/cstring.strlen.fuzz.cpp | 2 +- fuzzing/src/cstring.strncmp.fuzz.cpp | 4 ++-- fuzzing/src/cstring.strstr.fuzz.cpp | 4 ++-- fuzzing/src/string_view.contains.fuzz.cpp | 4 ++-- fuzzing/src/string_view.ends_with.fuzz.cpp | 4 ++-- fuzzing/src/string_view.find.fuzz.cpp | 4 ++-- .../src/string_view.find_first_not_of.fuzz.cpp | 4 ++-- fuzzing/src/string_view.find_first_of.fuzz.cpp | 4 ++-- .../src/string_view.find_last_not_of.fuzz.cpp | 4 ++-- fuzzing/src/string_view.find_last_of.fuzz.cpp | 4 ++-- fuzzing/src/string_view.rfind.fuzz.cpp | 4 ++-- fuzzing/src/string_view.starts_with.fuzz.cpp | 4 ++-- 24 files changed, 55 insertions(+), 61 deletions(-) diff --git a/fuzzing/src/algorithm.equal.fuzz.cpp b/fuzzing/src/algorithm.equal.fuzz.cpp index 64cb2416e..afca0f507 100644 --- a/fuzzing/src/algorithm.equal.fuzz.cpp +++ b/fuzzing/src/algorithm.equal.fuzz.cpp @@ -12,8 +12,8 @@ template [[nodiscard]] static auto fuzz_equal(FuzzedDataProvider& p) -> int { - auto const a = p.ConsumeRandomLengthString(64); - auto const b = p.ConsumeRandomLengthString(64); + auto const a = p.ConsumeRandomLengthString(); + auto const b = p.ConsumeRandomLengthString(); auto const av = etl::string_view{a.data(), a.size()}; auto const bv = etl::string_view{b.data(), b.size()}; diff --git a/fuzzing/src/algorithm.is_partitioned.fuzz.cpp b/fuzzing/src/algorithm.is_partitioned.fuzz.cpp index 2c378c581..e4b57c4ed 100644 --- a/fuzzing/src/algorithm.is_partitioned.fuzz.cpp +++ b/fuzzing/src/algorithm.is_partitioned.fuzz.cpp @@ -13,7 +13,7 @@ [[nodiscard]] static auto fuzz_reverse(FuzzedDataProvider& p) -> int { - auto const str = p.ConsumeRandomLengthString(32); + auto const str = p.ConsumeRandomLengthString(); auto const view = etl::string_view{str.data(), str.size()}; auto const e = etl::is_partitioned(view.begin(), view.end(), [](char c) { return c < 'a'; }); diff --git a/fuzzing/src/algorithm.lexicographical_compare.fuzz.cpp b/fuzzing/src/algorithm.lexicographical_compare.fuzz.cpp index 719542747..8561ddad0 100644 --- a/fuzzing/src/algorithm.lexicographical_compare.fuzz.cpp +++ b/fuzzing/src/algorithm.lexicographical_compare.fuzz.cpp @@ -4,17 +4,17 @@ #include "fuzzing.hpp" #include -#include +#include #include [[nodiscard]] static auto fuzz_lexicographical_compare(FuzzedDataProvider& p) -> int { - auto const a = p.ConsumeBytes(64); - auto const b = p.ConsumeBytes(64); + auto const a = p.ConsumeRandomLengthString(); + auto const b = p.ConsumeRandomLengthString(); - auto const va = etl::span{a.data(), a.size()}; - auto const vb = etl::span{b.data(), b.size()}; + auto const va = etl::string_view{a.data(), a.size()}; + auto const vb = etl::string_view{b.data(), b.size()}; auto const e = etl::lexicographical_compare(va.begin(), va.end(), vb.begin(), vb.end()); auto const s = std::lexicographical_compare(va.begin(), va.end(), vb.begin(), vb.end()); diff --git a/fuzzing/src/algorithm.mismatch.fuzz.cpp b/fuzzing/src/algorithm.mismatch.fuzz.cpp index 2ce4f35b4..d3e9615bc 100644 --- a/fuzzing/src/algorithm.mismatch.fuzz.cpp +++ b/fuzzing/src/algorithm.mismatch.fuzz.cpp @@ -10,15 +10,11 @@ template [[nodiscard]] static auto fuzz_mismatch(FuzzedDataProvider& p) -> int { - auto generator = [&p] { return p.ConsumeIntegral(); }; - auto src = etl::static_vector{}; - etl::generate_n(etl::back_inserter(src), src.capacity(), generator); + auto const a = p.ConsumeRandomLengthString(); + auto const b = p.ConsumeRandomLengthString(); - auto objs = etl::static_vector{}; - etl::generate_n(etl::back_inserter(objs), objs.capacity(), generator); - - auto e = etl::mismatch(src.begin(), src.end(), objs.begin(), objs.end()); - auto s = std::mismatch(src.begin(), src.end(), objs.begin(), objs.end()); + auto const e = etl::mismatch(a.begin(), a.end(), b.begin(), b.end()); + auto const s = std::mismatch(a.begin(), a.end(), b.begin(), b.end()); if ((e.first != s.first) or (e.second != s.second)) { return 1; } diff --git a/fuzzing/src/algorithm.reverse.fuzz.cpp b/fuzzing/src/algorithm.reverse.fuzz.cpp index 2bb65a9b5..f504f0b94 100644 --- a/fuzzing/src/algorithm.reverse.fuzz.cpp +++ b/fuzzing/src/algorithm.reverse.fuzz.cpp @@ -13,7 +13,7 @@ [[nodiscard]] static auto fuzz_reverse(FuzzedDataProvider& p) -> int { - auto const str = p.ConsumeRandomLengthString(16); + auto const str = p.ConsumeRandomLengthString(); auto estr = str; auto sstr = str; diff --git a/fuzzing/src/algorithm.search.fuzz.cpp b/fuzzing/src/algorithm.search.fuzz.cpp index e3b2e3adb..9bcfbcaf4 100644 --- a/fuzzing/src/algorithm.search.fuzz.cpp +++ b/fuzzing/src/algorithm.search.fuzz.cpp @@ -5,22 +5,20 @@ #include #include -#include -#include +#include template [[nodiscard]] static auto fuzz_search(FuzzedDataProvider& p) -> int { - auto generator = [&p] { return p.ConsumeIntegral(); }; - auto src = etl::static_vector{}; - etl::generate_n(etl::back_inserter(src), src.capacity(), generator); + auto const haystack = p.ConsumeRandomLengthString(); + auto const needle = p.ConsumeRandomLengthString(); - auto objs = etl::static_vector{}; - etl::generate_n(etl::back_inserter(objs), objs.capacity(), generator); + auto const h = etl::span{haystack.data(), haystack.size()}; + auto const n = etl::span{needle.data(), needle.size()}; - auto const s = std::search(src.begin(), src.end(), objs.begin(), objs.end()); - auto const e = etl::search(src.begin(), src.end(), objs.begin(), objs.end()); - auto const d = etl::search(src.begin(), src.end(), etl::default_searcher(objs.begin(), objs.end())); + auto const s = std::search(h.begin(), h.end(), n.begin(), n.end()); + auto const e = etl::search(h.begin(), h.end(), n.begin(), n.end()); + auto const d = etl::search(h.begin(), h.end(), etl::default_searcher(n.begin(), n.end())); if (e != s or d != s) { return 1; } diff --git a/fuzzing/src/algorithm.set_difference.fuzz.cpp b/fuzzing/src/algorithm.set_difference.fuzz.cpp index 18c258df7..0afaa5073 100644 --- a/fuzzing/src/algorithm.set_difference.fuzz.cpp +++ b/fuzzing/src/algorithm.set_difference.fuzz.cpp @@ -13,8 +13,8 @@ [[nodiscard]] static auto fuzz_set_difference(FuzzedDataProvider& p) -> int { - auto const a = p.ConsumeRandomLengthString(16); - auto const b = p.ConsumeRandomLengthString(16); + auto const a = p.ConsumeRandomLengthString(); + auto const b = p.ConsumeRandomLengthString(); auto const aview = etl::span{a.c_str(), a.size()}; auto const bview = etl::span{b.c_str(), b.size()}; diff --git a/fuzzing/src/algorithm.set_intersection.fuzz.cpp b/fuzzing/src/algorithm.set_intersection.fuzz.cpp index 7f67e1579..211480e8a 100644 --- a/fuzzing/src/algorithm.set_intersection.fuzz.cpp +++ b/fuzzing/src/algorithm.set_intersection.fuzz.cpp @@ -13,8 +13,8 @@ [[nodiscard]] static auto fuzz_set_intersection(FuzzedDataProvider& p) -> int { - auto const a = p.ConsumeRandomLengthString(16); - auto const b = p.ConsumeRandomLengthString(16); + auto const a = p.ConsumeRandomLengthString(); + auto const b = p.ConsumeRandomLengthString(); auto const aview = etl::span{a.c_str(), a.size()}; auto const bview = etl::span{b.c_str(), b.size()}; diff --git a/fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp b/fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp index 1ec4af539..c520819f7 100644 --- a/fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp +++ b/fuzzing/src/algorithm.set_symmetric_difference.fuzz.cpp @@ -13,8 +13,8 @@ [[nodiscard]] static auto fuzz_set_symmetric_difference(FuzzedDataProvider& p) -> int { - auto const a = p.ConsumeRandomLengthString(16); - auto const b = p.ConsumeRandomLengthString(16); + auto const a = p.ConsumeRandomLengthString(); + auto const b = p.ConsumeRandomLengthString(); auto const aview = etl::span{a.c_str(), a.size()}; auto const bview = etl::span{b.c_str(), b.size()}; diff --git a/fuzzing/src/algorithm.set_union.fuzz.cpp b/fuzzing/src/algorithm.set_union.fuzz.cpp index 851eef5b7..aac8b0a8d 100644 --- a/fuzzing/src/algorithm.set_union.fuzz.cpp +++ b/fuzzing/src/algorithm.set_union.fuzz.cpp @@ -13,8 +13,8 @@ [[nodiscard]] static auto fuzz_set_union(FuzzedDataProvider& p) -> int { - auto const a = p.ConsumeRandomLengthString(16); - auto const b = p.ConsumeRandomLengthString(16); + auto const a = p.ConsumeRandomLengthString(); + auto const b = p.ConsumeRandomLengthString(); auto const aview = etl::span{a.c_str(), a.size()}; auto const bview = etl::span{b.c_str(), b.size()}; diff --git a/fuzzing/src/charconv.from_chars.fuzz.cpp b/fuzzing/src/charconv.from_chars.fuzz.cpp index 770bebf4f..f0336d704 100644 --- a/fuzzing/src/charconv.from_chars.fuzz.cpp +++ b/fuzzing/src/charconv.from_chars.fuzz.cpp @@ -19,7 +19,7 @@ template using namespace etl::fuzzing; auto const base = p.ConsumeIntegralInRange(2, 36); - auto const input = p.ConsumeRandomLengthString(11); + auto const input = p.ConsumeRandomLengthString(); auto [stdVal, stdPtr, stdEc] = [base, &input] { auto val = IntType{}; diff --git a/fuzzing/src/cstring.strcmp.fuzz.cpp b/fuzzing/src/cstring.strcmp.fuzz.cpp index a47598630..65b19c71a 100644 --- a/fuzzing/src/cstring.strcmp.fuzz.cpp +++ b/fuzzing/src/cstring.strcmp.fuzz.cpp @@ -22,8 +22,8 @@ [[nodiscard]] static auto fuzz_strcmp(FuzzedDataProvider& p) -> int { - auto const lhs = p.ConsumeRandomLengthString(64); - auto const rhs = p.ConsumeRandomLengthString(64); + auto const lhs = p.ConsumeRandomLengthString(); + auto const rhs = p.ConsumeRandomLengthString(); auto const s = std::strcmp(lhs.c_str(), rhs.c_str()); auto const e = etl::strcmp(lhs.c_str(), rhs.c_str()); diff --git a/fuzzing/src/cstring.strlen.fuzz.cpp b/fuzzing/src/cstring.strlen.fuzz.cpp index bfac0a7e3..2809d4ce0 100644 --- a/fuzzing/src/cstring.strlen.fuzz.cpp +++ b/fuzzing/src/cstring.strlen.fuzz.cpp @@ -10,7 +10,7 @@ [[nodiscard]] static auto fuzz_strlen(FuzzedDataProvider& p) -> int { - auto const str = p.ConsumeRandomLengthString(64); + auto const str = p.ConsumeRandomLengthString(); auto const s = std::strlen(str.c_str()); auto const e = etl::strlen(str.c_str()); diff --git a/fuzzing/src/cstring.strncmp.fuzz.cpp b/fuzzing/src/cstring.strncmp.fuzz.cpp index 918795b0a..3db321205 100644 --- a/fuzzing/src/cstring.strncmp.fuzz.cpp +++ b/fuzzing/src/cstring.strncmp.fuzz.cpp @@ -22,8 +22,8 @@ [[nodiscard]] static auto fuzz_strncmp(FuzzedDataProvider& p) -> int { - auto const lhs = p.ConsumeRandomLengthString(64); - auto const rhs = p.ConsumeRandomLengthString(64); + auto const lhs = p.ConsumeRandomLengthString(); + auto const rhs = p.ConsumeRandomLengthString(); auto const count = std::min(lhs.size(), rhs.size()); auto const s = std::strncmp(lhs.c_str(), rhs.c_str(), count); diff --git a/fuzzing/src/cstring.strstr.fuzz.cpp b/fuzzing/src/cstring.strstr.fuzz.cpp index 2510ec98e..4eb37895e 100644 --- a/fuzzing/src/cstring.strstr.fuzz.cpp +++ b/fuzzing/src/cstring.strstr.fuzz.cpp @@ -11,8 +11,8 @@ [[nodiscard]] static auto fuzz_strstr(FuzzedDataProvider& p) -> int { - auto const haystack = p.ConsumeRandomLengthString(64); - auto const needle = p.ConsumeRandomLengthString(64); + auto const haystack = p.ConsumeRandomLengthString(); + auto const needle = p.ConsumeRandomLengthString(); auto const s = std::strstr(haystack.c_str(), needle.c_str()); auto const e = etl::strstr(haystack.c_str(), needle.c_str()); diff --git a/fuzzing/src/string_view.contains.fuzz.cpp b/fuzzing/src/string_view.contains.fuzz.cpp index 20e53baa5..1418e4a82 100644 --- a/fuzzing/src/string_view.contains.fuzz.cpp +++ b/fuzzing/src/string_view.contains.fuzz.cpp @@ -10,8 +10,8 @@ static auto fuzz_string_view_contains(FuzzedDataProvider& p) -> int { - auto const haystack = p.ConsumeRandomLengthString(64); - auto const needle = p.ConsumeRandomLengthString(64); + auto const haystack = p.ConsumeRandomLengthString(); + auto const needle = p.ConsumeRandomLengthString(); auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; diff --git a/fuzzing/src/string_view.ends_with.fuzz.cpp b/fuzzing/src/string_view.ends_with.fuzz.cpp index 6c99aa8cc..e2bfc2d6a 100644 --- a/fuzzing/src/string_view.ends_with.fuzz.cpp +++ b/fuzzing/src/string_view.ends_with.fuzz.cpp @@ -10,8 +10,8 @@ static auto fuzz_string_view_ends_with(FuzzedDataProvider& p) -> int { - auto const haystack = p.ConsumeRandomLengthString(64); - auto const needle = p.ConsumeRandomLengthString(64); + auto const haystack = p.ConsumeRandomLengthString(); + auto const needle = p.ConsumeRandomLengthString(); auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; diff --git a/fuzzing/src/string_view.find.fuzz.cpp b/fuzzing/src/string_view.find.fuzz.cpp index 0ea1d28a4..1a6d2402b 100644 --- a/fuzzing/src/string_view.find.fuzz.cpp +++ b/fuzzing/src/string_view.find.fuzz.cpp @@ -10,8 +10,8 @@ static auto fuzz_string_view_find(FuzzedDataProvider& p) -> int { - auto const haystack = p.ConsumeRandomLengthString(64); - auto const needle = p.ConsumeRandomLengthString(64); + auto const haystack = p.ConsumeRandomLengthString(); + auto const needle = p.ConsumeRandomLengthString(); auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; diff --git a/fuzzing/src/string_view.find_first_not_of.fuzz.cpp b/fuzzing/src/string_view.find_first_not_of.fuzz.cpp index 587dae6dc..ccd47e3c2 100644 --- a/fuzzing/src/string_view.find_first_not_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_first_not_of.fuzz.cpp @@ -10,8 +10,8 @@ static auto fuzz_string_view_find_first_not_of(FuzzedDataProvider& p) -> int { - auto const haystack = p.ConsumeRandomLengthString(64); - auto const needle = p.ConsumeRandomLengthString(64); + auto const haystack = p.ConsumeRandomLengthString(); + auto const needle = p.ConsumeRandomLengthString(); auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; diff --git a/fuzzing/src/string_view.find_first_of.fuzz.cpp b/fuzzing/src/string_view.find_first_of.fuzz.cpp index 71851cca0..0b4aa5074 100644 --- a/fuzzing/src/string_view.find_first_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_first_of.fuzz.cpp @@ -10,8 +10,8 @@ static auto fuzz_string_view_find_first_of(FuzzedDataProvider& p) -> int { - auto const haystack = p.ConsumeRandomLengthString(64); - auto const needle = p.ConsumeRandomLengthString(64); + auto const haystack = p.ConsumeRandomLengthString(); + auto const needle = p.ConsumeRandomLengthString(); auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; diff --git a/fuzzing/src/string_view.find_last_not_of.fuzz.cpp b/fuzzing/src/string_view.find_last_not_of.fuzz.cpp index 31673c545..f545e8ad7 100644 --- a/fuzzing/src/string_view.find_last_not_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_last_not_of.fuzz.cpp @@ -10,8 +10,8 @@ static auto fuzz_string_view_find_last_not_of(FuzzedDataProvider& p) -> int { - auto const haystack = p.ConsumeRandomLengthString(64); - auto const needle = p.ConsumeRandomLengthString(64); + auto const haystack = p.ConsumeRandomLengthString(); + auto const needle = p.ConsumeRandomLengthString(); auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; diff --git a/fuzzing/src/string_view.find_last_of.fuzz.cpp b/fuzzing/src/string_view.find_last_of.fuzz.cpp index fdafd3172..74838a66c 100644 --- a/fuzzing/src/string_view.find_last_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_last_of.fuzz.cpp @@ -10,8 +10,8 @@ static auto fuzz_string_view_find_last_of(FuzzedDataProvider& p) -> int { - auto const haystack = p.ConsumeRandomLengthString(64); - auto const needle = p.ConsumeRandomLengthString(64); + auto const haystack = p.ConsumeRandomLengthString(); + auto const needle = p.ConsumeRandomLengthString(); auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; diff --git a/fuzzing/src/string_view.rfind.fuzz.cpp b/fuzzing/src/string_view.rfind.fuzz.cpp index e8670940a..5f1e7d0b7 100644 --- a/fuzzing/src/string_view.rfind.fuzz.cpp +++ b/fuzzing/src/string_view.rfind.fuzz.cpp @@ -10,8 +10,8 @@ static auto fuzz_string_view_rfind(FuzzedDataProvider& p) -> int { - auto const haystack = p.ConsumeRandomLengthString(64); - auto const needle = p.ConsumeRandomLengthString(64); + auto const haystack = p.ConsumeRandomLengthString(); + auto const needle = p.ConsumeRandomLengthString(); auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; diff --git a/fuzzing/src/string_view.starts_with.fuzz.cpp b/fuzzing/src/string_view.starts_with.fuzz.cpp index 0c001c99b..a67186ca7 100644 --- a/fuzzing/src/string_view.starts_with.fuzz.cpp +++ b/fuzzing/src/string_view.starts_with.fuzz.cpp @@ -10,8 +10,8 @@ static auto fuzz_string_view_starts_with(FuzzedDataProvider& p) -> int { - auto const haystack = p.ConsumeRandomLengthString(64); - auto const needle = p.ConsumeRandomLengthString(64); + auto const haystack = p.ConsumeRandomLengthString(); + auto const needle = p.ConsumeRandomLengthString(); auto const eview = etl::string_view{haystack.data(), haystack.size()}; auto const sview = std::string_view{haystack.data(), haystack.size()}; From a9fa73af6ab320fdb2fd6a016b4262915be87d80 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Sun, 5 Oct 2025 18:03:13 +0200 Subject: [PATCH 37/39] [fuzzing] Always print output to stderr --- fuzzing/include/sorting.hpp | 4 +- fuzzing/src/bitset.fuzz.cpp | 12 ++-- fuzzing/src/cctype.fuzz.cpp | 56 +++++++++---------- fuzzing/src/charconv.from_chars.fuzz.cpp | 4 +- fuzzing/src/charconv.to_chars.fuzz.cpp | 9 +-- .../random.uniform_real_distribution.fuzz.cpp | 2 +- fuzzing/src/string_view.contains.fuzz.cpp | 12 ++-- fuzzing/src/string_view.ends_with.fuzz.cpp | 12 ++-- fuzzing/src/string_view.find.fuzz.cpp | 12 ++-- .../string_view.find_first_not_of.fuzz.cpp | 12 ++-- .../src/string_view.find_first_of.fuzz.cpp | 12 ++-- .../src/string_view.find_last_not_of.fuzz.cpp | 12 ++-- fuzzing/src/string_view.find_last_of.fuzz.cpp | 12 ++-- fuzzing/src/string_view.rfind.fuzz.cpp | 12 ++-- fuzzing/src/string_view.starts_with.fuzz.cpp | 12 ++-- scripts/sorting.cpp | 48 ++++++++++------ 16 files changed, 129 insertions(+), 114 deletions(-) diff --git a/fuzzing/include/sorting.hpp b/fuzzing/include/sorting.hpp index 91fbc5f27..605fe540a 100644 --- a/fuzzing/include/sorting.hpp +++ b/fuzzing/include/sorting.hpp @@ -18,13 +18,13 @@ sorter(view.begin(), view.end(), etl::less()); if (not std::is_sorted(view.begin(), view.end(), etl::less())) { - std::println("Data is not sorted via etl::less. Size = {}", view.size()); + std::println(stderr, "Data is not sorted via etl::less. Size = {}", view.size()); return 1; } sorter(view.begin(), view.end(), etl::greater()); if (not std::is_sorted(view.begin(), view.end(), etl::greater())) { - std::println("Data is not sorted via etl::greater. Size = {}", view.size()); + std::println(stderr, "Data is not sorted via etl::greater. Size = {}", view.size()); return 1; } diff --git a/fuzzing/src/bitset.fuzz.cpp b/fuzzing/src/bitset.fuzz.cpp index 7e5310afb..a32260033 100644 --- a/fuzzing/src/bitset.fuzz.cpp +++ b/fuzzing/src/bitset.fuzz.cpp @@ -29,18 +29,18 @@ static auto fuzz_bitset(FuzzedDataProvider& p) -> int auto const slong = sset.to_ullong(); if ((eview != sview) or (elong != slong)) { - std::println("etl::bitset::to_ullong"); - std::println("val: '{}'", static_cast(val)); - std::println("estr: '{}'\nsstr: '{}'", estr.c_str(), sstr); - std::println("elong: '{}' slong: '{}'", elong, slong); + std::println(stderr, "etl::bitset::to_ullong"); + std::println(stderr, "val: '{}'", static_cast(val)); + std::println(stderr, "estr: '{}'\nsstr: '{}'", estr.c_str(), sstr); + std::println(stderr, "elong: '{}' slong: '{}'", elong, slong); return 1; } auto const efromstr = etl::bitset{estr.c_str()}; if (eset != efromstr) { - std::println("etl::bitset(string_view)"); - std::println("estr: '{}'\nefromstr: '{}'", estr.c_str(), efromstr.template to_string().c_str()); + std::println(stderr, "etl::bitset(string_view)"); + std::println(stderr, "estr: '{}'\nefromstr: '{}'", estr.c_str(), efromstr.template to_string().c_str()); return 1; } diff --git a/fuzzing/src/cctype.fuzz.cpp b/fuzzing/src/cctype.fuzz.cpp index b936efd84..43a5c84d4 100644 --- a/fuzzing/src/cctype.fuzz.cpp +++ b/fuzzing/src/cctype.fuzz.cpp @@ -16,8 +16,8 @@ auto const s = std::isalnum(static_cast(static_cast(c))) != 0; auto const e = etl::isalnum(static_cast(static_cast(c))) != 0; if (e != s) { - std::println("std::isalnum({:c}) = {}", c, s); - std::println("etl::isalnum({:c}) = {}", c, e); + std::println(stderr, "std::isalnum({:c}) = {}", c, s); + std::println(stderr, "etl::isalnum({:c}) = {}", c, e); return 1; } } @@ -26,8 +26,8 @@ auto const s = std::isalpha(static_cast(static_cast(c))) != 0; auto const e = etl::isalpha(static_cast(static_cast(c))) != 0; if (e != s) { - std::println("std::isalpha({:c}) = {}", c, s); - std::println("etl::isalpha({:c}) = {}", c, e); + std::println(stderr, "std::isalpha({:c}) = {}", c, s); + std::println(stderr, "etl::isalpha({:c}) = {}", c, e); return 1; } } @@ -36,8 +36,8 @@ auto const s = std::isblank(static_cast(static_cast(c))) != 0; auto const e = etl::isblank(static_cast(static_cast(c))) != 0; if (e != s) { - std::println("std::isblank({:c}) = {}", c, s); - std::println("etl::isblank({:c}) = {}", c, e); + std::println(stderr, "std::isblank({:c}) = {}", c, s); + std::println(stderr, "etl::isblank({:c}) = {}", c, e); return 1; } } @@ -46,8 +46,8 @@ auto const s = std::iscntrl(static_cast(static_cast(c))) != 0; auto const e = etl::iscntrl(static_cast(static_cast(c))) != 0; if (e != s) { - std::println("std::iscntrl({:c}) = {}", c, s); - std::println("etl::iscntrl({:c}) = {}", c, e); + std::println(stderr, "std::iscntrl({:c}) = {}", c, s); + std::println(stderr, "etl::iscntrl({:c}) = {}", c, e); return 1; } } @@ -56,8 +56,8 @@ auto const s = std::isdigit(static_cast(static_cast(c))) != 0; auto const e = etl::isdigit(static_cast(static_cast(c))) != 0; if (e != s) { - std::println("std::isdigit({:c}) = {}", c, s); - std::println("etl::isdigit({:c}) = {}", c, e); + std::println(stderr, "std::isdigit({:c}) = {}", c, s); + std::println(stderr, "etl::isdigit({:c}) = {}", c, e); return 1; } } @@ -66,8 +66,8 @@ auto const s = std::isgraph(static_cast(static_cast(c))) != 0; auto const e = etl::isgraph(static_cast(static_cast(c))) != 0; if (e != s) { - std::println("std::isgraph({:c}) = {}", c, s); - std::println("etl::isgraph({:c}) = {}", c, e); + std::println(stderr, "std::isgraph({:c}) = {}", c, s); + std::println(stderr, "etl::isgraph({:c}) = {}", c, e); return 1; } } @@ -76,8 +76,8 @@ auto const s = std::islower(static_cast(static_cast(c))) != 0; auto const e = etl::islower(static_cast(static_cast(c))) != 0; if (e != s) { - std::println("std::islower({:c}) = {}", c, s); - std::println("etl::islower({:c}) = {}", c, e); + std::println(stderr, "std::islower({:c}) = {}", c, s); + std::println(stderr, "etl::islower({:c}) = {}", c, e); return 1; } } @@ -86,8 +86,8 @@ auto const s = std::isprint(static_cast(static_cast(c))) != 0; auto const e = etl::isprint(static_cast(static_cast(c))) != 0; if (e != s) { - std::println("std::isprint({:c}) = {}", c, s); - std::println("etl::isprint({:c}) = {}", c, e); + std::println(stderr, "std::isprint({:c}) = {}", c, s); + std::println(stderr, "etl::isprint({:c}) = {}", c, e); return 1; } } @@ -96,8 +96,8 @@ auto const s = std::ispunct(static_cast(static_cast(c))) != 0; auto const e = etl::ispunct(static_cast(static_cast(c))) != 0; if (e != s) { - std::println("std::ispunct({:c}) = {}", c, s); - std::println("etl::ispunct({:c}) = {}", c, e); + std::println(stderr, "std::ispunct({:c}) = {}", c, s); + std::println(stderr, "etl::ispunct({:c}) = {}", c, e); return 1; } } @@ -106,8 +106,8 @@ auto const s = std::isspace(static_cast(static_cast(c))) != 0; auto const e = etl::isspace(static_cast(static_cast(c))) != 0; if (e != s) { - std::println("std::isspace({:c}) = {}", c, s); - std::println("etl::isspace({:c}) = {}", c, e); + std::println(stderr, "std::isspace({:c}) = {}", c, s); + std::println(stderr, "etl::isspace({:c}) = {}", c, e); return 1; } } @@ -116,8 +116,8 @@ auto const s = std::isupper(static_cast(static_cast(c))) != 0; auto const e = etl::isupper(static_cast(static_cast(c))) != 0; if (e != s) { - std::println("std::isupper({:c}) = {}", c, s); - std::println("etl::isupper({:c}) = {}", c, e); + std::println(stderr, "std::isupper({:c}) = {}", c, s); + std::println(stderr, "etl::isupper({:c}) = {}", c, e); return 1; } } @@ -126,8 +126,8 @@ auto const s = std::isxdigit(static_cast(static_cast(c))) != 0; auto const e = etl::isxdigit(static_cast(static_cast(c))) != 0; if (e != s) { - std::println("std::isxdigit({:c}) = {}", c, s); - std::println("etl::isxdigit({:c}) = {}", c, e); + std::println(stderr, "std::isxdigit({:c}) = {}", c, s); + std::println(stderr, "etl::isxdigit({:c}) = {}", c, e); return 1; } } @@ -136,8 +136,8 @@ auto const s = std::tolower(static_cast(static_cast(c))); auto const e = etl::tolower(static_cast(static_cast(c))); if (e != s) { - std::println("std::tolower({:c}) = {:c}", c, s); - std::println("etl::tolower({:c}) = {:c}", c, e); + std::println(stderr, "std::tolower({:c}) = {:c}", c, s); + std::println(stderr, "etl::tolower({:c}) = {:c}", c, e); return 1; } } @@ -146,8 +146,8 @@ auto const s = std::toupper(static_cast(static_cast(c))); auto const e = etl::toupper(static_cast(static_cast(c))); if (e != s) { - std::println("std::toupper({:c}) = {:c}", c, s); - std::println("etl::toupper({:c}) = {:c}", c, e); + std::println(stderr, "std::toupper({:c}) = {:c}", c, s); + std::println(stderr, "etl::toupper({:c}) = {:c}", c, e); return 1; } } diff --git a/fuzzing/src/charconv.from_chars.fuzz.cpp b/fuzzing/src/charconv.from_chars.fuzz.cpp index f0336d704..a10c8b7fa 100644 --- a/fuzzing/src/charconv.from_chars.fuzz.cpp +++ b/fuzzing/src/charconv.from_chars.fuzz.cpp @@ -34,12 +34,13 @@ template }(); if (etlVal != stdVal) { - std::println("Str: '{}' Base: {} Value mismatch: etl={} - std={}", input, base, etlVal, stdVal); + std::println(stderr, "Str: '{}' Base: {} Value mismatch: etl={} - std={}", input, base, etlVal, stdVal); return 1; } if (etlEc != stdEc) { std::println( + stderr, "Str: '{}' Base: {} Error mismatch: etl={} - std={}", input, base, @@ -51,6 +52,7 @@ template if (etlPtr != stdPtr) { std::println( + stderr, "Str: '{}' Base: {} Value: etl={} - std={} Error: etl={} - std={} Pointer mismatch: etl={} - std={}", input, base, diff --git a/fuzzing/src/charconv.to_chars.fuzz.cpp b/fuzzing/src/charconv.to_chars.fuzz.cpp index b279f7304..4000cccaf 100644 --- a/fuzzing/src/charconv.to_chars.fuzz.cpp +++ b/fuzzing/src/charconv.to_chars.fuzz.cpp @@ -35,15 +35,16 @@ template auto const etlDist = std::distance(etlBuf.data(), etlPtr); if ((etlDist != stdDist) or (etlEc != stdEc) or ((etlBuf != stdBuf) and stdEc != std::errc::value_too_large)) { - std::println("Func: {}", __PRETTY_FUNCTION__); - std::println("Value: {} Base: {}", value, base); + std::println(stderr, "Func: {}", __PRETTY_FUNCTION__); + std::println(stderr, "Value: {} Base: {}", value, base); std::println( + stderr, "Buffer: etl='{}' - std='{}'", std::string_view{etlBuf.data(), etlBuf.size()}, std::string_view{stdBuf.data(), stdBuf.size()} ); - std::println("Distance: etl={} - std={}", etlDist, stdDist); - std::println("Error: etl='{}' - std='{}'", to_string(etlEc), to_string(stdEc)); + std::println(stderr, "Distance: etl={} - std={}", etlDist, stdDist); + std::println(stderr, "Error: etl='{}' - std='{}'", to_string(etlEc), to_string(stdEc)); return 1; } diff --git a/fuzzing/src/random.uniform_real_distribution.fuzz.cpp b/fuzzing/src/random.uniform_real_distribution.fuzz.cpp index 323670767..2ae48c0c9 100644 --- a/fuzzing/src/random.uniform_real_distribution.fuzz.cpp +++ b/fuzzing/src/random.uniform_real_distribution.fuzz.cpp @@ -23,7 +23,7 @@ template auto urng = etl::xoshiro128starstar{p.ConsumeIntegral()}; auto dist = etl::uniform_real_distribution{distMin, distMax}; if (auto const val = dist(urng); val < distMin or val > distMax) { - std::println("dist_min: {}, dist_max: {}, val: {}", distMin, distMax, val); + std::println(stderr, "dist_min: {}, dist_max: {}, val: {}", distMin, distMax, val); return 1; } return 0; diff --git a/fuzzing/src/string_view.contains.fuzz.cpp b/fuzzing/src/string_view.contains.fuzz.cpp index 1418e4a82..801d93f78 100644 --- a/fuzzing/src/string_view.contains.fuzz.cpp +++ b/fuzzing/src/string_view.contains.fuzz.cpp @@ -20,9 +20,9 @@ static auto fuzz_string_view_contains(FuzzedDataProvider& p) -> int auto const epos = eview.contains(needle[0]); auto const spos = sview.contains(needle[0]); if (epos != spos) { - std::println("etl::string_view::contains(char)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::contains(char)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } } @@ -30,9 +30,9 @@ static auto fuzz_string_view_contains(FuzzedDataProvider& p) -> int auto const epos = eview.contains(needle.c_str()); auto const spos = sview.contains(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::contains(char const*)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::contains(char const*)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } return 0; diff --git a/fuzzing/src/string_view.ends_with.fuzz.cpp b/fuzzing/src/string_view.ends_with.fuzz.cpp index e2bfc2d6a..703c4a60f 100644 --- a/fuzzing/src/string_view.ends_with.fuzz.cpp +++ b/fuzzing/src/string_view.ends_with.fuzz.cpp @@ -20,9 +20,9 @@ static auto fuzz_string_view_ends_with(FuzzedDataProvider& p) -> int auto const epos = eview.ends_with(needle[0]); auto const spos = sview.ends_with(needle[0]); if (epos != spos) { - std::println("etl::string_view::ends_with(char)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::ends_with(char)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } } @@ -30,9 +30,9 @@ static auto fuzz_string_view_ends_with(FuzzedDataProvider& p) -> int auto const epos = eview.ends_with(needle.c_str()); auto const spos = sview.ends_with(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::ends_with(char const*)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::ends_with(char const*)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } return 0; diff --git a/fuzzing/src/string_view.find.fuzz.cpp b/fuzzing/src/string_view.find.fuzz.cpp index 1a6d2402b..744de20e9 100644 --- a/fuzzing/src/string_view.find.fuzz.cpp +++ b/fuzzing/src/string_view.find.fuzz.cpp @@ -20,9 +20,9 @@ static auto fuzz_string_view_find(FuzzedDataProvider& p) -> int auto const epos = eview.find(needle[0]); auto const spos = sview.find(needle[0]); if (epos != spos) { - std::println("etl::string_view::find(char)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::find(char)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } } @@ -30,9 +30,9 @@ static auto fuzz_string_view_find(FuzzedDataProvider& p) -> int auto const epos = eview.find(needle.c_str()); auto const spos = sview.find(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::find(char const*)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::find(char const*)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } return 0; diff --git a/fuzzing/src/string_view.find_first_not_of.fuzz.cpp b/fuzzing/src/string_view.find_first_not_of.fuzz.cpp index ccd47e3c2..bf4fcc0e8 100644 --- a/fuzzing/src/string_view.find_first_not_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_first_not_of.fuzz.cpp @@ -20,9 +20,9 @@ static auto fuzz_string_view_find_first_not_of(FuzzedDataProvider& p) -> int auto const epos = eview.find_first_not_of(needle[0]); auto const spos = sview.find_first_not_of(needle[0]); if (epos != spos) { - std::println("etl::string_view::find_first_not_of(char)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::find_first_not_of(char)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } } @@ -30,9 +30,9 @@ static auto fuzz_string_view_find_first_not_of(FuzzedDataProvider& p) -> int auto const epos = eview.find_first_not_of(needle.c_str()); auto const spos = sview.find_first_not_of(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::find_first_not_of(char const*)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::find_first_not_of(char const*)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } return 0; diff --git a/fuzzing/src/string_view.find_first_of.fuzz.cpp b/fuzzing/src/string_view.find_first_of.fuzz.cpp index 0b4aa5074..2becd3de5 100644 --- a/fuzzing/src/string_view.find_first_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_first_of.fuzz.cpp @@ -20,9 +20,9 @@ static auto fuzz_string_view_find_first_of(FuzzedDataProvider& p) -> int auto const epos = eview.find_first_of(needle[0]); auto const spos = sview.find_first_of(needle[0]); if (epos != spos) { - std::println("etl::string_view::find_first_of(char)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::find_first_of(char)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } } @@ -30,9 +30,9 @@ static auto fuzz_string_view_find_first_of(FuzzedDataProvider& p) -> int auto const epos = eview.find_first_of(needle.c_str()); auto const spos = sview.find_first_of(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::find_first_of(char const*)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::find_first_of(char const*)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } return 0; diff --git a/fuzzing/src/string_view.find_last_not_of.fuzz.cpp b/fuzzing/src/string_view.find_last_not_of.fuzz.cpp index f545e8ad7..8a29cdbd8 100644 --- a/fuzzing/src/string_view.find_last_not_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_last_not_of.fuzz.cpp @@ -20,9 +20,9 @@ static auto fuzz_string_view_find_last_not_of(FuzzedDataProvider& p) -> int auto const epos = eview.find_last_not_of(needle[0]); auto const spos = sview.find_last_not_of(needle[0]); if (epos != spos) { - std::println("etl::string_view::find_last_not_of(char)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::find_last_not_of(char)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } } @@ -30,9 +30,9 @@ static auto fuzz_string_view_find_last_not_of(FuzzedDataProvider& p) -> int auto const epos = eview.find_last_not_of(needle.c_str()); auto const spos = sview.find_last_not_of(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::find_last_not_of(char const*)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::find_last_not_of(char const*)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } return 0; diff --git a/fuzzing/src/string_view.find_last_of.fuzz.cpp b/fuzzing/src/string_view.find_last_of.fuzz.cpp index 74838a66c..0b8feb2e4 100644 --- a/fuzzing/src/string_view.find_last_of.fuzz.cpp +++ b/fuzzing/src/string_view.find_last_of.fuzz.cpp @@ -20,9 +20,9 @@ static auto fuzz_string_view_find_last_of(FuzzedDataProvider& p) -> int auto const epos = eview.find_last_of(needle[0]); auto const spos = sview.find_last_of(needle[0]); if (epos != spos) { - std::println("etl::string_view::find_last_of(char)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::find_last_of(char)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } } @@ -30,9 +30,9 @@ static auto fuzz_string_view_find_last_of(FuzzedDataProvider& p) -> int auto const epos = eview.find_last_of(needle.c_str()); auto const spos = sview.find_last_of(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::find_last_of(char const*)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::find_last_of(char const*)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } return 0; diff --git a/fuzzing/src/string_view.rfind.fuzz.cpp b/fuzzing/src/string_view.rfind.fuzz.cpp index 5f1e7d0b7..4900e79bc 100644 --- a/fuzzing/src/string_view.rfind.fuzz.cpp +++ b/fuzzing/src/string_view.rfind.fuzz.cpp @@ -20,9 +20,9 @@ static auto fuzz_string_view_rfind(FuzzedDataProvider& p) -> int auto const epos = eview.rfind(needle[0]); auto const spos = sview.rfind(needle[0]); if (epos != spos) { - std::println("etl::string_view::rfind(char)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::rfind(char)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } } @@ -30,9 +30,9 @@ static auto fuzz_string_view_rfind(FuzzedDataProvider& p) -> int auto const epos = eview.rfind(needle.c_str()); auto const spos = sview.rfind(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::rfind(char const*)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::rfind(char const*)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } return 0; diff --git a/fuzzing/src/string_view.starts_with.fuzz.cpp b/fuzzing/src/string_view.starts_with.fuzz.cpp index a67186ca7..0f2922453 100644 --- a/fuzzing/src/string_view.starts_with.fuzz.cpp +++ b/fuzzing/src/string_view.starts_with.fuzz.cpp @@ -20,9 +20,9 @@ static auto fuzz_string_view_starts_with(FuzzedDataProvider& p) -> int auto const epos = eview.starts_with(needle[0]); auto const spos = sview.starts_with(needle[0]); if (epos != spos) { - std::println("etl::string_view::starts_with(char)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::starts_with(char)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } } @@ -30,9 +30,9 @@ static auto fuzz_string_view_starts_with(FuzzedDataProvider& p) -> int auto const epos = eview.starts_with(needle.c_str()); auto const spos = sview.starts_with(needle.c_str()); if (epos != spos) { - std::println("etl::string_view::starts_with(char const*)"); - std::println("haystack: '{}' needle: '{}'", haystack, needle); - std::println("epos: '{}' spos: '{}'", epos, spos); + std::println(stderr, "etl::string_view::starts_with(char const*)"); + std::println(stderr, "haystack: '{}' needle: '{}'", haystack, needle); + std::println(stderr, "epos: '{}' spos: '{}'", epos, spos); return 1; } return 0; diff --git a/scripts/sorting.cpp b/scripts/sorting.cpp index 0cd3baa8b..0f58b2a8c 100644 --- a/scripts/sorting.cpp +++ b/scripts/sorting.cpp @@ -103,6 +103,7 @@ void run_case(char const* label, SortFn sorter, size_t n) std::mt19937 rng(123456789); for (size_t i = 0; i < n; ++i) { a.emplace_back(int(rng())); + // a.emplace_back(int(i)); } SortCounters::reset(); @@ -111,8 +112,9 @@ void run_case(char const* label, SortFn sorter, size_t n) double const lb = log2_factorial(n); // ~ n log2 n - 1.44 n double const nlogn = n * std::log2((double)n); // rough model + std::println( - "{} n={} comps={} comps/(n^2)={:.3f} comps/(nlog2n)={:.3f} comps/log2(n!)={:.3f} swaps={} copies={} moves={}", + "{:20}|{:^10}|{:^15}|{:^15.3f}|{:^15.3f}|{:^15.3f}|{:^10}|{:^10}|{:^10}", label, n, SortCounters::comps, @@ -128,24 +130,34 @@ void run_case(char const* label, SortFn sorter, size_t n) int main() { for (size_t n : {1u << 2, 1u << 4, 1u << 8, 1u << 12, 1u << 14}) { - std::puts("--------------------------------------------------------------"); - run_case("std::sort ", [](auto f, auto l) { std::sort(f, l); }, n); - run_case("etl::sort ", [](auto f, auto l) { etl::sort(f, l); }, n); - - std::puts("---------"); - run_case("std::stable_sort ", [](auto f, auto l) { std::stable_sort(f, l); }, n); - run_case("etl::stable_sort ", [](auto f, auto l) { etl::stable_sort(f, l); }, n); - - std::puts("---------"); - run_case("etl::merge_sort ", [](auto f, auto l) { etl::merge_sort(f, l); }, n); - run_case("etl::quick_sort ", [](auto f, auto l) { etl::quick_sort(f, l); }, n); + std::println( + "{:^20}|{:^10}|{:^15}|{:^15}|{:^15}|{:^15}|{:^10}|{:^10}|{:^10}", + "Algorithm", + "Size", + "Comps", + "Comps/(n^2)", + "Comps/(nlogn)", + "Comps/(n!)", + "Swap", + "Copy", + "Move" + ); + + run_case("std::sort", [](auto f, auto l) { std::sort(f, l); }, n); + run_case("etl::sort", [](auto f, auto l) { etl::sort(f, l); }, n); + + run_case("std::stable_sort", [](auto f, auto l) { std::stable_sort(f, l); }, n); + run_case("etl::stable_sort", [](auto f, auto l) { etl::stable_sort(f, l); }, n); + + run_case("etl::merge_sort", [](auto f, auto l) { etl::merge_sort(f, l); }, n); + run_case("etl::quick_sort", [](auto f, auto l) { etl::quick_sort(f, l); }, n); run_case("etl::insertion_sort", [](auto f, auto l) { etl::insertion_sort(f, l); }, n); - run_case("etl::bubble_sort ", [](auto f, auto l) { etl::bubble_sort(f, l); }, n); - run_case("etl::exchange_sort ", [](auto f, auto l) { etl::exchange_sort(f, l); }, n); - run_case("etl::gnome_sort ", [](auto f, auto l) { etl::gnome_sort(f, l); }, n); + run_case("etl::bubble_sort", [](auto f, auto l) { etl::bubble_sort(f, l); }, n); + run_case("etl::exchange_sort", [](auto f, auto l) { etl::exchange_sort(f, l); }, n); + run_case("etl::gnome_sort", [](auto f, auto l) { etl::gnome_sort(f, l); }, n); - std::puts("---------"); - run_case("std::nth_element ", [](auto f, auto l) { std::nth_element(f, etl::midpoint(f, l), l); }, n); - run_case("etl::nth_element ", [](auto f, auto l) { etl::nth_element(f, etl::midpoint(f, l), l); }, n); + run_case("std::nth_element", [](auto f, auto l) { std::nth_element(f, etl::midpoint(f, l), l); }, n); + run_case("etl::nth_element", [](auto f, auto l) { etl::nth_element(f, etl::midpoint(f, l), l); }, n); + std::puts(""); } } From 77703e4653efcc35422f72ae78be2f2babbf5d3f Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Tue, 7 Oct 2025 20:13:26 +0200 Subject: [PATCH 38/39] Upgrade reuse-tool to v6.1.0 --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4fd32b6d1..ffca3413c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,6 +31,6 @@ repos: types_or: [c++, c] - repo: https://github.com/fsfe/reuse-tool - rev: v5.1.1 + rev: v6.1.0 hooks: - id: reuse From 97ba5000e0c1cc50c5915e020e09fead051e9d83 Mon Sep 17 00:00:00 2001 From: Tobias Hienzsch Date: Tue, 7 Oct 2025 21:18:38 +0200 Subject: [PATCH 39/39] Remove unused clang-format directives --- include/etl/_compare/synth_three_way.hpp | 2 -- include/etl/_compare/three_way_comparable.hpp | 27 ++++++++----------- include/etl/_concepts/assignable_from.hpp | 17 +++++------- .../weakly_equality_comparable_with.hpp | 6 +---- .../etl/_iterator/incrementable_traits.hpp | 3 --- .../indirectly_regular_unary_invocable.hpp | 20 +++++++------- .../_iterator/indirectly_unary_invocable.hpp | 18 ++++++------- .../etl/_iterator/legacy_input_iterator.hpp | 7 ++--- .../etl/_iterator/weakly_incrementable.hpp | 2 -- 9 files changed, 39 insertions(+), 63 deletions(-) diff --git a/include/etl/_compare/synth_three_way.hpp b/include/etl/_compare/synth_three_way.hpp index a38a77939..fd0a1ba65 100644 --- a/include/etl/_compare/synth_three_way.hpp +++ b/include/etl/_compare/synth_three_way.hpp @@ -10,7 +10,6 @@ namespace etl { -// // clang-format off // inline constexpr auto synth_three_way = // [](T const& t, U const& u) // requires requires { @@ -26,7 +25,6 @@ namespace etl { // return weak_ordering::equivalent; // } // }; -// // clang-format on // template // using synth_three_way_result diff --git a/include/etl/_compare/three_way_comparable.hpp b/include/etl/_compare/three_way_comparable.hpp index d0046adf6..551e191f2 100644 --- a/include/etl/_compare/three_way_comparable.hpp +++ b/include/etl/_compare/three_way_comparable.hpp @@ -17,32 +17,27 @@ namespace detail { template concept compares_as = same_as, Cat>; -// clang-format off -template +template concept partially_ordered_with = requires(remove_reference_t const& t, remove_reference_t const& u) { - { t < u } -> boolean_testable; - { t > u } -> boolean_testable; + { t < u } -> boolean_testable; + { t > u } -> boolean_testable; { t <= u } -> boolean_testable; { t >= u } -> boolean_testable; - { u < t } -> boolean_testable; - { u > t } -> boolean_testable; + { u < t } -> boolean_testable; + { u > t } -> boolean_testable; { u <= t } -> boolean_testable; { u >= t } -> boolean_testable; }; -// clang-format on } // namespace detail -// clang-format off /// \ingroup compare -template -concept three_way_comparable = - weakly_equality_comparable_with && - detail::partially_ordered_with && - requires(remove_reference_t const& a, remove_reference_t const& b) { - { a <=> b } -> detail::compares_as; - }; -// clang-format on +template +concept three_way_comparable = weakly_equality_comparable_with + && detail::partially_ordered_with + && requires(remove_reference_t const& a, remove_reference_t const& b) { + { a <=> b } -> detail::compares_as; + }; } // namespace etl #endif // TETL_COMPARE_THREE_WAY_COMPAREABLE_HPP diff --git a/include/etl/_concepts/assignable_from.hpp b/include/etl/_concepts/assignable_from.hpp index 730dfc6c9..7cd1cb569 100644 --- a/include/etl/_concepts/assignable_from.hpp +++ b/include/etl/_concepts/assignable_from.hpp @@ -12,19 +12,14 @@ namespace etl { -// clang-format off - /// \headerfile etl/concepts.hpp /// \ingroup concepts -template -concept assignable_from = - is_lvalue_reference_v - // and common_reference_with const&, remove_reference_t const&> - and requires(LHS lhs, RHS&& rhs) { - { lhs = etl::forward(rhs) } -> same_as; - }; - -// clang-format on +template +concept assignable_from = is_lvalue_reference_v + // and common_reference_with const&, remove_reference_t const&> + and requires(LHS lhs, RHS&& rhs) { + { lhs = etl::forward(rhs) } -> same_as; + }; } // namespace etl diff --git a/include/etl/_concepts/weakly_equality_comparable_with.hpp b/include/etl/_concepts/weakly_equality_comparable_with.hpp index b5c034b0c..3fea96f30 100644 --- a/include/etl/_concepts/weakly_equality_comparable_with.hpp +++ b/include/etl/_concepts/weakly_equality_comparable_with.hpp @@ -10,12 +10,10 @@ namespace etl { -// clang-format off - /// \note Non-standard extension /// \headerfile etl/concepts.hpp /// \ingroup concepts -template +template concept weakly_equality_comparable_with = requires(remove_reference_t const& t, remove_reference_t const& u) { { t == u } -> boolean_testable; { t != u } -> boolean_testable; @@ -23,8 +21,6 @@ concept weakly_equality_comparable_with = requires(remove_reference_t const& { u != t } -> boolean_testable; }; -// clang-format on - } // namespace etl #endif // TETL_CONCEPTS_WEAKLY_EQUALITY_COMPAREABLE_WITH_HPP diff --git a/include/etl/_iterator/incrementable_traits.hpp b/include/etl/_iterator/incrementable_traits.hpp index dd6e12f53..abca6ac8a 100644 --- a/include/etl/_iterator/incrementable_traits.hpp +++ b/include/etl/_iterator/incrementable_traits.hpp @@ -35,7 +35,6 @@ struct incrementable_traits { using difference_type = typename T::difference_type; }; -// clang-format off template requires(not detail::has_difference_type) and requires(T const& a, T const& b) { { a - b } -> etl::integral; @@ -44,8 +43,6 @@ struct incrementable_traits { using difference_type = etl::make_signed_t() - etl::declval())>; }; -// clang-format on - } // namespace etl #endif // TETL_ITERATOR_INCREMENTABLE_TRAITS_HPP diff --git a/include/etl/_iterator/indirectly_regular_unary_invocable.hpp b/include/etl/_iterator/indirectly_regular_unary_invocable.hpp index 3c174e12e..288aaa32a 100644 --- a/include/etl/_iterator/indirectly_regular_unary_invocable.hpp +++ b/include/etl/_iterator/indirectly_regular_unary_invocable.hpp @@ -15,16 +15,16 @@ namespace etl { -// clang-format off -template -concept indirectly_regular_unary_invocable = - etl::indirectly_readable - and etl::copy_constructible - and etl::regular_invocable&> - and etl::regular_invocable> - and etl::regular_invocable> - and etl::common_reference_with&>, etl::invoke_result_t>>; -// clang-format on +template +concept indirectly_regular_unary_invocable = etl::indirectly_readable + and etl::copy_constructible + and etl::regular_invocable&> + and etl::regular_invocable> + and etl::regular_invocable> + and etl::common_reference_with< + etl::invoke_result_t&>, + etl::invoke_result_t> + >; } // namespace etl diff --git a/include/etl/_iterator/indirectly_unary_invocable.hpp b/include/etl/_iterator/indirectly_unary_invocable.hpp index e113cc98d..8374db05a 100644 --- a/include/etl/_iterator/indirectly_unary_invocable.hpp +++ b/include/etl/_iterator/indirectly_unary_invocable.hpp @@ -15,16 +15,16 @@ namespace etl { -// clang-format off template -concept indirectly_unary_invocable = - etl::indirectly_readable - and etl::copy_constructible - and etl::invocable&> - and etl::invocable> - and etl::invocable> - and etl::common_reference_with&>, etl::invoke_result_t>>; -// clang-format on +concept indirectly_unary_invocable = etl::indirectly_readable + and etl::copy_constructible + and etl::invocable&> + and etl::invocable> + and etl::invocable> + and etl::common_reference_with< + etl::invoke_result_t&>, + etl::invoke_result_t> + >; } // namespace etl diff --git a/include/etl/_iterator/legacy_input_iterator.hpp b/include/etl/_iterator/legacy_input_iterator.hpp index 645a82118..06058a08a 100644 --- a/include/etl/_iterator/legacy_input_iterator.hpp +++ b/include/etl/_iterator/legacy_input_iterator.hpp @@ -14,8 +14,6 @@ namespace etl { -// clang-format off - /// \note Non-standard extension /// \headerfile etl/iterator.hpp /// \ingroup iterator @@ -23,14 +21,13 @@ template concept legacy_input_iterator = etl::legacy_iterator and etl::equality_comparable and requires(Iter i) { typename etl::incrementable_traits::difference_type; typename etl::indirectly_readable_traits::value_type; - // typename etl::common_reference_t&&, typename etl::indirectly_readable_traits::value_type&>; + // typename etl::common_reference_t&&, typename + // etl::indirectly_readable_traits::value_type&>; *i++; // typename etl::common_reference_t::value_type&>; requires etl::signed_integral::difference_type>; }; -// clang-format on - } // namespace etl #endif // TETL_ITERATOR_LEGACY_INPUT_ITERATOR_HPP diff --git a/include/etl/_iterator/weakly_incrementable.hpp b/include/etl/_iterator/weakly_incrementable.hpp index 378efb840..570bc289c 100644 --- a/include/etl/_iterator/weakly_incrementable.hpp +++ b/include/etl/_iterator/weakly_incrementable.hpp @@ -11,7 +11,6 @@ namespace etl { -// clang-format off /// \ingroup iterator template concept weakly_incrementable = etl::movable and requires(Iter i) { @@ -20,7 +19,6 @@ concept weakly_incrementable = etl::movable and requires(Iter i) { { ++i } -> etl::same_as; i++; }; -// clang-format on } // namespace etl