diff --git a/src/SCE/CMakeLists.txt b/src/SCE/CMakeLists.txt index a547a5855a..f704b91883 100644 --- a/src/SCE/CMakeLists.txt +++ b/src/SCE/CMakeLists.txt @@ -8,6 +8,7 @@ add_library(openscap_sce SHARED "${CMAKE_SOURCE_DIR}/src/common/list.c" "${CMAKE_SOURCE_DIR}/src/common/oscap_string.c" "${CMAKE_SOURCE_DIR}/src/common/oscap_buffer.c" + "${CMAKE_SOURCE_DIR}/src/common/oscap_pcre.c" "${CMAKE_SOURCE_DIR}/src/common/util.c" ) target_include_directories(openscap_sce PUBLIC public) diff --git a/src/common/oscap_pcre.c b/src/common/oscap_pcre.c index d4760fb0f3..4d958e6934 100644 --- a/src/common/oscap_pcre.c +++ b/src/common/oscap_pcre.c @@ -28,6 +28,7 @@ #ifdef HAVE_PCRE2 #define PCRE2_CODE_UNIT_WIDTH 8 +#define PCRE2_ERR_BUF_SIZE 127 #include #else #include @@ -85,27 +86,49 @@ static inline oscap_pcre_error_t _pcre_error_to_oscap_pcre(int res) { switch (res) { #ifdef HAVE_PCRE2 - case PCRE2_ERROR_NOMATCH: - return OSCAP_PCRE_ERR_NOMATCH; - case PCRE2_ERROR_PARTIAL: - return OSCAP_PCRE_ERR_PARTIAL; - case PCRE2_ERROR_RECURSIONLIMIT: - return OSCAP_PCRE_ERR_RECURSIONLIMIT; + case PCRE2_ERROR_NOMATCH: + return OSCAP_PCRE_ERR_NOMATCH; + case PCRE2_ERROR_PARTIAL: + return OSCAP_PCRE_ERR_PARTIAL; + case PCRE2_ERROR_UTF8_ERR1: + case PCRE2_ERROR_UTF8_ERR2: + case PCRE2_ERROR_UTF8_ERR3: + case PCRE2_ERROR_UTF8_ERR4: + case PCRE2_ERROR_UTF8_ERR5: + case PCRE2_ERROR_UTF8_ERR6: + case PCRE2_ERROR_UTF8_ERR7: + case PCRE2_ERROR_UTF8_ERR8: + case PCRE2_ERROR_UTF8_ERR9: + case PCRE2_ERROR_UTF8_ERR10: + case PCRE2_ERROR_UTF8_ERR11: + case PCRE2_ERROR_UTF8_ERR12: + case PCRE2_ERROR_UTF8_ERR13: + case PCRE2_ERROR_UTF8_ERR14: + case PCRE2_ERROR_UTF8_ERR15: + case PCRE2_ERROR_UTF8_ERR16: + case PCRE2_ERROR_UTF8_ERR17: + case PCRE2_ERROR_UTF8_ERR18: + case PCRE2_ERROR_UTF8_ERR19: + case PCRE2_ERROR_UTF8_ERR20: + case PCRE2_ERROR_UTF8_ERR21: + return OSCAP_PCRE_ERR_BADUTF8; + case PCRE2_ERROR_RECURSIONLIMIT: + return OSCAP_PCRE_ERR_RECURSIONLIMIT; #else - case PCRE_ERROR_NOMATCH: - return OSCAP_PCRE_ERR_NOMATCH; - case PCRE_ERROR_PARTIAL: - return OSCAP_PCRE_ERR_PARTIAL; - case PCRE_ERROR_BADPARTIAL: - return OSCAP_PCRE_ERR_BADPARTIAL; - case PCRE_ERROR_BADUTF8: - return OSCAP_PCRE_ERR_BADUTF8; - case PCRE_ERROR_RECURSIONLIMIT: - return OSCAP_PCRE_ERR_RECURSIONLIMIT; + case PCRE_ERROR_NOMATCH: + return OSCAP_PCRE_ERR_NOMATCH; + case PCRE_ERROR_PARTIAL: + return OSCAP_PCRE_ERR_PARTIAL; + case PCRE_ERROR_BADPARTIAL: + return OSCAP_PCRE_ERR_BADPARTIAL; + case PCRE_ERROR_BADUTF8: + return OSCAP_PCRE_ERR_BADUTF8; + case PCRE_ERROR_RECURSIONLIMIT: + return OSCAP_PCRE_ERR_RECURSIONLIMIT; #endif - default: - dW("Unknown PCRE/PCRE2 error code: %d", res); - return OSCAP_PCRE_ERR_UNKNOWN; + default: + dW("Unknown PCRE error code: %d", res); + return OSCAP_PCRE_ERR_UNKNOWN; } } @@ -115,20 +138,23 @@ oscap_pcre_t* oscap_pcre_compile(const char *pattern, oscap_pcre_options_t optio oscap_pcre_t *res = malloc(sizeof(oscap_pcre_t)); #ifdef HAVE_PCRE2 int errno; - PCRE2_SIZE erroffs; + PCRE2_SIZE erroffset2; res->re_ctx = NULL; -// dW("Pat: %s", pattern); - res->re = pcre2_compile_8((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, _oscap_pcre_opts_to_pcre(options), &errno, &erroffs, NULL); + dD("pcre2_compile_8: patt=%s", pattern); + res->re = pcre2_compile_8((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, _oscap_pcre_opts_to_pcre(options), &errno, &erroffset2, NULL); if (res->re == NULL) { - PCRE2_UCHAR8 err_msg[1024]; - pcre2_get_error_message_8(errno, err_msg, 1024); - dW("pcre2_compile_8 error: %s", err_msg); - *erroffset = erroffs; - *errptr = strdup((const char*)err_msg); + PCRE2_UCHAR8 errmsg[PCRE2_ERR_BUF_SIZE]; + pcre2_get_error_message_8(errno, errmsg, PCRE2_ERR_BUF_SIZE); + dW("pcre2_compile_8: error (at offset %d): %s", erroffset2, errmsg); + *erroffset = erroffset2; + *errptr = strdup((const char*)errmsg); } #else res->re_extra = NULL; + dD("pcre_compile: patt=%s", pattern); res->re = pcre_compile(pattern, _oscap_pcre_opts_to_pcre(options), errptr, erroffset, NULL); + if (res->re == NULL) + dW("pcre_compile: error (at offset %d): %s", *erroffset, *errptr); #endif if (res->re == NULL) { free(res); @@ -137,16 +163,6 @@ oscap_pcre_t* oscap_pcre_compile(const char *pattern, oscap_pcre_options_t optio return res; } -int oscap_pcre_get_first_byte(oscap_pcre_t *opcre, int *fb) -{ -#ifdef HAVE_PCRE2 - return pcre2_pattern_info_8(opcre->re, PCRE2_INFO_FIRSTCODEUNIT, fb); -// dW("PI: %d", *fb); -#else - return pcre_fullinfo(opcre->re, NULL, PCRE_INFO_FIRSTBYTE, fb); -#endif -} - void oscap_pcre_optimize(oscap_pcre_t *opcre) { #ifdef HAVE_PCRE2 @@ -169,7 +185,6 @@ void oscap_pcre_set_match_limit_recursion(oscap_pcre_t *opcre, unsigned long lim if (opcre->re_ctx == NULL) { opcre->re_ctx = pcre2_match_context_create_8(NULL); } -// dW("LIM: %d", limit); pcre2_set_depth_limit_8(opcre->re_ctx, limit); #else if (opcre->re_extra == NULL) { @@ -187,26 +202,28 @@ int oscap_pcre_exec(const oscap_pcre_t *opcre, const char *subject, { int rc = 0; #ifdef HAVE_PCRE2 - pcre2_match_data_8 *mdata = pcre2_match_data_create_8(ovecsize/3, NULL); -// dW("Subj: %s", subject); + // The ovecsize is multiplied by 3 in the code for compatibility with PCRE1 + int ovecsize2 = ovecsize/3; + pcre2_match_data_8 *mdata = pcre2_match_data_create_8(ovecsize2, NULL); + dD("pcre2_match_8: subj=%s", subject); rc = pcre2_match_8(opcre->re, (PCRE2_SPTR8)subject, length, startoffset, _oscap_pcre_opts_to_pcre(options), mdata, opcre->re_ctx); -// dW("RC: %d", rc); + dD("pcre2_match_8: rc=%d, ", rc); if (rc > PCRE2_ERROR_NOMATCH) { PCRE2_SIZE *ovecp = pcre2_get_ovector_pointer_8(mdata); -// uint32_t ovecp_count = pcre2_get_ovector_count_8(mdata); -// dW("count: %d", ovecp_count); + uint32_t ovecp_count = pcre2_get_ovector_count_8(mdata); + dD("pcre2_match_8: pcre2_get_ovector_count_8=%d", ovecp_count); for (int i = 0; i < rc; i++) { - if (i < ovecsize/3) { + if (i < ovecsize2) { ovector[i*2] = ovecp[i*2]; ovector[i*2+1] = ovecp[i*2+1]; } -// dW(" OVECP[i]: %d", ovecp[i*2]); -// dW(" OVECP[i+1]: %d", ovecp[i*2+1]); } } pcre2_match_data_free_8(mdata); #else + dD("pcre_exec: subj=%s", subject); rc = pcre_exec(opcre->re, opcre->re_extra, subject, length, startoffset, _oscap_pcre_opts_to_pcre(options), ovector, ovecsize); + dD("pcre_exec: rc=%d, ", rc); #endif return rc >= 0 ? rc : _pcre_error_to_oscap_pcre(rc); } @@ -227,3 +244,14 @@ void oscap_pcre_free(oscap_pcre_t *opcre) } } +void oscap_pcre_err_free(char *err) +{ + if (err != NULL) { +#ifdef HAVE_PCRE2 + free(err); +#else + // PCRE1 error messages are static, NOOP. +#endif + } +} + diff --git a/src/common/oscap_pcre.h b/src/common/oscap_pcre.h index c971b70555..01fe76b6dd 100644 --- a/src/common/oscap_pcre.h +++ b/src/common/oscap_pcre.h @@ -58,6 +58,6 @@ void oscap_pcre_set_match_limit_recursion(oscap_pcre_t *opcre, unsigned long lim void oscap_pcre_optimize(oscap_pcre_t *opcre); -int oscap_pcre_get_first_byte(oscap_pcre_t *opcre, int *fb); +void oscap_pcre_err_free(char *err); #endif