Blame apache2/msc_pcre.c

Packit 284210
/*
Packit 284210
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
Packit 284210
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
Packit 284210
*
Packit 284210
* You may not use this file except in compliance with
Packit 284210
* the License.  You may obtain a copy of the License at
Packit 284210
*
Packit 284210
*     http://www.apache.org/licenses/LICENSE-2.0
Packit 284210
*
Packit 284210
* If any of the files related to licensing are missing or if you have any
Packit 284210
* other questions related to licensing please contact Trustwave Holdings, Inc.
Packit 284210
* directly using the email address security@modsecurity.org.
Packit 284210
*/
Packit 284210
Packit 284210
#include "msc_pcre.h"
Packit 284210
#include "apr_strings.h"
Packit 284210
Packit 284210
/**
Packit 284210
 * Releases the resources used by a single regular expression pattern.
Packit 284210
 */
Packit 284210
static apr_status_t msc_pcre_cleanup(msc_regex_t *regex) {
Packit 284210
    if (regex != NULL) {
Packit 284210
        if (regex->pe != NULL) {
Packit 284210
#if defined(VERSION_NGINX)
Packit 284210
            pcre_free(regex->pe);
Packit 284210
#else
Packit 284210
            free(regex->pe);
Packit 284210
#endif
Packit 284210
            regex->pe = NULL;
Packit 284210
        }
Packit 284210
        if (regex->re != NULL) {
Packit 284210
            pcre_free(regex->re);
Packit 284210
            regex->re = NULL;
Packit 284210
        }
Packit 284210
    }
Packit 284210
Packit 284210
    return APR_SUCCESS;
Packit 284210
}
Packit 284210
Packit 284210
/**
Packit 284210
 * Compiles the provided regular expression pattern. The _err*
Packit 284210
 * parameters are optional, but if they are provided and an error
Packit 284210
 * occurs they will contain the error message and the offset in
Packit 284210
 * the pattern where the offending part of the pattern begins. The
Packit 284210
 * match_limit* parameters are optional and if >0, then will set
Packit 284210
 * match limits.
Packit 284210
 */
Packit 284210
void *msc_pregcomp_ex(apr_pool_t *pool, const char *pattern, int options,
Packit 284210
                      const char **_errptr, int *_erroffset,
Packit 284210
                      int match_limit, int match_limit_recursion)
Packit 284210
{
Packit 284210
    const char *errptr = NULL;
Packit 284210
    int erroffset;
Packit 284210
    msc_regex_t *regex;
Packit 284210
    pcre_extra *pe = NULL;
Packit 284210
Packit 284210
    regex = apr_pcalloc(pool, sizeof(msc_regex_t));
Packit 284210
    if (regex == NULL) return NULL;
Packit 284210
    regex->pattern = pattern;
Packit 284210
Packit 284210
    if ((_errptr == NULL)||(_erroffset == NULL)) {
Packit 284210
        regex->re = pcre_compile(pattern, options, &errptr, &erroffset, NULL);
Packit 284210
    } else {
Packit 284210
        regex->re = pcre_compile(pattern, options, _errptr, _erroffset, NULL);
Packit 284210
    }
Packit 284210
    if (regex->re == NULL) return NULL;
Packit 284210
Packit 284210
    #ifdef WITH_PCRE_STUDY
Packit 284210
        #ifdef WITH_PCRE_JIT
Packit 284210
                pe = pcre_study(regex->re, PCRE_STUDY_JIT_COMPILE, &errptr);
Packit 284210
        #else
Packit 284210
                pe = pcre_study(regex->re, 0, &errptr);
Packit 284210
        #endif
Packit 284210
    #endif
Packit 284210
Packit 284210
    /* Setup the pcre_extra record if pcre_study did not already do it */
Packit 284210
    if (pe == NULL) {
Packit 284210
#if defined(VERSION_NGINX)
Packit 284210
        pe = pcre_malloc(sizeof(pcre_extra));
Packit 284210
#else
Packit 284210
        pe = malloc(sizeof(pcre_extra));
Packit 284210
#endif
Packit 284210
        if (pe == NULL) {
Packit 284210
            return NULL;
Packit 284210
        }
Packit 284210
        memset(pe, 0, sizeof(pcre_extra));
Packit 284210
    }
Packit 284210
Packit 284210
#ifdef PCRE_EXTRA_MATCH_LIMIT
Packit 284210
    /* If match limit is available, then use it */
Packit 284210
Packit 284210
    /* Use ModSecurity runtime defaults */
Packit 284210
    if (match_limit > 0) {
Packit 284210
        pe->match_limit = match_limit;
Packit 284210
        pe->flags |= PCRE_EXTRA_MATCH_LIMIT;
Packit 284210
    }
Packit 284210
#ifdef MODSEC_PCRE_MATCH_LIMIT
Packit 284210
    /* Default to ModSecurity compiled defaults */
Packit 284210
    else {
Packit 284210
        pe->match_limit = MODSEC_PCRE_MATCH_LIMIT;
Packit 284210
        pe->flags |= PCRE_EXTRA_MATCH_LIMIT;
Packit 284210
    }
Packit 284210
#endif /* MODSEC_PCRE_MATCH_LIMIT */
Packit 284210
#else
Packit 284210
#pragma message ( "This PCRE version does not support match limits!  Upgrade to at least PCRE v6.5." )
Packit 284210
#endif /* PCRE_EXTRA_MATCH_LIMIT */
Packit 284210
Packit 284210
#ifdef PCRE_EXTRA_MATCH_LIMIT_RECURSION
Packit 284210
    /* If match limit recursion is available, then use it */
Packit 284210
Packit 284210
    /* Use ModSecurity runtime defaults */
Packit 284210
    if (match_limit_recursion > 0) {
Packit 284210
        pe->match_limit_recursion = match_limit_recursion;
Packit 284210
        pe->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
Packit 284210
    }
Packit 284210
#ifdef MODSEC_PCRE_MATCH_LIMIT_RECURSION
Packit 284210
    /* Default to ModSecurity compiled defaults */
Packit 284210
    else {
Packit 284210
        pe->match_limit_recursion = MODSEC_PCRE_MATCH_LIMIT_RECURSION;
Packit 284210
        pe->flags |= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
Packit 284210
    }
Packit 284210
#endif /* MODSEC_PCRE_MATCH_LIMIT_RECURSION */
Packit 284210
#else
Packit 284210
#pragma message ( "This PCRE version does not support match recursion limits!  Upgrade to at least PCRE v6.5." )
Packit 284210
#endif /* PCRE_EXTRA_MATCH_LIMIT_RECURSION */
Packit 284210
Packit 284210
    regex->pe = pe;
Packit 284210
Packit 284210
    apr_pool_cleanup_register(pool, (void *)regex,
Packit 284210
        (apr_status_t (*)(void *))msc_pcre_cleanup, apr_pool_cleanup_null);
Packit 284210
Packit 284210
    return regex;
Packit 284210
}
Packit 284210
Packit 284210
/**
Packit 284210
 * Compiles the provided regular expression pattern.  Calls msc_pregcomp_ex()
Packit 284210
 * with default limits.
Packit 284210
 */
