From f3ddfbb9ecb5bd4aabe19980edf8686ad666bd2e Mon Sep 17 00:00:00 2001 From: pancake Date: Sat, 24 Oct 2015 02:06:45 +0200 Subject: [PATCH] Fixes for RRegex, Use r_regex_match(), comp+exec seems buggy --- libr/core/cmd_search.c | 5 +- libr/include/r_regex.h | 3 + libr/util/regex/regcomp.c | 112 ++++++++++++++------------------------ libr/util/regex/regexec.c | 8 ++- libr/util/regex/test.c | 12 ++++ 5 files changed, 65 insertions(+), 75 deletions(-) diff --git a/libr/core/cmd_search.c b/libr/core/cmd_search.c index 8a59ce9c69..3f913a93de 100644 --- a/libr/core/cmd_search.c +++ b/libr/core/cmd_search.c @@ -665,7 +665,7 @@ static RList* construct_rop_gadget(RCore *core, ut64 addr, ut8 *buf, int idx, strncpy (grep_str, start, end - start); if (regex) { // get the first regexp. - if (r_list_length(rx_list) > 0) { + if (r_list_length (rx_list) > 0) { rx = r_list_get_n(rx_list, count++); } } @@ -695,7 +695,8 @@ static RList* construct_rop_gadget(RCore *core, ut64 addr, ut8 *buf, int idx, idx += asmop.size; addr += asmop.size; if (rx) { - grep_find = r_regex_exec(rx, asmop.buf_asm, 0, 0, 0); + //grep_find = r_regex_exec (rx, asmop.buf_asm, 0, 0, 0); + grep_find = r_regex_match (grep, "e", asmop.buf_asm); search_hit = (end && grep && (grep_find < 1)); } else { search_hit = (end && grep && strstr (asmop.buf_asm, grep_str)); diff --git a/libr/include/r_regex.h b/libr/include/r_regex.h index 1bb8346a1d..3f74a2e089 100644 --- a/libr/include/r_regex.h +++ b/libr/include/r_regex.h @@ -9,6 +9,7 @@ typedef struct r_regex_t { size_t re_nsub; /* number of parenthesized subexpressions */ const char *re_endp; /* end pointer for R_REGEX_PEND */ struct re_guts *re_g; /* none of your business :-) */ + int re_flags; } RRegex; typedef struct r_regmatch_t { @@ -60,6 +61,7 @@ typedef int regoff_t; R_API RRegex *r_regex_new (const char *pattern, const char *cflags); R_API int r_regex_run (const char *pattern, const char *flags, const char *text); +R_API int r_regex_match (const char *pattern, const char *flags, const char *text); R_API int r_regex_flags(const char *flags); R_API int r_regex_comp(RRegex*, const char *, int); R_API size_t r_regex_error(int, const RRegex*, char *, size_t); @@ -67,6 +69,7 @@ R_API size_t r_regex_error(int, const RRegex*, char *, size_t); * gcc under c99 mode won't compile "[]" by itself. As a workaround, * a dummy argument name is added. */ +R_API bool r_regex_check(const RRegex *rr, const char *str); R_API int r_regex_exec(const RRegex *, const char *, size_t, RRegexMatch __pmatch[], int); R_API void r_regex_free(RRegex *); R_API void r_regex_fini(RRegex *); diff --git a/libr/util/regex/regcomp.c b/libr/util/regex/regcomp.c index 2ec36707df..2747a1c69d 100644 --- a/libr/util/regex/regcomp.c +++ b/libr/util/regex/regcomp.c @@ -189,15 +189,11 @@ R_API void r_regex_fini(RRegex *preg) { preg->re_magic = 0; /* mark it invalid */ g->magic = 0; /* mark it invalid */ - if (g->strip != NULL) - free((char *)g->strip); - if (g->sets != NULL) - free((char *)g->sets); - if (g->setbits != NULL) - free((char *)g->setbits); - if (g->must != NULL) - free(g->must); - free((char *)g); + free(g->strip); + free(g->sets); + free(g->setbits); + free(g->must); + free(g); } R_API void r_regex_free(RRegex *preg) { @@ -207,10 +203,9 @@ R_API void r_regex_free(RRegex *preg) { /* - regcomp - interface for parser and compilation + - 0 success, otherwise R_REGEX_something */ -R_API int /* 0 success, otherwise R_REGEX_something */ -r_regex_comp(RRegex *preg, const char *pattern, int cflags) -{ +R_API int r_regex_comp(RRegex *preg, const char *pattern, int cflags) { struct parse pa; struct re_guts *g; struct parse *p = &pa; @@ -224,22 +219,24 @@ r_regex_comp(RRegex *preg, const char *pattern, int cflags) cflags = GOODFLAGS(cflags); if ((cflags&R_REGEX_EXTENDED) && (cflags&R_REGEX_NOSPEC)) - return(R_REGEX_INVARG); + return R_REGEX_INVARG; if (cflags&R_REGEX_PEND) { if (preg->re_endp < pattern) return(R_REGEX_INVARG); len = preg->re_endp - pattern; - } else - len = strlen((char *)pattern); + } else len = strlen((char *)pattern); /* do the mallocs early so failure handling is easy */ - g = (struct re_guts *)malloc(sizeof(struct re_guts) + - (NC-1)*sizeof(cat_t)); + g = (struct re_guts *)calloc(sizeof(struct re_guts) + (NC-1),sizeof(cat_t)); if (g == NULL) - return(R_REGEX_ESPACE); + return R_REGEX_ESPACE; + preg->re_flags = cflags; p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */ p->strip = (sop *)calloc(p->ssize, sizeof(sop)); + if (!p->strip) { + return R_REGEX_ESPACE; + } p->slen = 0; if (p->strip == NULL) { free((char *)g); @@ -268,19 +265,18 @@ r_regex_comp(RRegex *preg, const char *pattern, int cflags) g->mlen = 0; g->nsub = 0; g->ncategories = 1; /* category 0 is "everything else" */ - g->categories = &g->catspace[-(CHAR_MIN)]; + g->categories = &g->catspace[-(CHAR_MIN)]; // WTF (void) memset((char *)g->catspace, 0, NC*sizeof(cat_t)); g->backrefs = 0; /* do it */ EMIT(OEND, 0); g->firststate = THERE(); - if (cflags&R_REGEX_EXTENDED) + if (cflags & R_REGEX_EXTENDED) p_ere(p, OUT); - else if (cflags&R_REGEX_NOSPEC) - p_str(p); - else - p_bre(p, OUT, OUT); + else if (cflags & R_REGEX_NOSPEC) + p_str (p); + else p_bre (p, OUT, OUT); EMIT(OEND, 0); g->laststate = THERE(); @@ -300,17 +296,15 @@ r_regex_comp(RRegex *preg, const char *pattern, int cflags) #endif /* win or lose, we're done */ - if (p->error != 0) /* lose */ - r_regex_fini(preg); - return(p->error); + if (p->error) /* lose */ + r_regex_fini (preg); + return p->error; } /* - p_ere - ERE parser top level, concatenation and alternation */ -static void -p_ere(struct parse *p, int stop) /* character this ERE should end at */ -{ +static void p_ere(struct parse *p, int stop) { /* character this ERE should end at */ char c; sopno prevback = 0; sopno prevfwd = 0; @@ -351,9 +345,7 @@ p_ere(struct parse *p, int stop) /* character this ERE should end at */ /* - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op */ -static void -p_ere_exp(struct parse *p) -{ +static void p_ere_exp(struct parse *p) { char c; sopno pos; int count; @@ -486,9 +478,7 @@ p_ere_exp(struct parse *p) /* - p_str - string (no metacharacters) "parser" */ -static void -p_str(struct parse *p) -{ +static void p_str(struct parse *p) { REQUIRE(MORE(), R_REGEX_EMPTY); while (MORE()) ordinary(p, GETNEXT()); @@ -504,8 +494,7 @@ p_str(struct parse *p) * category in such cases. This is fairly harmless; not worth fixing. * The amount of lookahead needed to avoid this kludge is excessive. */ -static void -p_bre(struct parse *p, +static void p_bre(struct parse *p, int end1, /* first terminating character */ int end2) /* second terminating character */ { @@ -672,9 +661,7 @@ p_count(struct parse *p) * Note a significant property of this code: if the allocset() did SETERROR, * no set operations are done. */ -static void -p_bracket(struct parse *p) -{ +static void p_bracket(struct parse *p) { cset *cs; int invert = 0; @@ -744,16 +731,15 @@ p_bracket(struct parse *p) if (nch(p, cs) == 1) { /* optimize singleton sets */ ordinary(p, firstch(p, cs)); freeset(p, cs); - } else + } else { EMIT(OANYOF, freezeset(p, cs)); + } } /* - p_b_term - parse one term of a bracketed character list */ -static void -p_b_term(struct parse *p, cset *cs) -{ +static void p_b_term(struct parse *p, cset *cs) { char c; char start = 0, finish; int i; @@ -814,9 +800,7 @@ p_b_term(struct parse *p, cset *cs) /* - p_b_cclass - parse a character-class name and deal with it */ -static void -p_b_cclass(struct parse *p, cset *cs) -{ +static void p_b_cclass(struct parse *p, cset *cs) { char *sp = p->next; struct cclass *cp; size_t len; @@ -847,9 +831,7 @@ p_b_cclass(struct parse *p, cset *cs) * * This implementation is incomplete. xxx */ -static void -p_b_eclass(struct parse *p, cset *cs) -{ +static void p_b_eclass(struct parse *p, cset *cs) { char c; c = p_b_coll_elem(p, '='); @@ -922,9 +904,7 @@ othercase(int ch) * * Boy, is this implementation ever a kludge... */ -static void -bothcases(struct parse *p, int ch) -{ +static void bothcases(struct parse *p, int ch) { char *oldnext = p->next; char *oldend = p->end; char bracket[3]; @@ -1069,9 +1049,7 @@ seterr(struct parse *p, int e) /* - allocset - allocate a set of characters for [] */ -static cset * -allocset(struct parse *p) -{ +static cset * allocset(struct parse *p) { int no = p->g->ncsets++; size_t nc; size_t nbytes; @@ -1128,9 +1106,7 @@ nomem: /* - freeset - free a now-unused set */ -static void -freeset(struct parse *p, cset *cs) -{ +static void freeset(struct parse *p, cset *cs) { int i; cset *top = &p->g->sets[p->g->ncsets]; size_t css = (size_t)p->g->csetsize; @@ -1197,9 +1173,7 @@ firstch(struct parse *p, cset *cs) /* - nch - number of characters in a set */ -static int -nch(struct parse *p, cset *cs) -{ +static int nch(struct parse *p, cset *cs) { int i; size_t css = (size_t)p->g->csetsize; int n = 0; @@ -1213,9 +1187,7 @@ nch(struct parse *p, cset *cs) /* - mcadd - add a collating element to a cset */ -static void -mcadd( struct parse *p, cset *cs, char *cp) -{ +static void mcadd( struct parse *p, cset *cs, char *cp) { size_t oldend = cs->smultis; void *np; @@ -1240,9 +1212,7 @@ mcadd( struct parse *p, cset *cs, char *cp) * is deferred. */ /* ARGSUSED */ -static void -mcinvert(struct parse *p, cset *cs) -{ +static void mcinvert(struct parse *p, cset *cs) { assert(cs->multis == NULL); /* xxx */ } @@ -1253,9 +1223,7 @@ mcinvert(struct parse *p, cset *cs) * is deferred. */ /* ARGSUSED */ -static void -mccase(struct parse *p, cset *cs) -{ +static void mccase(struct parse *p, cset *cs) { assert(cs->multis == NULL); /* xxx */ } diff --git a/libr/util/regex/regexec.c b/libr/util/regex/regexec.c index 769571f0cc..4e247a0b31 100644 --- a/libr/util/regex/regexec.c +++ b/libr/util/regex/regexec.c @@ -128,6 +128,10 @@ #include "engine.c" + +R_API bool r_regex_check(const RRegex *rr, const char *str) { + return r_regex_exec (rr, str, 0, NULL, rr->re_flags); +} /* - regexec - interface for matching * @@ -137,7 +141,7 @@ */ int /* 0 success, R_REGEX_NOMATCH failure */ r_regex_exec(const RRegex *preg, const char *string, size_t nmatch, - RRegexMatch pmatch[], int eflags) + RRegexMatch pmatch[], int eflags) { struct re_guts *g = preg->re_g; #ifdef REDEBUG @@ -145,6 +149,8 @@ r_regex_exec(const RRegex *preg, const char *string, size_t nmatch, #else # define GOODFLAGS(f) ((f)&(R_REGEX_NOTBOL|R_REGEX_NOTEOL|R_REGEX_STARTEND)) #endif + if (!preg || !string) + return R_REGEX_ASSERT; if (preg->re_magic != MAGIC1 || g->magic != MAGIC2) return(R_REGEX_BADPAT); diff --git a/libr/util/regex/test.c b/libr/util/regex/test.c index 9165c9e133..71a13a47dc 100644 --- a/libr/util/regex/test.c +++ b/libr/util/regex/test.c @@ -18,6 +18,17 @@ int _main() { return 0; } +static void test_or() { + RRegex *rx = r_regex_new ("(eax|ebx)", "e"); + printf ("result (%s) = %d\n", "mov eax", r_regex_match("(eax|ebx)", "e", "mov eax")); + printf ("result (%s) = %d\n", "mov ebx", r_regex_match("(eax|ebx)", "e", "mov ebx")); + printf ("result (%s) = %d\n", "mov eax", r_regex_check(rx, "mov eax")); + printf ("result (%s) = %d\n", "mov ebx", r_regex_check(rx, "mov ebx")); + printf ("result (%s) = %d\n", "mov eax", r_regex_exec(rx, "mov eax", 0, 0, 1)); + printf ("result (%s) = %d\n", "mov ebx", r_regex_exec(rx, "mov ebx", 0, 0, 1)); + r_regex_free (rx); +} + int main(int argc, char **argv) { const char *needle = "^hi"; const char *haystack_1 = "patata"; @@ -35,5 +46,6 @@ int main(int argc, char **argv) { printf ("result (%s) = %d\n", haystack_2, res); r_regex_free (rx); } else printf ("oops, cannot compile regexp\n"); + test_or(); return 0; }