Esempio n. 1
0
int regex_match_substring(tvh_regex_t *regex, unsigned number, char *buf, size_t size_buf)
{
  assert(buf);
  if (number >= TVHREGEX_MAX_MATCHES)
    return -2;
#if ENABLE_PCRE || ENABLE_PCRE2
  if (regex->is_posix) {
#endif
    if (regex->re_posix_match[number].rm_so == -1)
      return -1;
    ssize_t size = regex->re_posix_match[number].rm_eo - regex->re_posix_match[number].rm_so;
    if (size < 0 || size > (size_buf - 1))
      return -1;
    strlcpy(buf, regex->re_posix_text + regex->re_posix_match[number].rm_so, size + 1);
    return 0;
#if ENABLE_PCRE || ENABLE_PCRE2
  } else {
#if ENABLE_PCRE
    return pcre_copy_substring(regex->re_text, regex->re_match,
                               (regex->re_matches == 0)
                               ? TVHREGEX_MAX_MATCHES
                               : regex->re_matches,
                               number, buf, size_buf) < 0;
#elif ENABLE_PCRE2
    PCRE2_SIZE psiz = size_buf;
    return pcre2_substring_copy_bynumber(regex->re_match, number, (PCRE2_UCHAR8*)buf, &psiz);
#endif
  }
#endif
}
Esempio n. 2
0
/** Extract a subcapture value from the request
 *
 * @note This is the PCRE variant of the function.
 *
 * @param[in] ctx	To allocate subcapture buffer in.
 * @param[out] out	Where to write the subcapture string.
 * @param[in] request	to extract.
 * @param[in] num	Subcapture index (0 for entire match).
 * @return
 *	- 0 on success.
 *	- -1 on notfound.
 */
int regex_request_to_sub(TALLOC_CTX *ctx, char **out, REQUEST *request, uint32_t num)
{
	fr_regcapture_t		*rc;
	char			*buff;
	size_t			len;
	int			ret;
	pcre2_match_data	*match_data;

	rc = request_data_reference(request, request, REQUEST_DATA_REGEX);
	if (!rc) {
		RDEBUG4("No subcapture data found");
		*out = NULL;
		return 1;
	}
	match_data = talloc_get_type_abort(rc->regmatch->match_data, pcre2_match_data);

	ret = pcre2_substring_length_bynumber(match_data, num, &len);
	switch (ret) {
	case PCRE2_ERROR_NOMEMORY:
		MEM(NULL);
		/*
		 *	We can't really fall through, but GCC 7.3 is
		 *	too stupid to realise that we can never get
		 *	here despite _fr_exit_now being marked as
		 *	NEVER_RETURNS.
		 *
		 *	If we did anything else, compilers and static
		 *	analysis tools would probably complain about
		 *	code that could never be executed *sigh*.
		 */
		/* FALL-THROUGH */

	/*
	 *	Not finding a substring is fine
	 */
	case PCRE2_ERROR_NOSUBSTRING:
		RDEBUG4("%i/%zu Not found", num + 1, rc->regmatch->used);
		*out = NULL;
		return -1;

	default:
		if (ret < 0) {
			*out = NULL;
			return -1;
		}

		MEM(buff = talloc_array(ctx, char, ++len));	/* +1 for \0, it'll get reset by pcre2_substring */
		pcre2_substring_copy_bynumber(match_data, num, (PCRE2_UCHAR *)buff, &len); /* can't error */

		RDEBUG4("%i/%zu Found: %pV (%zu)", num + 1, rc->regmatch->used,
			fr_box_strvalue_buffer(buff), talloc_array_length(buff) - 1);

		*out = buff;
		break;
	}

	return 0;
}
Esempio n. 3
0
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_substring_copy_byname(pcre2_match_data *match_data, PCRE2_SPTR stringname,
  PCRE2_UCHAR *buffer, PCRE2_SIZE *sizeptr)
{
PCRE2_SPTR first, last, entry;
int failrc, entrysize;
if (match_data->matchedby == PCRE2_MATCHEDBY_DFA_INTERPRETER)
  return PCRE2_ERROR_DFA_UFUNC;
entrysize = pcre2_substring_nametable_scan(match_data->code, stringname,
  &first, &last);
if (entrysize < 0) return entrysize;
failrc = PCRE2_ERROR_UNAVAILABLE;
for (entry = first; entry <= last; entry += entrysize)
  {
  uint32_t n = GET2(entry, 0);
  if (n < match_data->oveccount)
    {
    if (match_data->ovector[n*2] != PCRE2_UNSET)
      return pcre2_substring_copy_bynumber(match_data, n, buffer, sizeptr);
    failrc = PCRE2_ERROR_UNSET;
    }
  }
return failrc;
}
Esempio n. 4
0
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_substitute(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,
  PCRE2_SIZE start_offset, uint32_t options, pcre2_match_data *match_data,
  pcre2_match_context *mcontext, PCRE2_SPTR replacement, PCRE2_SIZE rlength,
  PCRE2_UCHAR *buffer, PCRE2_SIZE *blength)
{
int rc;
int subs;
uint32_t ovector_count;
uint32_t goptions = 0;
BOOL match_data_created = FALSE;
BOOL global = FALSE;
PCRE2_SIZE buff_offset, lengthleft, fraglength;
PCRE2_SIZE *ovector;

/* Partial matching is not valid. */

if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0)
  return PCRE2_ERROR_BADOPTION;

