2 * Copyright (C) 2013-2015 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/print.h>
21 #include <isc/regex.h>
22 #include <isc/string.h>
24 #if VALREGEX_REPORT_REASON
25 #define FAIL(x) do { reason = (x); goto error; } while(0)
27 #define FAIL(x) goto error
31 * Validate the regular expression 'C' locale.
34 isc_regex_validate(const char *c) {
36 none, parse_bracket, parse_bound,
37 parse_ce, parse_ec, parse_cc
39 /* Well known character classes. */
41 ":alnum:", ":digit:", ":punct:", ":alpha:", ":graph:",
42 ":space:", ":blank:", ":lower:", ":upper:", ":cntrl:",
45 isc_boolean_t seen_comma = ISC_FALSE;
46 isc_boolean_t seen_high = ISC_FALSE;
47 isc_boolean_t seen_char = ISC_FALSE;
48 isc_boolean_t seen_ec = ISC_FALSE;
49 isc_boolean_t seen_ce = ISC_FALSE;
50 isc_boolean_t have_atom = ISC_FALSE;
54 isc_boolean_t empty_ok = ISC_FALSE;
55 isc_boolean_t neg = ISC_FALSE;
56 isc_boolean_t was_multiple = ISC_FALSE;
58 unsigned int high = 0;
59 const char *ccname = NULL;
61 #if VALREGEX_REPORT_REASON
62 const char *reason = "";
65 if (c == NULL || *c == 0)
68 while (c != NULL && *c != 0) {
72 case '\\': /* make literal */
75 case '1': case '2': case '3':
76 case '4': case '5': case '6':
77 case '7': case '8': case '9':
79 FAIL("bad back reference");
81 was_multiple = ISC_FALSE;
84 FAIL("escaped end-of-string");
90 case '[': /* bracket start */
93 was_multiple = ISC_FALSE;
94 seen_char = ISC_FALSE;
95 state = parse_bracket;
97 case '{': /* bound start */
99 case '0': case '1': case '2': case '3':
100 case '4': case '5': case '6': case '7':
105 FAIL("was multiple");
106 seen_comma = ISC_FALSE;
107 seen_high = ISC_FALSE;
115 have_atom = ISC_TRUE;
116 was_multiple = ISC_TRUE;
120 case '(': /* group start */
121 have_atom = ISC_FALSE;
122 was_multiple = ISC_FALSE;
128 case ')': /* group end */
129 if (group && !have_atom && !empty_ok)
130 FAIL("empty alternative");
131 have_atom = ISC_TRUE;
132 was_multiple = ISC_FALSE;
137 case '|': /* alternative seperator */
140 have_atom = ISC_FALSE;
141 empty_ok = ISC_FALSE;
142 was_multiple = ISC_FALSE;
147 have_atom = ISC_TRUE;
148 was_multiple = ISC_TRUE;
155 FAIL("was multiple");
158 have_atom = ISC_TRUE;
159 was_multiple = ISC_TRUE;
165 have_atom = ISC_TRUE;
166 was_multiple = ISC_FALSE;
173 case '0': case '1': case '2': case '3': case '4':
174 case '5': case '6': case '7': case '8': case '9':
176 low = low * 10 + *c - '0';
178 FAIL("lower bound too big");
180 seen_high = ISC_TRUE;
181 high = high * 10 + *c - '0';
183 FAIL("upper bound too big");
189 FAIL("multiple commas");
190 seen_comma = ISC_TRUE;
195 FAIL("non digit/comma");
197 if (seen_high && low > high)
198 FAIL("bad parse bound");
199 seen_comma = ISC_FALSE;
208 if (seen_char || neg) goto inside;
213 if (range == 2) goto inside;
214 if (!seen_char) goto inside;
223 case '.': /* collating element */
224 if (range != 0) --range;
229 case '=': /* equivalence class */
231 FAIL("equivalence class in range");
236 case ':': /* character class */
238 FAIL("character class in range");
244 seen_char = ISC_TRUE;
247 if (!c[1] && !seen_char)
248 FAIL("unfinished brace");
253 have_atom = ISC_TRUE;
258 seen_char = ISC_TRUE;
259 if (range == 2 && (*c & 0xff) < range_start)
260 FAIL("out of order range");
263 range_start = *c & 0xff;
277 state = parse_bracket;
307 state = parse_bracket;
327 isc_boolean_t found = ISC_FALSE;
329 i < sizeof(cc)/sizeof(*cc);
335 (unsigned int)(c - ccname))
337 if (strncmp(cc[i], ccname, len))
344 state = parse_bracket;
367 #if VALREGEX_REPORT_REASON
368 fprintf(stderr, "%s\n", reason);