static int pcre2match(struct grep_pat *p, const char *line, const char *eol, regmatch_t *match, int eflags) { int ret, flags = 0; PCRE2_SIZE *ovector; PCRE2_UCHAR errbuf[256]; if (eflags & REG_NOTBOL) flags |= PCRE2_NOTBOL; if (p->pcre2_jit_on) ret = pcre2_jit_match(p->pcre2_pattern, (unsigned char *)line, eol - line, 0, flags, p->pcre2_match_data, NULL); else ret = pcre2_match(p->pcre2_pattern, (unsigned char *)line, eol - line, 0, flags, p->pcre2_match_data, NULL); if (ret < 0 && ret != PCRE2_ERROR_NOMATCH) { pcre2_get_error_message(ret, errbuf, sizeof(errbuf)); die("%s failed with error code %d: %s", (p->pcre2_jit_on ? "pcre2_jit_match" : "pcre2_match"), ret, errbuf); } if (ret > 0) { ovector = pcre2_get_ovector_pointer(p->pcre2_match_data); ret = 0; match->rm_so = (int)ovector[0]; match->rm_eo = (int)ovector[1]; } return ret; }
/* PCRE 2 version */ gboolean rspamd_regexp_search (rspamd_regexp_t *re, const gchar *text, gsize len, const gchar **start, const gchar **end, gboolean raw, GArray *captures) { pcre2_match_data *match_data; pcre2_match_context *mcontext; PCRE_T *r; const gchar *mt; gsize remain = 0, *ovec; gint rc, match_flags, novec, i; gboolean ret = FALSE; g_assert (re != NULL); g_assert (text != NULL); if (len == 0) { len = strlen (text); } if (end != NULL && *end != NULL) { /* Incremental search */ mt = (*end); if ((gint)len > (mt - text)) { remain = len - (mt - text); } } else { mt = text; remain = len; } if (remain == 0) { return FALSE; } match_flags = 0; if (raw || re->re == re->raw_re) { r = re->raw_re; mcontext = re->raw_mcontext; } else { r = re->re; mcontext = re->mcontext; } match_data = pcre2_match_data_create (re->ncaptures + 1, NULL); #ifdef HAVE_PCRE_JIT if (!(re->flags & RSPAMD_REGEXP_FLAG_DISABLE_JIT) && can_jit) { if (re->re != re->raw_re && !g_utf8_validate (mt, remain, NULL)) { msg_err ("bad utf8 input for JIT re"); return FALSE; } rc = pcre2_jit_match (r, mt, remain, 0, match_flags, match_data, mcontext); } else { rc = pcre2_match (r, mt, remain, 0, match_flags, match_data, mcontext); } #else rc = pcre2_match (r, mt, remain, 0, match_flags, match_data, mcontext); #endif if (rc >= 0) { novec = pcre2_get_ovector_count (match_data); ovec = pcre2_get_ovector_pointer (match_data); if (start) { *start = mt + ovec[0]; } if (end) { *end = mt + ovec[1]; } if (captures != NULL && novec > 1) { struct rspamd_re_capture *elt; g_assert (g_array_get_element_size (captures) == sizeof (struct rspamd_re_capture)); g_array_set_size (captures, novec); for (i = 0; i < novec; i ++) { elt = &g_array_index (captures, struct rspamd_re_capture, i); elt->p = mt + ovec[i * 2]; elt->len = (mt + ovec[i * 2 + 1]) - elt->p; } } ret = TRUE; if (re->flags & RSPAMD_REGEXP_FLAG_FULL_MATCH) { /* We also ensure that the match is full */ if (ovec[0] != 0 || (guint)ovec[1] < len) { ret = FALSE; } } }