diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dac71c9a..d7657837 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,10 +16,10 @@ jobs: run: ./autogen.sh - name: Configure - run: ./configure CPPFLAGS='-Wall -Wextra' --enable-jit --enable-pcre2-16 --enable-pcre2-32 + run: ./configure --enable-jit --enable-pcre2-16 --enable-pcre2-32 - name: Build - run: make -j2 + run: make -j2 CPPFLAGS='-Wall -Wextra -Werror' - name: Test (main test script) run: ./RunTest @@ -50,10 +50,10 @@ jobs: run: ./autogen.sh - name: Configure - run: ./configure CPPFLAGS='-Wall -Wextra' --enable-jit --enable-pcre2-16 --enable-pcre2-32 + run: ./configure --enable-jit --enable-pcre2-16 --enable-pcre2-32 - name: Build - run: make -j2 + run: make -j2 CPPFLAGS='-Wall -Wextra -Werror' - name: Test (main test script) run: ./RunTest @@ -77,7 +77,7 @@ jobs: submodules: true - name: Configure - run: cmake -DPCRE2_SUPPORT_JIT=ON -DPCRE2_BUILD_PCRE2_16=ON -DPCRE2_BUILD_PCRE2_32=ON -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' -DCMAKE_C_FLAGS='-Wall -Wextra' -B build + run: cmake -DPCRE2_SUPPORT_JIT=ON -DPCRE2_BUILD_PCRE2_16=ON -DPCRE2_BUILD_PCRE2_32=ON -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' -DCMAKE_C_FLAGS='-Wall -Wextra' -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -B build - name: Build run: cmake --build build @@ -112,7 +112,7 @@ jobs: submodules: true - name: Configure - run: cmake -DPCRE2_SUPPORT_JIT=ON -DPCRE2_BUILD_PCRE2_16=ON -DPCRE2_BUILD_PCRE2_32=ON -B build -A Win32 + run: cmake -DPCRE2_SUPPORT_JIT=ON -DPCRE2_BUILD_PCRE2_16=ON -DPCRE2_BUILD_PCRE2_32=ON -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -B build -A Win32 - name: Build run: cmake --build build diff --git a/CMakeLists.txt b/CMakeLists.txt index d4d80f15..ec8f7067 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -145,8 +145,6 @@ INCLUDE(CheckIncludeFile) INCLUDE(CheckTypeSize) INCLUDE(GNUInstallDirs) # for CMAKE_INSTALL_LIBDIR -CHECK_INCLUDE_FILE(stdio.h HAVE_STDIO_H) -CHECK_INCLUDE_FILE(stdlib.h HAVE_STDLIB_H) CHECK_INCLUDE_FILE(assert.h HAVE_ASSERT_H) CHECK_INCLUDE_FILE(dirent.h HAVE_DIRENT_H) CHECK_INCLUDE_FILE(sys/stat.h HAVE_SYS_STAT_H) @@ -1164,6 +1162,7 @@ IF(PCRE2_SHOW_REPORT) MESSAGE(STATUS " Build 8 bit PCRE2 library ....... : ${PCRE2_BUILD_PCRE2_8}") MESSAGE(STATUS " Build 16 bit PCRE2 library ...... : ${PCRE2_BUILD_PCRE2_16}") MESSAGE(STATUS " Build 32 bit PCRE2 library ...... : ${PCRE2_BUILD_PCRE2_32}") + MESSAGE(STATUS " Include debugging code ...........: ${PCRE2_DEBUG}") MESSAGE(STATUS " Enable JIT compiling support .... : ${PCRE2_SUPPORT_JIT}") MESSAGE(STATUS " Use SELinux allocator in JIT .... : ${PCRE2_SUPPORT_JIT_SEALLOC}") MESSAGE(STATUS " Enable Unicode support .......... : ${PCRE2_SUPPORT_UNICODE}") diff --git a/config-cmake.h.in b/config-cmake.h.in index fe00ca9a..bc413af6 100644 --- a/config-cmake.h.in +++ b/config-cmake.h.in @@ -6,8 +6,6 @@ #cmakedefine HAVE_BUILTIN_UNREACHABLE 1 #cmakedefine HAVE_ATTRIBUTE_UNINITIALIZED 1 #cmakedefine HAVE_DIRENT_H 1 -#cmakedefine HAVE_STDIO_H 1 -#cmakedefine HAVE_STDLIB_H 1 #cmakedefine HAVE_SYS_STAT_H 1 #cmakedefine HAVE_SYS_TYPES_H 1 #cmakedefine HAVE_UNISTD_H 1 diff --git a/maint/README b/maint/README index 2d532310..119b0ffc 100644 --- a/maint/README +++ b/maint/README @@ -187,11 +187,10 @@ new release. . I used to test new releases myself on a number of different operating systems. For example, on Solaris it is helpful to test using Sun's cc - compiler as a change from gcc. Adding -xarch=v9 to the cc options does a - 64-bit test, but it also needs -S 64 for pcre2test to increase the stack size - for test 2. Since I retired I can no longer do much of this. There are - automated tests under Ubuntu, Alpine, and Windows that are now set up as - GitHub actions. Check that they are running clean. + compiler as a change from gcc. Adding -m64 to the cc options does a 64-bit + build. Since I retired I can no longer do much of this. There are automated + tests under Ubuntu, Alpine, macOS and Windows that are now set up as GitHub + actions. Check that they are running clean. . The buildbots at http://buildfarm.opencsw.org/ do some automated testing of PCRE2 and should also be checked before putting out a release. (June 2024: diff --git a/src/pcre2_auto_possess.c b/src/pcre2_auto_possess.c index 66788cb7..81d31082 100644 --- a/src/pcre2_auto_possess.c +++ b/src/pcre2_auto_possess.c @@ -199,7 +199,7 @@ static BOOL check_char_prop(uint32_t c, unsigned int ptype, unsigned int pdata, BOOL negated) { -BOOL ok; +BOOL ok, rc; const uint32_t *p; const ucd_record *prop = GET_UCD(c); @@ -240,13 +240,13 @@ switch(ptype) { HSPACE_CASES: VSPACE_CASES: - return negated; + rc = negated; + break; default: - return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == negated; + rc = (PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == negated; } - PCRE2_UNREACHABLE(); /* Control never reaches here */ - break; + return rc; case PT_WORD: return (PRIV(ucp_gentype)[prop->chartype] == ucp_L || @@ -260,7 +260,7 @@ switch(ptype) if (c < *p) return !negated; if (c == *p++) return negated; } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ break; /* Haven't yet thought these through. */ @@ -456,6 +456,7 @@ switch(c) { /* Early return if there is not enough space. This should never happen, since all clists are shorter than 5 character now. */ + PCRE2_DEBUG_UNREACHABLE(); list[2] = code[0]; list[3] = code[1]; return code; @@ -1121,7 +1122,7 @@ for(;;) if (list[1] == 0) return TRUE; } - PCRE2_UNREACHABLE(); /* Control never reaches here */ +PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ } diff --git a/src/pcre2_compile.c b/src/pcre2_compile.c index e5d76404..a1a1cd71 100644 --- a/src/pcre2_compile.c +++ b/src/pcre2_compile.c @@ -1848,8 +1848,9 @@ else /* As we know we are at a digit, the only possible error from read_number() is a number that is too large to be a group number. Because that number might be still valid if read as an octal, errorcodeptr is not - set on failure and therefore a bogus value of INT_MAX is set instead that - will be used later to properly set the error, if not falling through. */ + set on failure and therefore a sentinel value of INT_MAX is used instead + of the original value, and will be used later to properly set the error, + if not falling through. */ if (!read_number(&ptr, ptrend, -1, MAX_GROUP_NUMBER, 0, &s, errorcodeptr)) s = INT_MAX; @@ -1860,10 +1861,14 @@ else if (s < 10 || c >= CHAR_8 || (unsigned)s <= bracount) { /* s > MAX_GROUP_NUMBER should not be possible because of read_number(), - but we keep it just to be safe and because it will also catch the bogus - value set on failure of that function. */ + but we keep it just to be safe and because it will also catch the + sentinel value that was set on failure by that function. */ - if ((unsigned)s > MAX_GROUP_NUMBER) *errorcodeptr = ERR61; + if ((unsigned)s > MAX_GROUP_NUMBER) + { + PCRE2_ASSERT(s == INT_MAX); + *errorcodeptr = ERR61; + } else escape = -s; /* Indicates a back reference */ break; } @@ -5245,7 +5250,7 @@ for (;;) } } - PCRE2_UNREACHABLE(); /* Control never reaches here */ +PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ } @@ -5525,6 +5530,7 @@ have duplicate names. Give an internal error. */ if (i >= cb->names_found) { + PCRE2_DEBUG_UNREACHABLE(); *errorcodeptr = ERR53; cb->erroroffset = name - cb->start_pattern; return FALSE; @@ -8452,7 +8458,7 @@ for (;; pptr++) } /* End of big switch */ } /* End of big loop */ - PCRE2_UNREACHABLE(); /* Control never reaches here */ +PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ } @@ -8758,7 +8764,7 @@ for (;;) pptr++; } - PCRE2_UNREACHABLE(); /* Control never reaches here */ +PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ } @@ -9382,6 +9388,7 @@ for (;; pptr++) /* This should never occur. */ case META_END: + PCRE2_DEBUG_UNREACHABLE(); return NULL; /* The data for these items is variable in length. */ @@ -9446,7 +9453,7 @@ for (;; pptr++) pptr += meta_extra_lengths[meta]; } - PCRE2_UNREACHABLE(); /* Control never reaches here */ +PCRE2_UNREACHABLE(); /* Control never reaches here */ } @@ -10508,7 +10515,8 @@ if ((options & PCRE2_LITERAL) == 0) optim_flags &= ~(p->value); /* For backward compatibility the three original VERBs to disable - optimizations need to also update the corresponding external option. */ + optimizations need to also update the corresponding bit in the + external options. */ switch(p->value) { @@ -10528,7 +10536,9 @@ if ((options & PCRE2_LITERAL) == 0) break; default: - PCRE2_UNREACHABLE(); + /* Fail assertion if a new type was added and someone forgot to + update this switch */ + PCRE2_DEBUG_UNREACHABLE(); } break; /* Out of the table scan loop */ } diff --git a/src/pcre2_convert.c b/src/pcre2_convert.c index 571b36c5..c11b4fad 100644 --- a/src/pcre2_convert.c +++ b/src/pcre2_convert.c @@ -1137,8 +1137,7 @@ for (int i = 0; i < 2; i++) break; default: - *bufflenptr = 0; /* Error offset */ - return PCRE2_ERROR_INTERNAL; + goto EXIT; } if (rc != 0 || /* Error */ @@ -1158,10 +1157,12 @@ for (int i = 0; i < 2; i++) use_length = *bufflenptr + 1; } -/* Normally, we should exit this function in the previous loop, but we -can't return an API call without a meaningful value, so if something -went terribly wrong, we then will just report it as an intenal error */ +/* Something went terribly wrong. Trigger and assert and return an error */ +PCRE2_DEBUG_UNREACHABLE(); +EXIT: + +*bufflenptr = 0; /* Error offset */ return PCRE2_ERROR_INTERNAL; } diff --git a/src/pcre2_dfa_match.c b/src/pcre2_dfa_match.c index d1d33ad5..f2e98ed7 100644 --- a/src/pcre2_dfa_match.c +++ b/src/pcre2_dfa_match.c @@ -3570,7 +3570,9 @@ switch(re->newline_convention) mb->nltype = NLTYPE_ANYCRLF; break; - default: return PCRE2_ERROR_INTERNAL; + default: + PCRE2_DEBUG_UNREACHABLE(); + return PCRE2_ERROR_INTERNAL; } /* Check a UTF string for validity if required. For 8-bit and 16-bit strings, diff --git a/src/pcre2_match.c b/src/pcre2_match.c index eb748e9f..899489d0 100644 --- a/src/pcre2_match.c +++ b/src/pcre2_match.c @@ -813,7 +813,11 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, offset = Flast_group_offset; for(;;) { - if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL; + if (offset == PCRE2_UNSET) + { + PCRE2_DEBUG_UNREACHABLE(); + return PCRE2_ERROR_INTERNAL; + } N = (heapframe *)((char *)match_data->heapframes + offset); P = (heapframe *)((char *)N - frame_size); if (N->group_frame_type == (GF_CAPTURE | number)) break; @@ -852,7 +856,11 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, offset = Flast_group_offset; for(;;) { - if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL; + if (offset == PCRE2_UNSET) + { + PCRE2_DEBUG_UNREACHABLE(); + return PCRE2_ERROR_INTERNAL; + } N = (heapframe *)((char *)match_data->heapframes + offset); P = (heapframe *)((char *)N - frame_size); if (GF_IDMASK(N->group_frame_type) == GF_RECURSE) break; @@ -2607,6 +2615,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, /* This should never occur */ default: + PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } @@ -2970,6 +2979,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, /* This should not occur */ default: + PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } } @@ -3245,6 +3255,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; default: + PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } /* End switch(Lctype) */ @@ -3497,6 +3508,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; default: + PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } } @@ -3531,7 +3543,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, GETCHARINCTEST(fc, Feptr); if (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_LAMP: @@ -3553,7 +3564,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, chartype == ucp_Lt) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_GC: @@ -3571,7 +3581,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if ((UCD_CATEGORY(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_PC: @@ -3589,7 +3598,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if ((UCD_CHARTYPE(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_SC: @@ -3607,7 +3615,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if ((UCD_SCRIPT(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_SCX: @@ -3630,7 +3637,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if (ok == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_ALNUM: @@ -3650,7 +3656,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if ((category == ucp_L || category == ucp_N) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ /* Perl space used to exclude VT, but from Perl 5.18 it is included, @@ -3683,7 +3688,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; } } - PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_WORD: @@ -3707,7 +3711,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, chartype == ucp_Pc) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_CLIST: @@ -3745,7 +3748,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, } } } - PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_UCNC: @@ -3765,7 +3767,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, fc >= 0xe000) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_BIDICL: @@ -3783,7 +3784,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if ((UCD_BIDICLASS(fc) == Lpropvalue) == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ case PT_BOOL: @@ -3806,11 +3806,11 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if (ok == (Lctype == OP_NOTPROP)) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ /* This should never occur */ default: + PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } } @@ -3965,6 +3965,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; default: + PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } } @@ -4109,12 +4110,13 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; default: + PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } } } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ } /* If maximizing, it is worth using inline code for speed, doing the type @@ -4392,6 +4394,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; default: + PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } @@ -4710,6 +4713,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; default: + PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } @@ -4967,6 +4971,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, break; default: + PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } @@ -5126,6 +5131,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, } Feptr += slength; } + PCRE2_UNREACHABLE(); /* Control never reaches here */ } @@ -5201,7 +5207,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ #undef Lcaseless #undef Lmin @@ -5425,7 +5431,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, Fecode += GET(Fecode, 1); if (*Fecode != OP_ALT) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ #undef Lframe_type @@ -5511,7 +5516,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, Lstart_branch = next_ecode; if (*Lstart_branch != OP_ALT) RRETURN(MATCH_NOMATCH); } - PCRE2_UNREACHABLE(); /* Control never reaches here */ #undef Lframe_type @@ -6026,7 +6030,6 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, if (utf) { FORWARDCHARTEST(Feptr, mb->end_subject); } #endif } - PCRE2_UNREACHABLE(); /* Control never reaches here */ #undef Lmin @@ -6119,7 +6122,11 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, /* It is the end of whole-pattern recursion. */ offset = Flast_group_offset; - if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL; + if (offset == PCRE2_UNSET) + { + PCRE2_DEBUG_UNREACHABLE(); + return PCRE2_ERROR_INTERNAL; + } N = (heapframe *)((char *)match_data->heapframes + offset); P = (heapframe *)((char *)N - frame_size); Flast_group_offset = P->last_group_offset; @@ -6616,6 +6623,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, something seriously wrong in the code above or the OP_xxx definitions. */ default: + PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } @@ -6625,8 +6633,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode, } /* End of main loop */ - PCRE2_UNREACHABLE(); /* Control never reaches here */ - +PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ /* ========================================================================= */ /* The RRETURN() macro jumps here. The number that is saved in Freturn_id @@ -6666,6 +6673,7 @@ switch (Freturn_id) #endif default: + PCRE2_DEBUG_UNREACHABLE(); return PCRE2_ERROR_INTERNAL; } #undef LBL @@ -7180,7 +7188,9 @@ switch(re->newline_convention) mb->nltype = NLTYPE_ANYCRLF; break; - default: return PCRE2_ERROR_INTERNAL; + default: + PCRE2_DEBUG_UNREACHABLE(); + return PCRE2_ERROR_INTERNAL; } /* The backtracking frames have fixed data at the front, and a PCRE2_SIZE diff --git a/src/pcre2_study.c b/src/pcre2_study.c index f7da869e..352dd6df 100644 --- a/src/pcre2_study.c +++ b/src/pcre2_study.c @@ -755,11 +755,12 @@ for (;;) new ones get added they are properly considered. */ default: + PCRE2_DEBUG_UNREACHABLE(); return -3; } } - PCRE2_UNREACHABLE(); /* Control never reaches here */ +PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */ } @@ -1633,6 +1634,7 @@ do goto HANDLE_CLASSMAP; default: + PCRE2_DEBUG_UNREACHABLE(); return SSB_UNKNOWN; /* Internal error, should not occur */ } } @@ -1783,7 +1785,11 @@ if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0) { int depth = 0; int rc = set_start_bits(re, code, utf, ucp, &depth); - if (rc == SSB_UNKNOWN) return 1; + if (rc == SSB_UNKNOWN) + { + PCRE2_DEBUG_UNREACHABLE(); + return 1; + } /* If a list of starting code units was set up, scan the list to see if only one or two were listed. Having only one listed is rare because usually a @@ -1899,9 +1905,11 @@ if ((re->flags & (PCRE2_MATCH_EMPTY|PCRE2_HASACCEPT)) == 0 && break; /* Leave minlength unchanged (will be zero) */ case -2: + PCRE2_DEBUG_UNREACHABLE(); return 2; /* missing capturing bracket */ case -3: + PCRE2_DEBUG_UNREACHABLE(); return 3; /* unrecognized opcode */ default: diff --git a/src/pcre2_util.h b/src/pcre2_util.h index 6eeaa7d9..0900e1e5 100644 --- a/src/pcre2_util.h +++ b/src/pcre2_util.h @@ -43,27 +43,74 @@ POSSIBILITY OF SUCH DAMAGE. /* Assertion macros */ -#ifdef HAVE_BUILTIN_UNREACHABLE -#define PCRE2_UNREACHABLE() __builtin_unreachable() -#elif HAVE_BUILTIN_ASSUME -#define PCRE2_UNREACHABLE() __assume(0) -#else -#define PCRE2_UNREACHABLE() do {} while(0) -#endif - #ifdef PCRE2_DEBUG + +/* PCRE2_ASSERT(x) can be used to inject an assert() for conditions +that the code below doesn't support. It is a NOP for non debug builds +but in debug builds will print information about the location of the +code where it triggered and crash. + +it is meant to work like assert(), and therefore the expressiom used +should indicate what the expected state is, and shouldn't have any +sideeffects. */ + #if defined(HAVE_ASSERT_H) && !defined(NDEBUG) #include #define PCRE2_ASSERT(x) assert(x) -#elif defined(HAVE_STDLIB_H) && defined(HAVE_STDIO_H) -#define PCRE2_ASSERT(x) do { if (!(x)) { fprintf(stderr, "Assertion failed at " __FILE__ ":%d\n", __LINE__); abort(); }} while(0) +#else +#define PCRE2_ASSERT(x) do \ +{ \ + if (!(x)) \ + { \ + fprintf(stderr, "Assertion failed at " __FILE__ ":%d\n", __LINE__); \ + abort(); \ + } \ +} while(0) +#endif + +/* PCRE2_UNREACHABLE() can be used to mark locations on the code that +shouldn't be reached. In non debug builds is defined as a hint for +the compiler to eliminate any code after it, so it is useful also for +performance reasons, but should be used with care because if it is +ever reached will trigger Undefined Behaviour and if you are lucky a +crash. In debug builds will report the location where it was trigered +and crash. */ + +#define PCRE2_UNREACHABLE() do \ +{ \ +fprintf(stderr, "Execution reached unexpected point at " __FILE__ \ + ":%d\n", __LINE__); \ +abort(); \ +} while(0) + +/* PCRE2_DEBUG_UNREACHABLE() is a debug only version of the previous +macro. It is meant to be used in places where the code is handling +an error situation in code that shouldn't be reached, but that has +some sort of fallback code to normally handle the error. When in +doubt you should use this instead of the previous macro. */ + +#define PCRE2_DEBUG_UNREACHABLE() PCRE2_UNREACHABLE() + +#endif /* PCRE2_DEBUG */ + +#ifndef PCRE2_DEBUG_UNREACHABLE +#define PCRE2_DEBUG_UNREACHABLE() do {} while(0) #endif + +#ifndef PCRE2_UNREACHABLE +#ifdef HAVE_BUILTIN_UNREACHABLE +#define PCRE2_UNREACHABLE() __builtin_unreachable() +#elif defined(HAVE_BUILTIN_ASSUME) +#define PCRE2_UNREACHABLE() __assume(0) +#else +#define PCRE2_UNREACHABLE() do {} while(0) #endif +#endif /* !PCRE2_UNREACHABLE */ #ifndef PCRE2_ASSERT #define PCRE2_ASSERT(x) do {} while(0) #endif -#endif /* PCRE2_UTIL_H_IDEMPOTENT_GUARD */ +#endif /* PCRE2_UTIL_H_IDEMPOTENT_GUARD */ /* End of pcre2_util.h */ diff --git a/src/pcre2_xclass.c b/src/pcre2_xclass.c index 93e0ab29..28091828 100644 --- a/src/pcre2_xclass.c +++ b/src/pcre2_xclass.c @@ -298,6 +298,7 @@ while ((t = *data++) != XCL_END) default. */ default: + PCRE2_DEBUG_UNREACHABLE(); return FALSE; } diff --git a/src/pcre2grep.c b/src/pcre2grep.c index b4c657a6..a50b2ccb 100644 --- a/src/pcre2grep.c +++ b/src/pcre2grep.c @@ -898,12 +898,12 @@ readdirectory(directory_type *dir) for (;;) { struct dirent *dent = readdir(dir); - if (dent == NULL) return NULL; + if (dent == NULL) break; if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0) return dent->d_name; } - PCRE2_UNREACHABLE(); /* Control never reaches here */ +return NULL; } static void @@ -1696,9 +1696,9 @@ switch(endlinetype) { p -= 2; while (p > startptr && p[-1] != '\n') p--; - if (p <= startptr + 1 || p[-2] == '\r') return p; + if (p <= startptr + 1 || p[-2] == '\r') break; } - PCRE2_UNREACHABLE(); /* Control never reaches here */ + return p; case PCRE2_NEWLINE_ANY: case PCRE2_NEWLINE_ANYCRLF: @@ -2487,10 +2487,13 @@ while (length > 0) break; /* LCOV_EXCL_START */ - default: /* Even though this should not occur, the string having */ - case DDE_ERROR: /* been checked above, we need to include the free() */ - free(args); /* calls so that source checkers do not complain. */ + default: + /* Even though this should not occur, the string having been checked above, + * we need to include the free() calls so that source checkers do not complain. */ + case DDE_ERROR: + free(args); free(argsvector); + PCRE2_DEBUG_UNREACHABLE(); return 0; /* LCOV_EXCL_STOP */ } diff --git a/src/pcre2test.c b/src/pcre2test.c index 852f1b84..6b857b96 100644 --- a/src/pcre2test.c +++ b/src/pcre2test.c @@ -3600,7 +3600,7 @@ for (;;) } } - PCRE2_UNREACHABLE(); /* Control never reaches here */ +PCRE2_UNREACHABLE(); /* Control never reaches here */ }