2 * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
20 #include <isc/regex.h>
21 #include <isc/string.h>
23 #if VALREGEX_REPORT_REASON
24 #define FAIL(x) do { reason = (x); goto error; } while(0)
26 #define FAIL(x) goto error
30 * Validate the regular expression 'C' locale.
33 isc_regex_validate(const char *c) {
35 none, parse_bracket, parse_bound,
36 parse_ce, parse_ec, parse_cc
38 /* Well known character classes. */
40 ":alnum:", ":digit:", ":punct:", ":alpha:", ":graph:",
41 ":space:", ":blank:", ":lower:", ":upper:", ":cntrl:",
44 isc_boolean_t seen_comma = ISC_FALSE;
45 isc_boolean_t seen_high = ISC_FALSE;
46 isc_boolean_t seen_char = ISC_FALSE;
47 isc_boolean_t seen_ec = ISC_FALSE;
48 isc_boolean_t seen_ce = ISC_FALSE;
49 isc_boolean_t have_atom = ISC_FALSE;
53 isc_boolean_t empty_ok = ISC_FALSE;
54 isc_boolean_t neg = ISC_FALSE;
55 isc_boolean_t was_multiple = ISC_FALSE;
57 unsigned int high = 0;
58 const char *ccname = NULL;
60 #if VALREGEX_REPORT_REASON
61 const char *reason = "";
64 if (c == NULL || *c == 0)
67 while (c != NULL && *c != 0) {
71 case '\\': /* make literal */
74 case '1': case '2': case '3':
75 case '4': case '5': case '6':
76 case '7': case '8': case '9':
78 FAIL("bad back reference");
80 was_multiple = ISC_FALSE;
83 FAIL("escaped end-of-string");
89 case '[': /* bracket start */
92 was_multiple = ISC_FALSE;
93 seen_char = ISC_FALSE;
94 state = parse_bracket;
96 case '{': /* bound start */
98 case '0': case '1': case '2': case '3':
99 case '4': case '5': case '6': case '7':
104 FAIL("was multiple");
105 seen_comma = ISC_FALSE;
106 seen_high = ISC_FALSE;
114 have_atom = ISC_TRUE;
115 was_multiple = ISC_TRUE;
119 case '(': /* group start */
120 have_atom = ISC_FALSE;
121 was_multiple = ISC_FALSE;
127 case ')': /* group end */
128 if (group && !have_atom && !empty_ok)
129 FAIL("empty alternative");
130 have_atom = ISC_TRUE;
131 was_multiple = ISC_FALSE;
136 case '|': /* alternative seperator */
139 have_atom = ISC_FALSE;
140 empty_ok = ISC_FALSE;
141 was_multiple = ISC_FALSE;
146 have_atom = ISC_TRUE;
147 was_multiple = ISC_TRUE;
154 FAIL("was multiple");
157 have_atom = ISC_TRUE;
158 was_multiple = ISC_TRUE;
164 have_atom = ISC_TRUE;
165 was_multiple = ISC_FALSE;
172 case '0': case '1': case '2': case '3': case '4':
173 case '5': case '6': case '7': case '8': case '9':
175 low = low * 10 + *c - '0';
177 FAIL("lower bound too big");
179 seen_high = ISC_TRUE;
180 high = high * 10 + *c - '0';
182 FAIL("upper bound too big");
188 FAIL("multiple commas");
189 seen_comma = ISC_TRUE;
194 FAIL("non digit/comma");
196 if (seen_high && low > high)
197 FAIL("bad parse bound");
198 seen_comma = ISC_FALSE;
207 if (seen_char || neg) goto inside;
212 if (range == 2) goto inside;
213 if (!seen_char) goto inside;
222 case '.': /* collating element */
228 case '=': /* equivalence class */
230 FAIL("equivalence class in range");
235 case ':': /* character class */
237 FAIL("character class in range");
243 seen_char = ISC_TRUE;
246 if (!c[1] && !seen_char)
247 FAIL("unfinished brace");
252 have_atom = ISC_TRUE;
257 seen_char = ISC_TRUE;
258 if (range == 2 && *c < range_start)
259 FAIL("out of order range");
276 state = parse_bracket;
306 state = parse_bracket;
326 isc_boolean_t found = ISC_FALSE;
328 i < sizeof(cc)/sizeof(*cc);
334 (unsigned int)(c - ccname))
336 if (strncmp(cc[i], ccname, len))
343 state = parse_bracket;
366 #if VALREGEX_REPORT_REASON
367 fprintf(stderr, "%s\n", reason);