~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to server/util_pcre.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*************************************************
 
2
*      Perl-Compatible Regular Expressions       *
 
3
*************************************************/
 
4
 
 
5
/*
 
6
This is a library of functions to support regular expressions whose syntax
 
7
and semantics are as close as possible to those of the Perl 5 language. See
 
8
the file Tech.Notes for some information on the internals.
 
9
 
 
10
This module is a wrapper that provides a POSIX API to the underlying PCRE
 
11
functions.
 
12
 
 
13
Written by: Philip Hazel <ph10@cam.ac.uk>
 
14
 
 
15
           Copyright (c) 1997-2004 University of Cambridge
 
16
 
 
17
-----------------------------------------------------------------------------
 
18
Redistribution and use in source and binary forms, with or without
 
19
modification, are permitted provided that the following conditions are met:
 
20
 
 
21
    * Redistributions of source code must retain the above copyright notice,
 
22
      this list of conditions and the following disclaimer.
 
23
 
 
24
    * Redistributions in binary form must reproduce the above copyright
 
25
      notice, this list of conditions and the following disclaimer in the
 
26
      documentation and/or other materials provided with the distribution.
 
27
 
 
28
    * Neither the name of the University of Cambridge nor the names of its
 
29
      contributors may be used to endorse or promote products derived from
 
30
      this software without specific prior written permission.
 
31
 
 
32
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
33
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
34
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
35
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 
36
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
37
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
38
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
39
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
40
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
41
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
42
POSSIBILITY OF SUCH DAMAGE.
 
43
-----------------------------------------------------------------------------
 
44
*/
 
45
 
 
46
#include "httpd.h"
 
47
#include "apr_strings.h"
 
48
#include "pcre.h"
 
49
 
 
50
#define APR_WANT_STRFUNC
 
51
#include "apr_want.h"
 
52
 
 
53
#ifndef POSIX_MALLOC_THRESHOLD
 
54
#define POSIX_MALLOC_THRESHOLD (10)
 
55
#endif
 
56
 
 
57
/* Table of error strings corresponding to POSIX error codes; must be
 
58
 * kept in synch with include/ap_regex.h's AP_REG_E* definitions. */
 
59
 
 
60
static const char *const pstring[] = {
 
61
  "",                                /* Dummy for value 0 */
 
62
  "internal error",                  /* AP_REG_ASSERT */
 
63
  "failed to get memory",            /* AP_REG_ESPACE */
 
64
  "bad argument",                    /* AP_REG_INVARG */
 
65
  "match failed"                     /* AP_REG_NOMATCH */
 
66
};
 
67
 
 
68
AP_DECLARE(apr_size_t) ap_regerror(int errcode, const ap_regex_t *preg,
 
69
                                   char *errbuf, apr_size_t errbuf_size)
 
70
{
 
71
const char *message, *addmessage;
 
72
apr_size_t length, addlength;
 
73
 
 
74
message = (errcode >= (int)(sizeof(pstring)/sizeof(char *)))?
 
75
  "unknown error code" : pstring[errcode];
 
76
length = strlen(message) + 1;
 
77
 
 
78
addmessage = " at offset ";
 
79
addlength = (preg != NULL && (int)preg->re_erroffset != -1)?
 
80
  strlen(addmessage) + 6 : 0;
 
81
 
 
82
if (errbuf_size > 0)
 
83
  {
 
84
  if (addlength > 0 && errbuf_size >= length + addlength)
 
85
      apr_snprintf(errbuf, sizeof errbuf,
 
86
                   "%s%s%-6d", message, addmessage, (int)preg->re_erroffset);
 
87
  else
 
88
    {
 
89
    strncpy(errbuf, message, errbuf_size - 1);
 
90
    errbuf[errbuf_size-1] = 0;
 
91
    }
 
92
  }
 
93
 
 
94
return length + addlength;
 
95
}
 
96
 
 
97
 
 
98
 
 
99
 
 
100
/*************************************************
 
101
*           Free store held by a regex           *
 
102
*************************************************/
 
103
 
 
104
AP_DECLARE(void) ap_regfree(ap_regex_t *preg)
 
105
{
 
106
(pcre_free)(preg->re_pcre);
 
107
}
 
108
 
 
109
 
 
110
 
 
111
 
 
112
/*************************************************
 
113
*            Compile a regular expression        *
 
114
*************************************************/
 
115
 
 
116
/*
 
117
Arguments:
 
118
  preg        points to a structure for recording the compiled expression
 
119
  pattern     the pattern to compile
 
120
  cflags      compilation flags
 
121
 
 
122
Returns:      0 on success
 
123
              various non-zero codes on failure
 
124
*/
 
125
 
 
126
AP_DECLARE(int) ap_regcomp(ap_regex_t *preg, const char *pattern, int cflags)
 
