diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 61dbb63e7..70deee110 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,7 @@ # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) name: CI + on: push: branches: @@ -13,6 +14,10 @@ on: pull_request: release: types: [published, created, edited] + +env: + UBSAN_OPTIONS: print_stacktrace=1 + jobs: ubuntu-jammy: runs-on: ubuntu-22.04 @@ -60,7 +65,7 @@ jobs: run: ../../../b2 print_config_info toolset=$TOOLSET working-directory: ../boost-root/libs/config/test - name: Test - run: ../../../b2 toolset=$TOOLSET + run: ../../../b2 toolset=$TOOLSET variant=debug,release ${{ startsWith(matrix.compiler, 'g++-13') && 'address-sanitizer=norecover undefined-sanitizer=norecover' || '' }} working-directory: ../boost-root/libs/regex/test ubuntu-jammy-standalone: runs-on: ubuntu-22.04 @@ -135,6 +140,54 @@ jobs: - name: Test run: ../../../b2 toolset=$TOOLSET define=CI_SUPPRESS_KNOWN_ISSUES define=SLOW_COMPILER working-directory: ../boost-root/libs/regex/test + ubuntu-noble-clang: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + compiler: [ clang++-16, clang++-17, clang++-18 ] + standard: [ c++11, c++14, c++17, c++20 ] + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: '0' + - uses: mstachniuk/ci-skip@v1 + with: + commit-filter: '[skip ci];[ci skip];[CI SKIP];[SKIP CI];***CI SKIP***;***SKIP CI***;[windows];[Windows];[WINDOWS];[apple];[Apple];[APPLE]' + commit-filter-separator: ';' + fail-fast: true + - name: Set TOOLSET + run: echo ${{ matrix.compiler }} | awk '/^g/ { print "TOOLSET=gcc" } /^clang/ { print "TOOLSET=clang" }' >> $GITHUB_ENV + - name: Add repository + run: sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test" + - name: Install packages + run: sudo apt install clang-16 clang-17 clang-18 + - name: Checkout main boost + run: git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root + - name: Update tools/boostdep + run: git submodule update --init tools/boostdep + working-directory: ../boost-root + - name: Copy files + run: cp -r $GITHUB_WORKSPACE/* libs/regex + working-directory: ../boost-root + - name: Install deps + run: python tools/boostdep/depinst/depinst.py -I example -g "--jobs 3" regex + working-directory: ../boost-root + - name: Bootstrap + run: ./bootstrap.sh + working-directory: ../boost-root + - name: Generate headers + run: ./b2 headers + working-directory: ../boost-root + - name: Generate user config + run: 'echo "using $TOOLSET : : ${{ matrix.compiler }} : -std=${{ matrix.standard }} ;" > ~/user-config.jam' + working-directory: ../boost-root + - name: Config info + run: ../../../b2 print_config_info toolset=$TOOLSET + working-directory: ../boost-root/libs/config/test + - name: Test + run: ../../../b2 toolset=$TOOLSET define=CI_SUPPRESS_KNOWN_ISSUES define=SLOW_COMPILER variant=debug,release ${{ startsWith(matrix.compiler, 'clang++-18') && 'address-sanitizer=norecover undefined-sanitizer=norecover' || '' }} + working-directory: ../boost-root/libs/regex/test macos: runs-on: macos-latest strategy: @@ -175,7 +228,7 @@ jobs: run: ./config_info_travis working-directory: ../boost-root/libs/config/test - name: Test - run: ../../../b2 toolset=${{ matrix.toolset }} cxxstd=${{ matrix.standard }} + run: ../../../b2 variant=debug,release toolset=${{ matrix.toolset }} cxxstd=${{ matrix.standard }} working-directory: ../boost-root/libs/regex/test windows_gcc: runs-on: windows-2019 diff --git a/include/boost/regex/v5/basic_regex_creator.hpp b/include/boost/regex/v5/basic_regex_creator.hpp index 7e4ffcaca..65e0e9952 100644 --- a/include/boost/regex/v5/basic_regex_creator.hpp +++ b/include/boost/regex/v5/basic_regex_creator.hpp @@ -250,7 +250,7 @@ class basic_regex_creator void fixup_pointers(re_syntax_base* state); void fixup_recursions(re_syntax_base* state); void create_startmaps(re_syntax_base* state); - int calculate_backstep(re_syntax_base* state); + int calculate_backstep(re_syntax_base* state, int recurse_count = 0); void create_startmap(re_syntax_base* state, unsigned char* l_map, unsigned int* pnull, unsigned char mask, unsigned recursion_count = 0); unsigned get_restart_type(re_syntax_base* state); void set_all_masks(unsigned char* bits, unsigned char); @@ -971,8 +971,12 @@ void basic_regex_creator::create_startmaps(re_syntax_base* state) } template -int basic_regex_creator::calculate_backstep(re_syntax_base* state) +int basic_regex_creator::calculate_backstep(re_syntax_base* state, int recurse_count) { + if (recurse_count >= 2000) { + return -1; + } + typedef typename traits::char_class_type m_type; int result = 0; while(state) @@ -1051,8 +1055,8 @@ int basic_regex_creator::calculate_backstep(re_syntax_base* state continue; case syntax_element_alt: { - int r1 = calculate_backstep(state->next.p); - int r2 = calculate_backstep(static_cast(state)->alt.p); + int r1 = calculate_backstep(state->next.p, recurse_count + 1); + int r2 = calculate_backstep(static_cast(state)->alt.p, recurse_count + 1); if((r1 < 0) || (r1 != r2)) return -1; return result + r1; diff --git a/include/boost/regex/v5/match_flags.hpp b/include/boost/regex/v5/match_flags.hpp index 6ff236b04..e08a49484 100644 --- a/include/boost/regex/v5/match_flags.hpp +++ b/include/boost/regex/v5/match_flags.hpp @@ -99,7 +99,7 @@ inline match_flags operator|(match_flags m1, match_flags m2) inline match_flags operator^(match_flags m1, match_flags m2) { return static_cast(static_cast(m1) ^ static_cast(m2)); } inline match_flags operator~(match_flags m1) -{ return static_cast(~static_cast(m1)); } +{ return static_cast(~static_cast(m1) & static_cast(match_not_any)); } inline match_flags& operator&=(match_flags& m1, match_flags m2) { m1 = m1&m2; return m1; } inline match_flags& operator|=(match_flags& m1, match_flags m2) diff --git a/include/boost/regex/v5/perl_matcher_non_recursive.hpp b/include/boost/regex/v5/perl_matcher_non_recursive.hpp index 874004521..5a1c3f4c5 100644 --- a/include/boost/regex/v5/perl_matcher_non_recursive.hpp +++ b/include/boost/regex/v5/perl_matcher_non_recursive.hpp @@ -237,8 +237,8 @@ void perl_matcher::extend_stack() saved_state* backup_state; stack_base = static_cast(get_mem_block()); backup_state = reinterpret_cast(reinterpret_cast(stack_base)+BOOST_REGEX_BLOCKSIZE); - saved_extra_block* block = static_cast(backup_state); - --block; + saved_extra_block* block = reinterpret_cast( + reinterpret_cast(backup_state) - sizeof(saved_extra_block)); (void) new (block) saved_extra_block(m_stack_base, m_backup_state); m_stack_base = stack_base; m_backup_state = block; diff --git a/test/de_fuzz/Jamfile.v2 b/test/de_fuzz/Jamfile.v2 index 4306ba7c1..01dfa7546 100644 --- a/test/de_fuzz/Jamfile.v2 +++ b/test/de_fuzz/Jamfile.v2 @@ -5,33 +5,31 @@ import testing ; -lib Fuzzer : : . ; - -run narrow.cpp [ glob ../../src/*.cpp ] Fuzzer +run narrow.cpp [ glob ../../src/*.cpp ] : # additional args - -dict=dictionary.txt -workers=3 corpus -runs=5000 + -dict=dictionary.txt -jobs=3 corpus -runs=5000 : # test-files : # requirements - clang -fsanitize-coverage=trace-pc-guard - -fsanitize=address -fsanitize=undefined + clang + -fsanitize=fuzzer -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=undefined -fno-optimize-sibling-calls -fno-omit-frame-pointer ../../../.. - -fsanitize=address -fsanitize=undefined + -fsanitize=fuzzer -fsanitize=address -fsanitize=undefined debug ; -run wide.cpp [ glob ../../src/*.cpp ] Fuzzer +run wide.cpp [ glob ../../src/*.cpp ] : # additional args - -dict=dictionary.txt -workers=3 corpus -runs=5000 + -dict=dictionary.txt -jobs=3 corpus -runs=5000 : # test-files : # requirements - clang -fsanitize-coverage=trace-pc-guard - -fsanitize=address -fsanitize=undefined + clang + -fsanitize=fuzzer -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=undefined -fno-optimize-sibling-calls -fno-omit-frame-pointer ../../../.. - -fsanitize=address -fsanitize=undefined + -fsanitize=fuzzer -fsanitize=address -fsanitize=undefined debug ; diff --git a/test/de_fuzz/corpus/corpus_1731 b/test/de_fuzz/corpus/corpus_1731 new file mode 100644 index 000000000..5e684ea2a Binary files /dev/null and b/test/de_fuzz/corpus/corpus_1731 differ