/* If no match data block is provided, create one. */

if (match_data == NULL)
  {
  pcre2_general_context *gcontext = (mcontext == NULL)?
    (pcre2_general_context *)code :
    (pcre2_general_context *)mcontext;
  match_data = pcre2_match_data_create_from_pattern(code, gcontext);
  if (match_data == NULL) return PCRE2_ERROR_NOMEMORY;
  match_data_created = TRUE;
  }
ovector = pcre2_get_ovector_pointer(match_data);
ovector_count = pcre2_get_ovector_count(match_data);

/* Check UTF replacement string if necessary. */

#ifdef SUPPORT_UNICODE
if ((code->overall_options & PCRE2_UTF) != 0 &&
    (options & PCRE2_NO_UTF_CHECK) == 0)
  {
  rc = PRIV(valid_utf)(replacement, rlength, &(match_data->rightchar));
  if (rc != 0)
    {
    match_data->leftchar = 0;
    goto EXIT;
    }
  }
#endif  /* SUPPORT_UNICODE */

/* Notice the global option and remove it from the options that are passed to
pcre2_match(). */

if ((options & PCRE2_SUBSTITUTE_GLOBAL) != 0)
  {
  options &= ~PCRE2_SUBSTITUTE_GLOBAL;
  global = TRUE;
  }

/* Find lengths of zero-terminated strings. */

if (length == PCRE2_ZERO_TERMINATED) length = PRIV(strlen)(subject);
if (rlength == PCRE2_ZERO_TERMINATED) rlength = PRIV(strlen)(replacement);

/* Copy up to the start offset */

if (start_offset > *blength) goto NOROOM;
memcpy(buffer, subject, start_offset * (PCRE2_CODE_UNIT_WIDTH/8));
buff_offset = start_offset;
lengthleft = *blength - start_offset;

/* Loop for global substituting. */

