* 20211221.15 (2.5.1-dev) Add ap_get_pollfd_from_conn()
* 20211221.16 (2.5.1-dev) Add ap_proxy_determine_address()
* 20211221.17 (2.5.1-dev) Add ap_proxy_worker_get_name()
+ * 20211221.18 (2.5.1-dev) Add ap_regexec_ex()
*/
#define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20211221
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 17 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 18 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
* @return 0 for successful match, \p AP_REG_NOMATCH otherwise
*/
AP_DECLARE(int) ap_regexec(const ap_regex_t *preg, const char *string,
- apr_size_t nmatch, ap_regmatch_t *pmatch, int eflags);
+ apr_size_t nmatch, ap_regmatch_t *pmatch,
+ int eflags);
/**
* Match a string with given length against a pre-compiled regex. The string
* other flags are ignored)
* @return 0 for successful match, AP_REG_NOMATCH otherwise
*/
-AP_DECLARE(int) ap_regexec_len(const ap_regex_t *preg, const char *buff,
- apr_size_t len, apr_size_t nmatch,
- ap_regmatch_t *pmatch, int eflags);
+AP_DECLARE(int) ap_regexec_len(const ap_regex_t *preg,
+ const char *buff, apr_size_t len,
+ apr_size_t nmatch, ap_regmatch_t *pmatch,
+ int eflags);
+/**
+ * Match a string with given length and at a given offset against a
+ * pre-compiled regex. The string does not need to be NUL-terminated.
+ * @param preg The pre-compiled regex
+ * @param buff The string to match
+ * @param len Length of the string to match
+ * @param pos Offset in the string where the match should (re)start
+ * @param nmatch Provide information regarding the location of any matches
+ * @param pmatch Provide information regarding the location of any matches
+ * @param eflags Bitwise OR of AP_REG_* flags (NOTBOL and NOTEOL supported,
+ * other flags are ignored)
+ * @return 0 for successful match, AP_REG_NOMATCH otherwise
+ */
+AP_DECLARE(int) ap_regexec_ex(const ap_regex_t *preg,
+ const char *buff, apr_size_t len, apr_size_t pos,
+ apr_size_t nmatch, ap_regmatch_t *pmatch,
+ int eflags);
/**
* Return the error code returned by regcomp or regexec into error messages
* @param errcode the error code returned by regexec or regcomp
apr_size_t nmatch, ap_regmatch_t *pmatch,
int eflags)
{
- return ap_regexec_len(preg, string, strlen(string), nmatch, pmatch,
- eflags);
+ return ap_regexec_ex(preg, string, strlen(string), 0,
+ nmatch, pmatch, eflags);
}
-AP_DECLARE(int) ap_regexec_len(const ap_regex_t *preg, const char *buff,
- apr_size_t len, apr_size_t nmatch,
- ap_regmatch_t *pmatch, int eflags)
+AP_DECLARE(int) ap_regexec_len(const ap_regex_t *preg,
+ const char *buff, apr_size_t len,
+ apr_size_t nmatch, ap_regmatch_t *pmatch,
+ int eflags)
+{
+ return ap_regexec_ex(preg, buff, len, 0, nmatch, pmatch, eflags);
+}
+
+AP_DECLARE(int) ap_regexec_ex(const ap_regex_t *preg,
+ const char *buff, apr_size_t len, apr_size_t pos,
+ apr_size_t nmatch, ap_regmatch_t *pmatch,
+ int eflags)
{
int rc;
int options = 0;
apr_uint32_t ncaps = (apr_uint32_t)preg->re_nsub + 1;
#ifndef HAVE_PCRE2
+ /* PCRE1 uses ints, reject overflowing values */
+ if (len > APR_INT32_MAX || pos > APR_INT32_MAX) {
+ return AP_REG_INVARG;
+ }
+
/* This is fine if pcre_exec() gets a vector size smaller than the
* number of capturing groups (it will treat the remaining ones as
* non-capturing), but if the vector is too small to keep track of
#ifdef HAVE_PCRE2
rc = pcre2_match((const pcre2_code *)preg->re_pcre,
- (const unsigned char *)buff, len, 0, options,
+ (const unsigned char *)buff, len, pos, options,
state.match_data, NULL);
ovector = pcre2_get_ovector_pointer(state.match_data);
#else
ovector = state.match_data;
- rc = pcre_exec((const pcre *)preg->re_pcre, NULL, buff, (int)len,
- 0, options, ovector, ncaps * 3);
+ rc = pcre_exec((const pcre *)preg->re_pcre, NULL,
+ buff, (int)len, (int)pos, options,
+ ovector, ncaps * 3);
#endif
if (rc >= 0) {