Skip to content

Commit

Permalink
Add PCRE2 library #3
Browse files Browse the repository at this point in the history
Move the oscap_get_substring into the oscap_pcre.c module
and rename it into oscap_pcre_get_substring.

The function imposes implicit dependencies on PCRE/PCRE2 symbols
even for utils.c users that won't use PCRE at all (SCE library).
  • Loading branch information
evgenyz committed Sep 4, 2023
1 parent 193487c commit 5a8c2ba
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 87 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@ endif()

if (${CMAKE_C_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pipe -W -Wall -Wnonnull -Wshadow -Wformat -Wundef -Wno-unused-parameter -Wmissing-prototypes -Wno-unknown-pragmas -Wno-int-conversion -Werror=implicit-function-declaration -D_GNU_SOURCE -std=c99")
add_link_options(-Wl,-z,now)
endif()
if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
add_link_options(-lkvm -lm -lprocstat)
Expand Down
2 changes: 1 addition & 1 deletion src/OVAL/probes/independent/textfilecontent54_probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ static int process_file(const char *prefix, const char *path, const char *file,
want_instance = 0;

SEXP_free(next_inst);
substr_cnt = oscap_get_substrings(buf, &ofs, pfd->compiled_regex, want_instance, &substrs);
substr_cnt = oscap_pcre_get_substrings(buf, &ofs, pfd->compiled_regex, want_instance, &substrs);

if (substr_cnt < 0) {
SEXP_t *msg;
Expand Down
2 changes: 1 addition & 1 deletion src/OVAL/probes/independent/textfilecontent_probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ static int process_file(const char *prefix, const char *path, const char *filena
int ofs = 0;

while (fgets(line, sizeof(line), fp) != NULL) {
substr_cnt = oscap_get_substrings(line, &ofs, re, 1, &substrs);
substr_cnt = oscap_pcre_get_substrings(line, &ofs, re, 1, &substrs);
if (substr_cnt > 0) {
int k;
SEXP_t *item;
Expand Down
71 changes: 71 additions & 0 deletions src/common/oscap_pcre.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

#include <memory.h>

#define OSCAP_PCRE_EXEC_RECURSION_LIMIT_DEFAULT 3500

#ifdef HAVE_PCRE2
#define PCRE2_CODE_UNIT_WIDTH 8
#define PCRE2_ERR_BUF_SIZE 127
Expand Down Expand Up @@ -244,6 +246,75 @@ void oscap_pcre_free(oscap_pcre_t *opcre)
}
}

int oscap_pcre_get_substrings(char *str, int *ofs, oscap_pcre_t *re, int want_substrs, char ***substrings) {
int i, ret, rc;
int ovector[60], ovector_len = sizeof (ovector) / sizeof (ovector[0]);
char **substrs;

// todo: max match count check

for (i = 0; i < ovector_len; ++i) {
ovector[i] = -1;
}

unsigned long limit = OSCAP_PCRE_EXEC_RECURSION_LIMIT_DEFAULT;
char *limit_str = getenv("OSCAP_PCRE_EXEC_RECURSION_LIMIT");
if (limit_str != NULL)
if (sscanf(limit_str, "%lu", &limit) <= 0)
dW("Unable to parse OSCAP_PCRE_EXEC_RECURSION_LIMIT value");
oscap_pcre_set_match_limit_recursion(re, limit);
size_t str_len = strlen(str);
#if defined(OS_SOLARIS)
rc = oscap_pcre_exec(re, str, str_len, *ofs, OSCAP_PCRE_OPTS_NO_UTF8_CHECK, ovector, ovector_len);
#else
rc = oscap_pcre_exec(re, str, str_len, *ofs, 0, ovector, ovector_len);
#endif

if (rc < OSCAP_PCRE_ERR_NOMATCH) {
if (str_len < 100)
dE("Function oscap_pcre_exec() failed to match a regular expression with return code %d on string '%s'.", rc, str);
else
dE("Function oscap_pcre_exec() failed to match a regular expression with return code %d on string '%.100s' (truncated, showing first 100 characters).", rc, str);
return rc;
} else if (rc == OSCAP_PCRE_ERR_NOMATCH) {
/* no match */
return 0;
}

*ofs = (*ofs == ovector[1]) ? ovector[1] + 1 : ovector[1];

if (!want_substrs) {
/* just report successful match */
return 1;
}

ret = 0;
if (rc == 0) {
/* vector too small */
// todo: report partial results
rc = ovector_len / 3;
}

substrs = malloc(rc * sizeof (char *));
for (i = 0; i < rc; ++i) {
int len;
char *buf;

if (ovector[2 * i] == -1) {
continue;
}
len = ovector[2 * i + 1] - ovector[2 * i];
buf = malloc(len + 1);
memcpy(buf, str + ovector[2 * i], len);
buf[len] = '\0';
substrs[ret] = buf;
++ret;
}

*substrings = substrs;

return ret;
}

void oscap_pcre_err_free(char *err)
{
Expand Down
12 changes: 12 additions & 0 deletions src/common/oscap_pcre.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,18 @@ void oscap_pcre_set_match_limit_recursion(oscap_pcre_t *opcre, unsigned long lim
*/
void oscap_pcre_optimize(oscap_pcre_t *opcre);

/**
* Match a regular expression and return substrings.
* Caller is responsible for freeing the returned array.
* @param str subject string
* @param ofs starting offset in str
* @param re compiled regular expression
* @param want_substrs if non-zero, substrings will be returned
* @param substrings contains returned substrings
* @return count of matched substrings, 0 if no match
* negative value on failure
*/
int oscap_pcre_get_substrings(char *str, int *ofs, oscap_pcre_t *re, int want_substrs, char ***substrings);

/**
* Free the error message returned by oscap_pcre_compile. DON'T USE REGULAR free()!
Expand Down
71 changes: 0 additions & 71 deletions src/common/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
#endif

#define PATH_SEPARATOR '/'
#define OSCAP_PCRE_EXEC_RECURSION_LIMIT_DEFAULT 3500

int oscap_string_to_enum(const struct oscap_string_map *map, const char *str)
{
Expand Down Expand Up @@ -361,76 +360,6 @@ char *oscap_path_join(const char *path1, const char *path2)
return joined_path;
}

int oscap_get_substrings(char *str, int *ofs, oscap_pcre_t *re, int want_substrs, char ***substrings) {
int i, ret, rc;
int ovector[60], ovector_len = sizeof (ovector) / sizeof (ovector[0]);
char **substrs;

// todo: max match count check

for (i = 0; i < ovector_len; ++i) {
ovector[i] = -1;
}

unsigned long limit = OSCAP_PCRE_EXEC_RECURSION_LIMIT_DEFAULT;
char *limit_str = getenv("OSCAP_PCRE_EXEC_RECURSION_LIMIT");
if (limit_str != NULL)
if (sscanf(limit_str, "%lu", &limit) <= 0)
dW("Unable to parse OSCAP_PCRE_EXEC_RECURSION_LIMIT value");
oscap_pcre_set_match_limit_recursion(re, limit);
size_t str_len = strlen(str);
#if defined(OS_SOLARIS)
rc = oscap_pcre_exec(re, str, str_len, *ofs, OSCAP_PCRE_OPTS_NO_UTF8_CHECK, ovector, ovector_len);
#else
rc = oscap_pcre_exec(re, str, str_len, *ofs, 0, ovector, ovector_len);
#endif

if (rc < OSCAP_PCRE_ERR_NOMATCH) {
if (str_len < 100)
dE("Function oscap_pcre_exec() failed to match a regular expression with return code %d on string '%s'.", rc, str);
else
dE("Function oscap_pcre_exec() failed to match a regular expression with return code %d on string '%.100s' (truncated, showing first 100 characters).", rc, str);
return rc;
} else if (rc == OSCAP_PCRE_ERR_NOMATCH) {
/* no match */
return 0;
}

*ofs = (*ofs == ovector[1]) ? ovector[1] + 1 : ovector[1];

if (!want_substrs) {
/* just report successful match */
return 1;
}

ret = 0;
if (rc == 0) {
/* vector too small */
// todo: report partial results
rc = ovector_len / 3;
}

substrs = malloc(rc * sizeof (char *));
for (i = 0; i < rc; ++i) {
int len;
char *buf;

if (ovector[2 * i] == -1) {
continue;
}
len = ovector[2 * i + 1] - ovector[2 * i];
buf = malloc(len + 1);
memcpy(buf, str + ovector[2 * i], len);
buf[len] = '\0';
substrs[ret] = buf;
++ret;
}

*substrings = substrs;

return ret;
}

#ifndef OS_WINDOWS
FILE *oscap_fopen_with_prefix(const char *prefix, const char *path)
{
Expand Down
14 changes: 0 additions & 14 deletions src/common/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -487,20 +487,6 @@ int oscap_strncasecmp(const char *s1, const char *s2, size_t n);
*/
char *oscap_strerror_r(int errnum, char *buf, size_t buflen);

/**
* Match a regular expression and return substrings.
* Caller is responsible for freeing the returned array.
* @param str subject string
* @param ofs starting offset in str
* @param re compiled regular expression
* @param want_substrs if non-zero, substrings will be returned
* @param substrings contains returned substrings
* @return count of matched substrings, 0 if no match
* negative value on failure
*/
int oscap_get_substrings(char *str, int *ofs, oscap_pcre_t *re, int want_substrs, char ***substrings);


#ifndef OS_WINDOWS
/**
* Open file for reading with prefix added to its name.
Expand Down

0 comments on commit 5a8c2ba

Please sign in to comment.