diff --git a/configure.ac b/configure.ac index 994988a..3133e56 100644 --- a/configure.ac +++ b/configure.ac @@ -141,7 +141,7 @@ case "$enable_intfilter" in native) intfiltertype="size_t" ;; -no) +no|"") intfiltertype="" ;; *) @@ -235,6 +235,43 @@ then MYDEFS="$MYDEFS -DSTATISTICS" fi +AC_ARG_WITH([pcre2],[AC_HELP_STRING([--with-pcre2],[pcre2-config executable @<:@default=pcre2@:>@])],[],[with_pcre2="pcre2-config"]) + +AC_ARG_ENABLE([regex],[AC_HELP_STRING([--enable-regex],[whether to enable regex engine. currently possible values are "pcre2" and "yes" which defaults to "pcre2" @<:@default=no@:>@])],[],[enable_regex=no]) +case "$enable_regex" in +no|"") + ;; +yes|pcre2) + AC_MSG_CHECKING([pcre2]) + V="" + if test "$with_pcre2" != "yes" + then + V=`"$with_pcre2" --version 2>/dev/null` + fi + if test -n "$V" + then + AC_MSG_RESULT([$V]) + MYDEFS="$MYDEFS -DPCRE2FILTER" + CF=`"$with_pcre2" --cflags` + if test -n "$CF" + then + CFLAGS="$CFLAGS $CF" + fi + LF=`"$with_pcre2" --libs8` + if test -n "$LF" + then + LDFLAGS="$LDFLAGS $LF" + fi + else + AC_MSG_RESULT([not found]) + AC_ERROR([pcre2-config cannot be executed]) + fi + ;; +*) + AC_MSG_WARN([unrecognised regex engine type: $enable_regex]) + ;; +esac + AC_SUBST(CSTD,["$cstd"]) AC_SUBST(ED25519IMPL,["$ed25519impl"]) AC_SUBST(MYDEFS,["$MYDEFS"]) diff --git a/filters.h b/filters.h index 53e2b2a..87ff52f 100644 --- a/filters.h +++ b/filters.h @@ -4,6 +4,11 @@ # define BINFILTER #endif +#ifdef PCRE2FILTER +# undef BINFILTER +# undef INTFILTER +#endif + #ifdef INTFILTER # ifdef BINSEARCH # ifndef BESORT @@ -51,9 +56,22 @@ struct intfilter { VEC_STRUCT(ifiltervec,struct intfilter) filters; # ifdef OMITMASK IFT ifiltermask; -# endif // BINSEARCH +# endif #endif // INTFILTER +#ifdef PCRE2FILTER + +#define PCRE2_CODE_UNIT_WIDTH 8 +#include + +struct pcre2filter { + char *str; + pcre2_code *re; +} ; +VEC_STRUCT(pfiltervec,struct pcre2filter) filters; + +#endif // PCRE2FILTER + static void filters_init() { VEC_INIT(filters); @@ -291,16 +309,24 @@ static void filter_sort(void) #endif // BINFILTER +#ifdef PCRE2FILTER +static size_t filter_len(size_t i) +{ + return 0; +} +#endif // PCRE2FILTER + static void filters_add(const char *filter) { +#ifdef NEEDBINFILTER struct binfilter bf; size_t ret; -#ifdef INTFILTER +# ifdef INTFILTER union intconv { IFT i; u8 b[sizeof(IFT)]; } fc,mc; -#endif +# endif // skip regex start symbol. we do not support regex tho if (*filter == '^') @@ -319,11 +345,11 @@ static void filters_add(const char *filter) ret = BASE32_FROM_LEN(ret); if (!ret) return; -#ifdef INTFILTER +# ifdef INTFILTER size_t maxsz = sizeof(IFT); -#else +# else size_t maxsz = sizeof(bf.f); -#endif +# endif if (ret > maxsz) { fprintf(stderr,"filter \"%s\" is too long\n",filter); fprintf(stderr," "); @@ -336,7 +362,7 @@ static void filters_add(const char *filter) base32_from(bf.f,&bf.mask,filter); bf.len = ret - 1; -#ifdef INTFILTER +# ifdef INTFILTER mc.i = 0; for (size_t i = 0;i < bf.len;++i) mc.b[i] = 0xFF; @@ -345,29 +371,58 @@ static void filters_add(const char *filter) fc.i &= mc.i; struct intfilter ifltr = { .f = fc.i, -# ifndef OMITMASK +# ifndef OMITMASK .m = mc.i, -# endif +# endif }; -# ifdef OMITMASK +# ifdef OMITMASK ifilter_addflatten(&ifltr,mc.i); -# else // OMITMASK +# else // OMITMASK VEC_ADD(filters,ifltr); -# endif // OMITMASK -#endif // INTFILTER +# endif // OMITMASK +# endif // INTFILTER -#ifdef BINFILTER +# ifdef BINFILTER VEC_ADD(filters,bf); -#endif // BINFILTER +# endif // BINFILTER +#endif // NEEDBINFILTER + +#ifdef PCRE2FILTER + int errornum; + PCRE2_SIZE erroroffset; + pcre2_code *re; + re = pcre2_compile((PCRE2_SPTR8)filter,PCRE2_ZERO_TERMINATED,0,&errornum,&erroroffset,0); + if (!re) { + PCRE2_UCHAR buffer[1024]; + pcre2_get_error_message(errornum,buffer,sizeof(buffer)); + fprintf(stderr,"PCRE2 compilation failed at offset %zu: %s\n", + (size_t)erroroffset,buffer); + return; + } + // attempt to JIT. ignore error + (void)pcre2_jit_compile(re,PCRE2_JIT_COMPLETE); + struct pcre2filter f; + memset(&f,0,sizeof(f)); + f.re = re; + size_t fl = strlen(filter) + 1; + f.str = malloc(fl); + if (!f.str) + abort(); + memcpy(f.str,filter,fl); + VEC_ADD(filters,f); +#endif // PCRE2FILTER } +#ifdef NEEDBINFILTER static void filters_dedup() { //TODO } +#endif // NEEDBINFILTER static void filters_prepare() { +#ifndef PCRE2FILTER if (!quietflag) fprintf(stderr,"sorting filters..."); filter_sort(); @@ -378,10 +433,17 @@ static void filters_prepare() } if (!quietflag) fprintf(stderr," done.\n"); +#endif } static void filters_clean() { +#ifdef PCRE2FILTER + for (size_t i = 0;i < VEC_LENGTH(filters);++i) { + pcre2_code_free(VEC_BUF(filters,i).re); + free(VEC_BUF(filters,i).str); + } +#endif VEC_FREE(filters); } @@ -450,6 +512,9 @@ do { \ # endif // BINSEARCH +#define PREFILTER +#define POSTFILTER + #endif // INTFILTER @@ -509,9 +574,36 @@ do { \ # endif // BINSEARCH +#define PREFILTER +#define POSTFILTER + #endif // BINFILTER +#ifdef PCRE2FILTER + +#define PREFILTER \ + char pkconvbuf[BASE32_TO_LEN(PUBLIC_LEN) + 1]; \ + pcre2_match_data *pcre2md = pcre2_match_data_create(128,0); + +#define POSTFILTER \ + pcre2_match_data_free(pcre2md); + +#define DOFILTER(it,pk,code) \ +do { \ + base32_to(pkconvbuf,pk,PUBLIC_LEN); \ + size_t __l = VEC_LENGTH(filters); \ + for (it = 0;it < __l;++it) { \ + int rc = pcre2_match(VEC_BUF(filters,it).re,(PCRE2_SPTR8)pkconvbuf,BASE32_TO_LEN(PUBLIC_LEN),0,0,pcre2md,0); \ + if (unlikely(rc >= 0)) { \ + code; \ + break; \ + } \ + } \ +} while (0) + +#endif // PCRE2FILTER + static void loadfilterfile(const char *fname) { @@ -539,8 +631,10 @@ static void filters_print() fprintf(stderr,"filters:\n"); for (i = 0;i < l;++i) { +#ifdef NEEDBINFILTER char buf0[256],buf1[256]; u8 bufx[128]; +#endif if (i >= 20) { size_t notshown = l - i; @@ -568,6 +662,7 @@ static void filters_print() u8 mask = VEC_BUF(filters,i).mask; u8 *ifraw = VEC_BUF(filters,i).f; #endif // BINFILTER +#ifdef NEEDBINFILTER base32_to(buf0,ifraw,len); memcpy(bufx,ifraw,len); bufx[len - 1] |= ~mask; @@ -577,6 +672,10 @@ static void filters_print() ++a, ++b; *a = 0; fprintf(stderr,"\t%s\n",buf0); +#endif // NEEDBINFILTER +#ifdef PCRE2FILTER + fprintf(stderr,"\t%s\n",VEC_BUF(filters,i).str); +#endif // PCRE2FILTER } fprintf(stderr,"in total, %zu %s\n",l,l == 1 ? "filter" : "filters"); } diff --git a/main.c b/main.c index 2b7601d..8319e04 100644 --- a/main.c +++ b/main.c @@ -33,7 +33,8 @@ static char *workdir = 0; static size_t workdirlen = 0; static int quietflag = 0; -static int wantdedup = 0; +//static int wantdedup = 0; +#define wantdedup 0 #define SECRET_LEN 64 #define PUBLIC_LEN 32 @@ -199,6 +200,7 @@ static void *dowork(void *task) #ifdef STATISTICS struct statstruct *st = (struct statstruct *)task; #endif + PREFILTER memcpy(secret,skprefix,skprefixlen); wpk[PUBLIC_LEN] = 0; @@ -267,6 +269,7 @@ next: end: free(sname); + POSTFILTER return 0; } @@ -304,6 +307,7 @@ static void *dofastwork(void *task) #ifdef STATISTICS struct statstruct *st = (struct statstruct *)task; #endif + PREFILTER memcpy(secret, skprefix, skprefixlen); wpk[PUBLIC_LEN] = 0; @@ -381,6 +385,7 @@ initseed: end: free(sname); + POSTFILTER return 0; }