diff --git a/configure.ac b/configure.ac index 4b4d09e..1ac8ee3 100644 --- a/configure.ac +++ b/configure.ac @@ -16,6 +16,7 @@ dnl Checks for compiler characteristics. AC_USE_SYSTEM_EXTENSIONS AC_C_CONST AC_C_INLINE +AC_TYPE_SSIZE_T tre_version_1=`echo $PACKAGE_VERSION | cut -d . -f 1` tre_version_2=`echo $PACKAGE_VERSION | cut -d . -f 2` diff --git a/lib/regexec.c b/lib/regexec.c index f5d8163..4d5fdd4 100644 --- a/lib/regexec.c +++ b/lib/regexec.c @@ -136,7 +136,7 @@ tre_have_approx(const regex_t *preg) } static int -tre_match(const tre_tnfa_t *tnfa, const void *string, size_t len, +tre_match(const tre_tnfa_t *tnfa, const void *string, ssize_t len, tre_str_type_t type, size_t nmatch, regmatch_t pmatch[], int eflags) { @@ -171,7 +171,7 @@ tre_match(const tre_tnfa_t *tnfa, const void *string, size_t len, return REG_BADPAT; } } - status = tre_tnfa_run_backtrack(tnfa, string, (int)len, type, + status = tre_tnfa_run_backtrack(tnfa, string, len, type, tags, eflags, &eo); } #ifdef TRE_APPROX @@ -183,14 +183,14 @@ tre_match(const tre_tnfa_t *tnfa, const void *string, size_t len, tre_regaparams_default(¶ms); params.max_err = 0; params.max_cost = 0; - status = tre_tnfa_run_approx(tnfa, string, (int)len, type, tags, + status = tre_tnfa_run_approx(tnfa, string, len, type, tags, &match, params, eflags, &eo); } #endif /* TRE_APPROX */ else { /* Exact matching, no back references, use the parallel matcher. */ - status = tre_tnfa_run_parallel(tnfa, string, (int)len, type, + status = tre_tnfa_run_parallel(tnfa, string, len, type, tags, eflags, &eo); } @@ -225,7 +225,7 @@ tre_regexec(const regex_t *preg, const char *str, size_t nmatch, regmatch_t pmatch[], int eflags) #endif { - return tre_regnexec(preg, str, (unsigned)-1, nmatch, pmatch, eflags); + return tre_regnexec(preg, str, -1, nmatch, pmatch, eflags); } int @@ -234,7 +234,7 @@ tre_regexecb(const regex_t *preg, const char *str, { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; - return tre_match(tnfa, str, (unsigned)-1, STR_BYTE, nmatch, pmatch, eflags); + return tre_match(tnfa, str, -1, STR_BYTE, nmatch, pmatch, eflags); } int @@ -261,7 +261,7 @@ int tre_regwexec(const regex_t *preg, const wchar_t *str, size_t nmatch, regmatch_t pmatch[], int eflags) { - return tre_regwnexec(preg, str, (unsigned)-1, nmatch, pmatch, eflags); + return tre_regwnexec(preg, str, -1, nmatch, pmatch, eflags); } #endif /* TRE_WCHAR */ @@ -271,7 +271,7 @@ tre_reguexec(const regex_t *preg, const tre_str_source *str, size_t nmatch, regmatch_t pmatch[], int eflags) { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; - return tre_match(tnfa, str, (unsigned)-1, STR_USER, nmatch, pmatch, eflags); + return tre_match(tnfa, str, -1, STR_USER, nmatch, pmatch, eflags); } @@ -282,7 +282,7 @@ tre_reguexec(const regex_t *preg, const tre_str_source *str, */ static int -tre_match_approx(const tre_tnfa_t *tnfa, const void *string, size_t len, +tre_match_approx(const tre_tnfa_t *tnfa, const void *string, ssize_t len, tre_str_type_t type, regamatch_t *match, regaparams_t params, int eflags) { @@ -311,7 +311,7 @@ tre_match_approx(const tre_tnfa_t *tnfa, const void *string, size_t len, if (tags == NULL) return REG_ESPACE; } - status = tre_tnfa_run_approx(tnfa, string, (int)len, type, tags, + status = tre_tnfa_run_approx(tnfa, string, len, type, tags, match, params, eflags, &eo); if (status == REG_OK) tre_fill_pmatch(match->nmatch, match->pmatch, tnfa->cflags, tnfa, tags, eo); @@ -336,7 +336,7 @@ int tre_regaexec(const regex_t *preg, const char *str, regamatch_t *match, regaparams_t params, int eflags) { - return tre_reganexec(preg, str, (unsigned)-1, match, params, eflags); + return tre_reganexec(preg, str, -1, match, params, eflags); } int @@ -345,8 +345,7 @@ tre_regaexecb(const regex_t *preg, const char *str, { tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; - return tre_match_approx(tnfa, str, (unsigned)-1, STR_BYTE, - match, params, eflags); + return tre_match_approx(tnfa, str, -1, STR_BYTE, match, params, eflags); } #ifdef TRE_WCHAR @@ -364,7 +363,7 @@ int tre_regawexec(const regex_t *preg, const wchar_t *str, regamatch_t *match, regaparams_t params, int eflags) { - return tre_regawnexec(preg, str, (unsigned)-1, match, params, eflags); + return tre_regawnexec(preg, str, -1, match, params, eflags); } #endif /* TRE_WCHAR */ diff --git a/lib/tre-internal.h b/lib/tre-internal.h index 340aefb..c055220 100644 --- a/lib/tre-internal.h +++ b/lib/tre-internal.h @@ -15,13 +15,18 @@ #ifdef HAVE_WCTYPE_H #include -#endif /* !HAVE_WCTYPE_H */ +#endif /* HAVE_WCTYPE_H */ + +#ifdef HAVE_SYS_TYPES_H +#include +#endif /* HAVE_SYS_TYPES_H */ #include #include #include "../local_includes/tre.h" #define TRE_MAX_RE 65536 +#define TRE_MAX_STRING INT_MAX #define TRE_MAX_STACK 1048576 #ifdef TRE_DEBUG @@ -268,26 +273,25 @@ tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags, const tre_tnfa_t *tnfa, int *tags, int match_eo); reg_errcode_t -tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len, +tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, ssize_t len, tre_str_type_t type, int *match_tags, int eflags, int *match_end_ofs); reg_errcode_t -tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len, +tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, ssize_t len, tre_str_type_t type, int *match_tags, int eflags, int *match_end_ofs); reg_errcode_t -tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, - int len, tre_str_type_t type, int *match_tags, - int eflags, int *match_end_ofs); +tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, ssize_t len, + tre_str_type_t type, int *match_tags, int eflags, + int *match_end_ofs); #ifdef TRE_APPROX reg_errcode_t -tre_tnfa_run_approx(const tre_tnfa_t *tnfa, const void *string, int len, - tre_str_type_t type, int *match_tags, - regamatch_t *match, regaparams_t params, - int eflags, int *match_end_ofs); +tre_tnfa_run_approx(const tre_tnfa_t *tnfa, const void *string, ssize_t len, + tre_str_type_t type, int *match_tags, regamatch_t *match, + regaparams_t params, int eflags, int *match_end_ofs); #endif /* TRE_APPROX */ #endif /* TRE_INTERNAL_H */ diff --git a/lib/tre-match-approx.c b/lib/tre-match-approx.c index 50664ce..837e753 100644 --- a/lib/tre-match-approx.c +++ b/lib/tre-match-approx.c @@ -197,7 +197,7 @@ tre_set_params(tre_tnfa_approx_reach_t *reach, } reg_errcode_t -tre_tnfa_run_approx(const tre_tnfa_t *tnfa, const void *string, int len, +tre_tnfa_run_approx(const tre_tnfa_t *tnfa, const void *string, ssize_t len, tre_str_type_t type, int *match_tags, regamatch_t *match, regaparams_t default_params, int eflags, int *match_end_ofs) @@ -205,7 +205,7 @@ tre_tnfa_run_approx(const tre_tnfa_t *tnfa, const void *string, int len, /* State variables required by GET_NEXT_WCHAR. */ tre_char_t prev_c = 0, next_c = 0; const char *str_byte = string; - int pos = -1; + ssize_t pos = -1; unsigned int pos_add_next = 1; #ifdef TRE_WCHAR const wchar_t *str_wide = string; @@ -213,6 +213,7 @@ tre_tnfa_run_approx(const tre_tnfa_t *tnfa, const void *string, int len, mbstate_t mbstate; #endif /* !TRE_WCHAR */ #endif /* TRE_WCHAR */ + reg_errcode_t ret; int reg_notbol = eflags & REG_NOTBOL; int reg_noteol = eflags & REG_NOTEOL; int reg_newline = tnfa->cflags & REG_NEWLINE; @@ -237,16 +238,20 @@ tre_tnfa_run_approx(const tre_tnfa_t *tnfa, const void *string, int len, int i, id; - if (!match_tags) - num_tags = 0; - else - num_tags = tnfa->num_tags; + /* + * TRE internals tend to use int instead of size_t for positions or + * lengths and don't check for overflow. This will take time to fix + * properly. In the meantime, simply limit the input to what we can + * handle. + */ + if (len > TRE_MAX_STRING) + len = TRE_MAX_STRING; #ifdef TRE_MBSTATE memset(&mbstate, '\0', sizeof(mbstate)); #endif /* TRE_MBSTATE */ - DPRINT(("tre_tnfa_run_approx, input type %d, len %d, eflags %d, " + DPRINT(("tre_tnfa_run_approx, input type %d, len %zd, eflags %d, " "match_tags %p\n", type, len, eflags, match_tags)); @@ -256,6 +261,11 @@ tre_tnfa_run_approx(const tre_tnfa_t *tnfa, const void *string, int len, default_params.cost_del, default_params.cost_subst)); + if (!match_tags) + num_tags = 0; + else + num_tags = tnfa->num_tags; + /* Allocate memory for temporary data required for matching. This needs to be done for every matching operation to be thread safe. This allocates everything in a single large block from the stack frame using alloca() @@ -321,7 +331,7 @@ tre_tnfa_run_approx(const tre_tnfa_t *tnfa, const void *string, int len, while (/*CONSTCOND*/(void)1,1) { - DPRINT(("%03d:%2lc/%05d\n", pos, (tre_cint_t)next_c, (int)next_c)); + DPRINT(("%03zd:%2lc/%05d\n", pos, (tre_cint_t)next_c, (int)next_c)); /* Add initial states to `reach_next' if an exact match has not yet been found. */ @@ -595,7 +605,7 @@ tre_tnfa_run_approx(const tre_tnfa_t *tnfa, const void *string, int len, && (num_tags > 0 && tmp_tags[0] <= match_tags[0])))) { - DPRINT((" setting new match at %d, cost %d\n", + DPRINT((" setting new match at %zd, cost %d\n", pos, cost0)); match_eo = pos; memcpy(match_costs, reach_next[dest_id].costs[0], @@ -630,7 +640,7 @@ tre_tnfa_run_approx(const tre_tnfa_t *tnfa, const void *string, int len, if (str_user_end) break; } - else if (next_c == L'\0') + else if (next_c == L'\0' || pos >= TRE_MAX_STRING) break; } else @@ -778,7 +788,7 @@ tre_tnfa_run_approx(const tre_tnfa_t *tnfa, const void *string, int len, || (cost0 == match_costs[TRE_M_COST] && num_tags > 0 && tmp_tags[0] <= match_tags[0]))) { - DPRINT((" setting new match at %d, cost %d\n", + DPRINT((" setting new match at %zd, cost %d\n", pos, cost0)); match_eo = pos; for (i = 0; i < TRE_M_LAST; i++) @@ -793,16 +803,17 @@ tre_tnfa_run_approx(const tre_tnfa_t *tnfa, const void *string, int len, DPRINT(("match end offset = %d, match cost = %d\n", match_eo, match_costs[TRE_M_COST])); -#ifndef TRE_USE_ALLOCA - if (buf) - xfree(buf); -#endif /* !TRE_USE_ALLOCA */ - match->cost = match_costs[TRE_M_COST]; match->num_ins = match_costs[TRE_M_NUM_INS]; match->num_del = match_costs[TRE_M_NUM_DEL]; match->num_subst = match_costs[TRE_M_NUM_SUBST]; *match_end_ofs = match_eo; - return match_eo >= 0 ? REG_OK : REG_NOMATCH; + ret = match_eo >= 0 ? REG_OK : REG_NOMATCH; + +#ifndef TRE_USE_ALLOCA + if (buf) + xfree(buf); +#endif /* !TRE_USE_ALLOCA */ + return ret; } diff --git a/lib/tre-match-backtrack.c b/lib/tre-match-backtrack.c index 0bd9822..7e18492 100644 --- a/lib/tre-match-backtrack.c +++ b/lib/tre-match-backtrack.c @@ -198,13 +198,13 @@ typedef struct tre_backtrack_struct { reg_errcode_t tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, - int len, tre_str_type_t type, int *match_tags, + ssize_t len, tre_str_type_t type, int *match_tags, int eflags, int *match_end_ofs) { /* State variables required by GET_NEXT_WCHAR. */ tre_char_t prev_c = 0, next_c = 0; const char *str_byte = string; - int pos = 0; + ssize_t pos = 0; unsigned int pos_add_next = 1; #ifdef TRE_WCHAR const wchar_t *str_wide = string; @@ -229,6 +229,7 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, #ifdef TRE_MBSTATE mbstate_t mbstate_start; #endif /* TRE_MBSTATE */ + reg_errcode_t ret; /* End offset of best match so far, or -1 if no match found yet. */ int match_eo = -1; @@ -246,7 +247,15 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, tre_tnfa_transition_t *trans_i; regmatch_t *pmatch = NULL; - int ret; + + /* + * TRE internals tend to use int instead of size_t for positions or + * lengths and don't check for overflow. This will take time to fix + * properly. In the meantime, simply limit the input to what we can + * handle. + */ + if (len > TRE_MAX_STRING) + len = TRE_MAX_STRING; #ifdef TRE_MBSTATE memset(&mbstate, '\0', sizeof(mbstate)); @@ -264,7 +273,7 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, stack->next = NULL; DPRINT(("tnfa_execute_backtrack, input type %d\n", type)); - DPRINT(("len = %d\n", len)); + DPRINT(("len = %zd\n", len)); #ifdef TRE_USE_ALLOCA tags = alloca(sizeof(*tags) * tnfa->num_tags); @@ -364,7 +373,7 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, tags[*next_tags] = pos; - DPRINT(("entering match loop, pos %d, str_byte %p\n", pos, str_byte)); + DPRINT(("entering match loop, pos %zd, str_byte %p\n", pos, str_byte)); DPRINT(("pos:chr/code | state and tags\n")); DPRINT(("-------------+------------------------------------------------\n")); @@ -379,7 +388,7 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, DPRINT(("start loop\n")); if (state == tnfa->final) { - DPRINT((" match found, %d %d\n", match_eo, pos)); + DPRINT((" match found, %d %zd\n", match_eo, pos)); if (match_eo < pos || (match_eo == pos && match_tags @@ -400,7 +409,7 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, } #ifdef TRE_DEBUG - DPRINT(("%3d:%2lc/%05d | %p ", pos, (tre_cint_t)next_c, (int)next_c, + DPRINT(("%3zd:%2lc/%05d | %p ", pos, (tre_cint_t)next_c, (int)next_c, state)); { int i; @@ -505,7 +514,7 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, #endif /* TRE_WCHAR */ pos += bt_len - 1; GET_NEXT_WCHAR(); - DPRINT((" pos now %d\n", pos)); + DPRINT((" pos now %zd\n", pos)); } else { @@ -523,7 +532,7 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, if (str_user_end) goto backtrack; } - else if (next_c == L'\0') + else if (next_c == L'\0' || pos >= TRE_MAX_STRING) goto backtrack; } else @@ -616,7 +625,7 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, /* Check for end of string. */ if (len < 0) { - if (next_c_start == L'\0') + if (next_c_start == L'\0' || pos_start >= TRE_MAX_STRING) { DPRINT(("end of string.\n")); break; diff --git a/lib/tre-match-parallel.c b/lib/tre-match-parallel.c index ffc7819..f062057 100644 --- a/lib/tre-match-parallel.c +++ b/lib/tre-match-parallel.c @@ -104,14 +104,14 @@ tre_print_reach(const tre_tnfa_reach_t *reach, int num_tags) #endif /* TRE_DEBUG */ reg_errcode_t -tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len, +tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, ssize_t len, tre_str_type_t type, int *match_tags, int eflags, int *match_end_ofs) { /* State variables required by GET_NEXT_WCHAR. */ tre_char_t prev_c = 0, next_c = 0; const char *str_byte = string; - int pos = -1; + ssize_t pos = -1; unsigned int pos_add_next = 1; #ifdef TRE_WCHAR const wchar_t *str_wide = string; @@ -119,6 +119,7 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len, mbstate_t mbstate; #endif /* TRE_MBSTATE */ #endif /* TRE_WCHAR */ + reg_errcode_t ret; int reg_notbol = eflags & REG_NOTBOL; int reg_noteol = eflags & REG_NOTEOL; int reg_newline = tnfa->cflags & REG_NEWLINE; @@ -136,6 +137,15 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len, int *tmp_tags = NULL; int *tmp_iptr; + /* + * TRE internals tend to use int instead of size_t for positions or + * lengths and don't check for overflow. This will take time to fix + * properly. In the meantime, simply limit the input to what we can + * handle. + */ + if (len > TRE_MAX_STRING) + len = TRE_MAX_STRING; + #ifdef TRE_MBSTATE memset(&mbstate, '\0', sizeof(mbstate)); #endif /* TRE_MBSTATE */ @@ -263,7 +273,7 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len, } #endif - DPRINT(("length: %d\n", len)); + DPRINT(("length: %zd\n", len)); DPRINT(("pos:chr/code | states and tags\n")); DPRINT(("-------------+------------------------------------------------\n")); @@ -331,7 +341,7 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len, if (str_user_end) break; } - else if (next_c == L'\0') + else if (next_c == L'\0' || pos >= TRE_MAX_STRING) break; } else @@ -343,9 +353,9 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len, GET_NEXT_WCHAR(); #ifdef TRE_DEBUG - DPRINT(("%3d:%2lc/%05d |", pos - 1, (tre_cint_t)prev_c, (int)prev_c)); + DPRINT(("%3zd:%2lc/%05d |", pos - 1, (tre_cint_t)prev_c, (int)prev_c)); tre_print_reach(reach_next, num_tags); - DPRINT(("%3d:%2lc/%05d |", pos, (tre_cint_t)next_c, (int)next_c)); + DPRINT(("%3zd:%2lc/%05d |", pos, (tre_cint_t)next_c, (int)next_c)); tre_print_reach(reach_next, num_tags); #endif /* TRE_DEBUG */ @@ -488,13 +498,14 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len, DPRINT(("match end offset = %d\n", match_eo)); + *match_end_ofs = match_eo; + ret = match_eo >= 0 ? REG_OK : REG_NOMATCH; + #ifndef TRE_USE_ALLOCA if (buf) xfree(buf); #endif /* !TRE_USE_ALLOCA */ - - *match_end_ofs = match_eo; - return match_eo >= 0 ? REG_OK : REG_NOMATCH; + return ret; } /* EOF */ diff --git a/lib/tre-match-utils.h b/lib/tre-match-utils.h index f33c9f1..76e8b19 100644 --- a/lib/tre-match-utils.h +++ b/lib/tre-match-utils.h @@ -41,7 +41,7 @@ else \ { \ size_t w; \ - int max; \ + size_t max; \ if (len >= 0) \ max = len - pos; \ else \ diff --git a/lib/tre-parse.c b/lib/tre-parse.c index 9c3106c..1079a5e 100644 --- a/lib/tre-parse.c +++ b/lib/tre-parse.c @@ -957,8 +957,8 @@ tre_parse(tre_parse_ctx_t *ctx) int depth = 0; int temporary_cflags = 0; - DPRINT(("tre_parse: parsing '%.*" STRF "', len = %d\n", - ctx->len, ctx->re, ctx->len)); + DPRINT(("tre_parse: parsing '%.*" STRF "', len = %zu\n", + (int)ctx->len, ctx->re, ctx->len)); if (!ctx->nofirstsub) { diff --git a/lib/tre-parse.h b/lib/tre-parse.h index 70591b6..3fd40d4 100644 --- a/lib/tre-parse.h +++ b/lib/tre-parse.h @@ -23,7 +23,7 @@ typedef struct { const tre_char_t *re_start; /* The first character after the end of the regexp. */ const tre_char_t *re_end; - int len; + size_t len; /* Current submatch ID. */ int submatch_id; /* The highest back reference or -1 if none seen so far. */ diff --git a/tests/Makefile.am b/tests/Makefile.am index d73acac..076118d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -68,3 +68,10 @@ TESTS = test-str-source retest if TRE_MULTIBYTE TESTS += wretest endif TRE_MULTIBYTE + +# This test produces insane amounts of debugging output +if !TRE_DEBUG +check_PROGRAMS += test-limits +TESTS += test-limits +test_limits_LDADD = libxtre.la $(LDADD) +endif diff --git a/tests/retest.c b/tests/retest.c index f6af42e..c486a81 100644 --- a/tests/retest.c +++ b/tests/retest.c @@ -60,7 +60,7 @@ #define CHAR_T wchar_t #define L(x) (L ## x) -#define MAXSTRSIZE (TRE_MAX_RE * 2) +#define MAXSTRSIZE 8192 static wchar_t wstr[MAXSTRSIZE]; static wchar_t wregex[MAXSTRSIZE]; static int woffs[MAXSTRSIZE]; @@ -1740,12 +1740,6 @@ main(int argc, char **argv) test_comp(NULL, REG_BASIC, REG_OK); test_comp(NULL, REG_EXTENDED, REG_OK); -#define TOOLONG (TRE_MAX_RE / 2 + 1) - static char toolong[TOOLONG + TOOLONG + 1]; - memset(toolong, '(', TOOLONG); - memset(toolong + TOOLONG, ')', TOOLONG); - toolong[TOOLONG + TOOLONG] = '\0'; - test_comp(toolong, REG_EXTENDED, REG_ESPACE); /* diff --git a/tests/test-limits.c b/tests/test-limits.c new file mode 100644 index 0000000..7362f22 --- /dev/null +++ b/tests/test-limits.c @@ -0,0 +1,141 @@ +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include + +#ifdef USE_SYSTEM_REGEX +# include +# ifndef REG_BASIC +# define REG_BASIC 0 +# endif +# ifndef REG_OK +# define REG_OK 0 +# endif +#else +# include "tre-internal.h" +# define regcomp tre_regcomp +# define regexec tre_regexec +# define regfree tre_regfree +#endif + +#define MIN_SHIFT 2 +#define MAX_SHIFT 32 + +static int ntests, nok; + +static void ok(void) { fputc('+', stderr); ntests++; nok++; } +static void notok(void) { fputc('-', stderr); ntests++; } +static void done(void) { fputc('\n', stderr); exit(nok == ntests ? 0 : 1); } +#define check(expr) do { ((expr) ? ok() : notok()); } while (0) + +int +main(void) +{ + regmatch_t pm[9]; + regex_t preg; + size_t npm = sizeof(pm) / sizeof(pm[0]); + size_t size; + char *buf; + int error, expect, shift; + + if ((size = 1ULL << MAX_SHIFT) == 0 || (buf = malloc(size + 1)) == NULL) { + notok(); + } else { + memset(buf, 'a', size); + buf[size] = '\0'; + for (shift = MIN_SHIFT; shift <= MAX_SHIFT; shift++) { + fprintf(stderr, "%d", shift); + if ((size = 1ULL << shift) == 0) { + notok(); + continue; + } + buf[0] = buf[size - 1] = 'x'; + buf[size] = '\0'; + +#ifdef USE_SYSTEM_REGEX + expect = REG_OK; +#else + /* expected outcome of regcomp() for a regex this size */ + expect = size <= TRE_MAX_RE ? REG_OK : REG_ESPACE; +#endif + + /* compile a BRE size characters long */ + error = regcomp(&preg, buf, REG_BASIC); + if (error != expect) { + notok(); + } else if (error == REG_OK) { + ok(); + regfree(&preg); + } else { + ok(); + } + + /* compile an ERE size characters long */ + error = regcomp(&preg, buf, REG_EXTENDED); + if (error != expect) { + notok(); + } else if (error == REG_OK) { + ok(); + regfree(&preg); + } else { + ok(); + } + +#ifdef USE_SYSTEM_REGEX + expect = REG_OK; +#else + /* expected outcome of regexec() for a string this size */ + expect = size <= TRE_MAX_STRING ? REG_OK : REG_NOMATCH; +#endif + + /* match a BRE with a string size characters long */ + error = regcomp(&preg, "x\\(aa*\\)x", REG_BASIC); + if (error == REG_OK) { + ok(); + error = regexec(&preg, buf, npm, pm, 0); + if (error != expect) { + notok(); + } else if (error == REG_OK) { + ok(); + check(pm[0].rm_so == 0 && (size_t)pm[0].rm_eo == size); + check(pm[1].rm_so == 1 && (size_t)pm[1].rm_eo == size - 1); + } else { + ok(); + } + regfree(&preg); + } else { + notok(); + } + + /* match an ERE with a string size characters long */ + error = regcomp(&preg, "x(a+)x", REG_EXTENDED); + if (error == REG_OK) { + ok(); + error = regexec(&preg, buf, npm, pm, 0); + if (error != expect) { + notok(); + } else if (error == REG_OK) { + ok(); + check(pm[0].rm_so == 0 && (size_t)pm[0].rm_eo == size); + check(pm[1].rm_so == 1 && (size_t)pm[1].rm_eo == size - 1); + } else { + ok(); + } + regfree(&preg); + } else { + notok(); + } + + /* undo our changes to the buffer */ + buf[0] = buf[size - 1] = buf[size] = 'a'; + fflush(stderr); + } + free(buf); + } + done(); +} diff --git a/win32/config.h b/win32/config.h index a6708cd..3c4fecf 100644 --- a/win32/config.h +++ b/win32/config.h @@ -171,9 +171,17 @@ /* Define to empty if `const' does not conform to ANSI C. */ /* #undef const */ -/* Define as `__inline' if that's what the C compiler calls it, or to nothing - if it is not supported. */ -#define inline __inline +/* Define to '__inline__' or '__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define as 'unsigned int' if doesn't define. */ +/* #undef size_t */ + +/* Define as 'int' if doesn't define. */ +#define ssize_t long /* Avoid silly warnings about "insecure" functions. */ #define _CRT_SECURE_NO_DEPRECATE 1