Packit 284210
void *msc_pregcomp(apr_pool_t *pool, const char *pattern, int options,
Packit 284210
                   const char **_errptr, int *_erroffset)
Packit 284210
{
Packit 284210
    return msc_pregcomp_ex(pool, pattern, options, _errptr, _erroffset, 0, 0);
Packit 284210
}
Packit 284210
Packit 284210
/**
Packit 284210
 * Executes regular expression with extended options.
Packit 284210
 * Returns PCRE_ERROR_NOMATCH when there is no match, error code < -1
Packit 284210
 * on errors, and a value > 0 when there is a match.
Packit 284210
 */
Packit 284210
int msc_regexec_ex(msc_regex_t *regex, const char *s, unsigned int slen,
Packit 284210
    int startoffset, int options, int *ovector, int ovecsize, char **error_msg)
Packit 284210
{
Packit 284210
    if (error_msg == NULL) return -1000; /* To differentiate from PCRE as it already uses -1. */
Packit 284210
    *error_msg = NULL;
Packit 284210
Packit 284210
    return pcre_exec(regex->re, regex->pe, s, slen, startoffset, options, ovector, ovecsize);
Packit 284210
}
Packit 284210
Packit 284210
/**
Packit 284210
 * Executes regular expression, capturing subexpressions in the given
Packit 284210
 * vector. Returns PCRE_ERROR_NOMATCH when there is no match, error code < -1
Packit 284210
 * on errors, and a value > 0 when there is a match.
Packit 284210
 */
Packit 284210
int msc_regexec_capture(msc_regex_t *regex, const char *s, unsigned int slen,
Packit 284210
    int *ovector, int ovecsize, char **error_msg)
Packit 284210
{
Packit 284210
    if (error_msg == NULL) return -1000; /* To differentiate from PCRE as it already uses -1. */
Packit 284210
    *error_msg = NULL;
Packit 284210
Packit 284210
    return msc_regexec_ex(regex, s, slen, 0, 0, ovector, ovecsize, error_msg);
Packit 284210
}
Packit 284210
Packit 284210
/**
Packit 284210
 * Executes regular expression but ignores any of the subexpression
Packit 284210
 * captures. See above for the return codes.
Packit 284210
 */
Packit 284210
int msc_regexec(msc_regex_t *regex, const char *s, unsigned int slen,
Packit 284210
    char **error_msg)
Packit 284210
{
Packit 284210
    if (error_msg == NULL) return -1000; /* To differentiate from PCRE as it already uses -1. */
Packit 284210
    *error_msg = NULL;
Packit 284210
Packit 284210
    return msc_regexec_ex(regex, s, slen, 0, 0, NULL, 0, error_msg);
Packit 284210
}
Packit 284210
Packit 284210
/**
Packit 284210
 * Gets info on a compiled regex.
Packit 284210
 */
Packit 284210
int msc_fullinfo(msc_regex_t *regex, int what, void *where)
Packit 284210
{
Packit 284210
    return pcre_fullinfo(regex->re, regex->pe, what, where);
Packit 284210
}
Packit 284210