subs = 0;
do
  {
  PCRE2_SIZE i;

  rc = pcre2_match(code, subject, length, start_offset, options|goptions,
    match_data, mcontext);

  /* Any error other than no match returns the error code. No match when not
  doing the special after-empty-match global rematch, or when at the end of the
  subject, breaks the global loop. Otherwise, advance the starting point by one
  character, copying it to the output, and try again. */

  if (rc < 0)
    {
    PCRE2_SIZE save_start;

    if (rc != PCRE2_ERROR_NOMATCH) goto EXIT;
    if (goptions == 0 || start_offset >= length) break;

    save_start = start_offset++;
    if ((code->overall_options & PCRE2_UTF) != 0)
      {
#if PCRE2_CODE_UNIT_WIDTH == 8
      while (start_offset < length && (subject[start_offset] & 0xc0) == 0x80)
        start_offset++;
#elif PCRE2_CODE_UNIT_WIDTH == 16
      while (start_offset < length &&
            (subject[start_offset] & 0xfc00) == 0xdc00)
        start_offset++;
#endif
      }

    fraglength = start_offset - save_start;
    if (lengthleft < fraglength) goto NOROOM;
    memcpy(buffer + buff_offset, subject + save_start,
      fraglength*(PCRE2_CODE_UNIT_WIDTH/8));
    buff_offset += fraglength;
    lengthleft -= fraglength;

    goptions = 0;
    continue;
    }

  /* Handle a successful match. */

  subs++;
  if (rc == 0) rc = ovector_count;
  fraglength = ovector[0] - start_offset;
  if (fraglength >= lengthleft) goto NOROOM;
  memcpy(buffer + buff_offset, subject + start_offset,
    fraglength*(PCRE2_CODE_UNIT_WIDTH/8));
  buff_offset += fraglength;
  lengthleft -= fraglength;

  for (i = 0; i < rlength; i++)
    {
    if (replacement[i] == CHAR_DOLLAR_SIGN)
      {
      int group, n;
      BOOL inparens;
      PCRE2_SIZE sublength;
      PCRE2_UCHAR next;
      PCRE2_UCHAR name[33];

      if (++i == rlength) goto BAD;
      if ((next = replacement[i]) == CHAR_DOLLAR_SIGN) goto LITERAL;

      group = -1;
      n = 0;
      inparens = FALSE;

      if (next == CHAR_LEFT_CURLY_BRACKET)
        {
        if (++i == rlength) goto BAD;
        next = replacement[i];
        inparens = TRUE;
        }

      if (next >= CHAR_0 && next <= CHAR_9)
        {
        group = next - CHAR_0;
        while (i < rlength - 1)
          {
          next = replacement[++i];
          if (next < CHAR_0 || next > CHAR_9) break;
          group = group * 10 + next - CHAR_0;
          }
        }
      else
        {
        const uint8_t *ctypes = code->tables + ctypes_offset;
        while (MAX_255(next) && (ctypes[next] & ctype_word) != 0)
          {
          name[n++] = next;
          if (n > 32) goto BAD;
          if (i == rlength) break;
          next = replacement[++i];
          }
        if (n == 0) goto BAD;
        name[n] = 0;
        }

      if (inparens)
        {
        if (i == rlength || next != CHAR_RIGHT_CURLY_BRACKET) goto BAD;
        }
      else i--;   /* Last code unit of name/number */

      /* Have found a syntactically correct group number or name. */

      sublength = lengthleft;
      if (group < 0)
        rc = pcre2_substring_copy_byname(match_data, name,
          buffer + buff_offset, &sublength);
      else
        rc = pcre2_substring_copy_bynumber(match_data, group,
          buffer + buff_offset, &sublength);

      if (rc < 0) goto EXIT;
      buff_offset += sublength;
      lengthleft -= sublength;
      }

   /* Handle a literal code unit */

   else
      {
      LITERAL:
      if (lengthleft-- < 1) goto NOROOM;
      buffer[buff_offset++] = replacement[i];
      }
    }

  /* The replacement has been copied to the output. Update the start offset to
  point to the rest of the subject string. If we matched an empty string,
  do the magic for global matches. */

  start_offset = ovector[1];
  goptions = (ovector[0] != ovector[1])? 0 :
    PCRE2_ANCHORED|PCRE2_NOTEMPTY_ATSTART;
  } while (global);  /* Repeat "do" loop */

/* Copy the rest of the subject and return the number of substitutions. */

rc = subs;
fraglength = length - start_offset;
if (fraglength + 1 > lengthleft) goto NOROOM;
memcpy(buffer + buff_offset, subject + start_offset,
  fraglength*(PCRE2_CODE_UNIT_WIDTH/8));
buff_offset += fraglength;
buffer[buff_offset] = 0;
*blength = buff_offset;

EXIT:
if (match_data_created) pcre2_match_data_free(match_data);
  else match_data->rc = rc;
return rc;

NOROOM:
rc = PCRE2_ERROR_NOMEMORY;
goto EXIT;

BAD:
rc = PCRE2_ERROR_BADREPLACEMENT;
goto EXIT;
}