127
{
 
128
const char *errorptr;
 
129
int erroffset;
 
130
int options = 0;
 
131
 
 
132
if ((cflags & AP_REG_ICASE) != 0) options |= PCRE_CASELESS;
 
133
if ((cflags & AP_REG_NEWLINE) != 0) options |= PCRE_MULTILINE;
 
134
 
 
135
preg->re_pcre = pcre_compile(pattern, options, &errorptr, &erroffset, NULL);
 
136
preg->re_erroffset = erroffset;
 
137
 
 
138
if (preg->re_pcre == NULL) return AP_REG_INVARG;
 
139
 
 
140
preg->re_nsub = pcre_info((const pcre *)preg->re_pcre, NULL, NULL);
 
141
return 0;
 
142
}
 
143
 
 
144
 
 
145
 
 
146
 
 
147
/*************************************************
 
148
*              Match a regular expression        *
 
149
*************************************************/
 
150
 
 
151
/* Unfortunately, PCRE requires 3 ints of working space for each captured
 
152
substring, so we have to get and release working store instead of just using
 
153
the POSIX structures as was done in earlier releases when PCRE needed only 2
 
154
ints. However, if the number of possible capturing brackets is small, use a
 
155
block of store on the stack, to reduce the use of malloc/free. The threshold is
 
156
in a macro that can be changed at configure time. */
 
157
 
 
158
AP_DECLARE(int) ap_regexec(const ap_regex_t *preg, const char *string,
 
159
                           apr_size_t nmatch, ap_regmatch_t pmatch[],
 
160
                           int eflags)
 
161
{
 
162
int rc;
 
163
int options = 0;
 
164
int *ovector = NULL;
 
165
int small_ovector[POSIX_MALLOC_THRESHOLD * 3];
 
166
int allocated_ovector = 0;
 
167
 
 
168
if ((eflags & AP_REG_NOTBOL) != 0) options |= PCRE_NOTBOL;
 
169
if ((eflags & AP_REG_NOTEOL) != 0) options |= PCRE_NOTEOL;
 
170
 
 
171
((ap_regex_t *)preg)->re_erroffset = (apr_size_t)(-1);  /* Only has meaning after compile */
 
172
 
 
173
if (nmatch > 0)
 
174
  {
 
175
  if (nmatch <= POSIX_MALLOC_THRESHOLD)
 
176
    {
 
177
    ovector = &(small_ovector[0]);
 
178
    }
 
179
  else
 
180
    {
 
181
    ovector = (int *)malloc(sizeof(int) * nmatch * 3);
 
182
    if (ovector == NULL) return AP_REG_ESPACE;
 
183
    allocated_ovector = 1;
 
184
    }
 
185
  }
 
186
 
 
187
rc = pcre_exec((const pcre *)preg->re_pcre, NULL, string, (int)strlen(string),
 
188
  0, options, ovector, nmatch * 3);
 
189
 
 
190
if (rc == 0) rc = nmatch;    /* All captured slots were filled in */
 
191
 
 
192
if (rc >= 0)
 
193
  {
 
194
  apr_size_t i;
 
195
  for (i = 0; i < (apr_size_t)rc; i++)
 
196
    {
 
197
    pmatch[i].rm_so = ovector[i*2];
 
198
    pmatch[i].rm_eo = ovector[i*2+1];
 
199
    }
 
200
  if (allocated_ovector) free(ovector);
 
201
  for (; i < nmatch; i++) pmatch[i].rm_so = pmatch[i].rm_eo = -1;
 
202
  return 0;
 
203
  }
 
204
 
 
205
else
 
206
  {
 
207
  if (allocated_ovector) free(ovector);
 
208
  switch(rc)
 
209
    {
 
210
    case PCRE_ERROR_NOMATCH: return AP_REG_NOMATCH;
 
211
    case PCRE_ERROR_NULL: return AP_REG_INVARG;
 
212
    case PCRE_ERROR_BADOPTION: return AP_REG_INVARG;
 
213
    case PCRE_ERROR_BADMAGIC: return AP_REG_INVARG;
 
214
    case PCRE_ERROR_UNKNOWN_NODE: return AP_REG_ASSERT;
 
215
    case PCRE_ERROR_NOMEMORY: return AP_REG_ESPACE;
 
216
#ifdef PCRE_ERROR_MATCHLIMIT
 
217
    case PCRE_ERROR_MATCHLIMIT: return AP_REG_ESPACE;
 
218
#endif
 
219
#ifdef PCRE_ERROR_BADUTF8
 
220
    case PCRE_ERROR_BADUTF8: return AP_REG_INVARG;
 
221
#endif
 
222
#ifdef PCRE_ERROR_BADUTF8_OFFSET
 
223
    case PCRE_ERROR_BADUTF8_OFFSET: return AP_REG_INVARG;
 
224
#endif
 
225
    default: return AP_REG_ASSERT;
 
226
    }
 
227
  }
 
228
}
 
229
 
 
230
/* End of pcreposix.c */