]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libc/regex/regcomp.c
Fix out-of-bounds read in libc/regex.
[FreeBSD/FreeBSD.git] / lib / libc / regex / regcomp.c
1 /*-
2  * Copyright (c) 1992, 1993, 1994 Henry Spencer.
3  * Copyright (c) 1992, 1993, 1994
4  *      The Regents of the University of California.  All rights reserved.
5  *
6  * Copyright (c) 2011 The FreeBSD Foundation
7  * All rights reserved.
8  * Portions of this software were developed by David Chisnall
9  * under sponsorship from the FreeBSD Foundation.
10  *
11  * This code is derived from software contributed to Berkeley by
12  * Henry Spencer.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *      @(#)regcomp.c   8.5 (Berkeley) 3/20/94
39  */
40
41 #if defined(LIBC_SCCS) && !defined(lint)
42 static char sccsid[] = "@(#)regcomp.c   8.5 (Berkeley) 3/20/94";
43 #endif /* LIBC_SCCS and not lint */
44 #include <sys/cdefs.h>
45 __FBSDID("$FreeBSD$");
46
47 #include <sys/types.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include <ctype.h>
51 #include <limits.h>
52 #include <stdlib.h>
53 #include <regex.h>
54 #include <stdbool.h>
55 #include <wchar.h>
56 #include <wctype.h>
57
58 #include "collate.h"
59
60 #include "utils.h"
61 #include "regex2.h"
62
63 #include "cname.h"
64
65 /*
66  * Branching context, used to keep track of branch state for all of the branch-
67  * aware functions. In addition to keeping track of branch positions for the
68  * p_branch_* functions, we use this to simplify some clumsiness in BREs for
69  * detection of whether ^ is acting as an anchor or being used erroneously and
70  * also for whether we're in a sub-expression or not.
71  */
72 struct branchc {
73         sopno start;
74         sopno back;
75         sopno fwd;
76
77         int nbranch;
78         int nchain;
79         bool outer;
80         bool terminate;
81 };
82
83 /*
84  * parse structure, passed up and down to avoid global variables and
85  * other clumsinesses
86  */
87 struct parse {
88         const char *next;       /* next character in RE */
89         const char *end;        /* end of string (-> NUL normally) */
90         int error;              /* has an error been seen? */
91         sop *strip;             /* malloced strip */
92         sopno ssize;            /* malloced strip size (allocated) */
93         sopno slen;             /* malloced strip length (used) */
94         int ncsalloc;           /* number of csets allocated */
95         struct re_guts *g;
96 #       define  NPAREN  10      /* we need to remember () 1-9 for back refs */
97         sopno pbegin[NPAREN];   /* -> ( ([0] unused) */
98         sopno pend[NPAREN];     /* -> ) ([0] unused) */
99         bool allowbranch;       /* can this expression branch? */
100         bool bre;               /* convenience; is this a BRE? */
101         bool (*parse_expr)(struct parse *, struct branchc *);
102         void (*pre_parse)(struct parse *, struct branchc *);
103         void (*post_parse)(struct parse *, struct branchc *);
104 };
105
106 /* ========= begin header generated by ./mkh ========= */
107 #ifdef __cplusplus
108 extern "C" {
109 #endif
110
111 /* === regcomp.c === */
112 static bool p_ere_exp(struct parse *p, struct branchc *bc);
113 static void p_str(struct parse *p);
114 static int p_branch_eat_delim(struct parse *p, struct branchc *bc);
115 static void p_branch_ins_offset(struct parse *p, struct branchc *bc);
116 static void p_branch_fix_tail(struct parse *p, struct branchc *bc);
117 static bool p_branch_empty(struct parse *p, struct branchc *bc);
118 static bool p_branch_do(struct parse *p, struct branchc *bc);
119 static void p_bre_pre_parse(struct parse *p, struct branchc *bc);
120 static void p_bre_post_parse(struct parse *p, struct branchc *bc);
121 static void p_re(struct parse *p, int end1, int end2);
122 static bool p_simp_re(struct parse *p, struct branchc *bc);
123 static int p_count(struct parse *p);
124 static void p_bracket(struct parse *p);
125 static void p_b_term(struct parse *p, cset *cs);
126 static void p_b_cclass(struct parse *p, cset *cs);
127 static void p_b_eclass(struct parse *p, cset *cs);
128 static wint_t p_b_symbol(struct parse *p);
129 static wint_t p_b_coll_elem(struct parse *p, wint_t endc);
130 static wint_t othercase(wint_t ch);
131 static void bothcases(struct parse *p, wint_t ch);
132 static void ordinary(struct parse *p, wint_t ch);
133 static void nonnewline(struct parse *p);
134 static void repeat(struct parse *p, sopno start, int from, int to);
135 static int seterr(struct parse *p, int e);
136 static cset *allocset(struct parse *p);
137 static void freeset(struct parse *p, cset *cs);
138 static void CHadd(struct parse *p, cset *cs, wint_t ch);
139 static void CHaddrange(struct parse *p, cset *cs, wint_t min, wint_t max);
140 static void CHaddtype(struct parse *p, cset *cs, wctype_t wct);
141 static wint_t singleton(cset *cs);
142 static sopno dupl(struct parse *p, sopno start, sopno finish);
143 static void doemit(struct parse *p, sop op, size_t opnd);
144 static void doinsert(struct parse *p, sop op, size_t opnd, sopno pos);
145 static void dofwd(struct parse *p, sopno pos, sop value);
146 static int enlarge(struct parse *p, sopno size);
147 static void stripsnug(struct parse *p, struct re_guts *g);
148 static void findmust(struct parse *p, struct re_guts *g);
149 static int altoffset(sop *scan, int offset);
150 static void computejumps(struct parse *p, struct re_guts *g);
151 static void computematchjumps(struct parse *p, struct re_guts *g);
152 static sopno pluscount(struct parse *p, struct re_guts *g);
153 static wint_t wgetnext(struct parse *p);
154
155 #ifdef __cplusplus
156 }
157 #endif
158 /* ========= end header generated by ./mkh ========= */
159
160 static char nuls[10];           /* place to point scanner in event of error */
161
162 /*
163  * macros for use with parse structure
164  * BEWARE:  these know that the parse structure is named `p' !!!
165  */
166 #define PEEK()  (*p->next)
167 #define PEEK2() (*(p->next+1))
168 #define MORE()  (p->next < p->end)
169 #define MORE2() (p->next+1 < p->end)
170 #define SEE(c)  (MORE() && PEEK() == (c))
171 #define SEETWO(a, b)    (MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b))
172 #define SEESPEC(a)      (p->bre ? SEETWO('\\', a) : SEE(a))
173 #define EAT(c)  ((SEE(c)) ? (NEXT(), 1) : 0)
174 #define EATTWO(a, b)    ((SEETWO(a, b)) ? (NEXT2(), 1) : 0)
175 #define NEXT()  (p->next++)
176 #define NEXT2() (p->next += 2)
177 #define NEXTn(n)        (p->next += (n))
178 #define GETNEXT()       (*p->next++)
179 #define WGETNEXT()      wgetnext(p)
180 #define SETERROR(e)     seterr(p, (e))
181 #define REQUIRE(co, e)  ((co) || SETERROR(e))
182 #define MUSTSEE(c, e)   (REQUIRE(MORE() && PEEK() == (c), e))
183 #define MUSTEAT(c, e)   (REQUIRE(MORE() && GETNEXT() == (c), e))
184 #define MUSTNOTSEE(c, e)        (REQUIRE(!MORE() || PEEK() != (c), e))
185 #define EMIT(op, sopnd) doemit(p, (sop)(op), (size_t)(sopnd))
186 #define INSERT(op, pos) doinsert(p, (sop)(op), HERE()-(pos)+1, pos)
187 #define AHEAD(pos)              dofwd(p, pos, HERE()-(pos))
188 #define ASTERN(sop, pos)        EMIT(sop, HERE()-pos)
189 #define HERE()          (p->slen)
190 #define THERE()         (p->slen - 1)
191 #define THERETHERE()    (p->slen - 2)
192 #define DROP(n) (p->slen -= (n))
193
194 #ifndef NDEBUG
195 static int never = 0;           /* for use in asserts; shuts lint up */
196 #else
197 #define never   0               /* some <assert.h>s have bugs too */
198 #endif
199
200 /* Macro used by computejump()/computematchjump() */
201 #define MIN(a,b)        ((a)<(b)?(a):(b))
202
203 /*
204  - regcomp - interface for parser and compilation
205  = extern int regcomp(regex_t *, const char *, int);
206  = #define      REG_BASIC       0000
207  = #define      REG_EXTENDED    0001
208  = #define      REG_ICASE       0002
209  = #define      REG_NOSUB       0004
210  = #define      REG_NEWLINE     0010
211  = #define      REG_NOSPEC      0020
212  = #define      REG_PEND        0040
213  = #define      REG_DUMP        0200
214  */
215 int                             /* 0 success, otherwise REG_something */
216 regcomp(regex_t * __restrict preg,
217         const char * __restrict pattern,
218         int cflags)
219 {
220         struct parse pa;
221         struct re_guts *g;
222         struct parse *p = &pa;
223         int i;
224         size_t len;
225         size_t maxlen;
226 #ifdef REDEBUG
227 #       define  GOODFLAGS(f)    (f)
228 #else
229 #       define  GOODFLAGS(f)    ((f)&~REG_DUMP)
230 #endif
231
232         cflags = GOODFLAGS(cflags);
233         if ((cflags&REG_EXTENDED) && (cflags&REG_NOSPEC))
234                 return(REG_INVARG);
235
236         if (cflags&REG_PEND) {
237                 if (preg->re_endp < pattern)
238                         return(REG_INVARG);
239                 len = preg->re_endp - pattern;
240         } else
241                 len = strlen(pattern);
242
243         /* do the mallocs early so failure handling is easy */
244         g = (struct re_guts *)malloc(sizeof(struct re_guts));
245         if (g == NULL)
246                 return(REG_ESPACE);
247         /*
248          * Limit the pattern space to avoid a 32-bit overflow on buffer
249          * extension.  Also avoid any signed overflow in case of conversion
250          * so make the real limit based on a 31-bit overflow.
251          *
252          * Likely not applicable on 64-bit systems but handle the case
253          * generically (who are we to stop people from using ~715MB+
254          * patterns?).
255          */
256         maxlen = ((size_t)-1 >> 1) / sizeof(sop) * 2 / 3;
257         if (len >= maxlen) {
258                 free((char *)g);
259                 return(REG_ESPACE);
260         }
261         p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */
262         assert(p->ssize >= len);
263
264         p->strip = (sop *)malloc(p->ssize * sizeof(sop));
265         p->slen = 0;
266         if (p->strip == NULL) {
267                 free((char *)g);
268                 return(REG_ESPACE);
269         }
270
271         /* set things up */
272         p->g = g;
273         p->next = pattern;      /* convenience; we do not modify it */
274         p->end = p->next + len;
275         p->error = 0;
276         p->ncsalloc = 0;
277         for (i = 0; i < NPAREN; i++) {
278                 p->pbegin[i] = 0;
279                 p->pend[i] = 0;
280         }
281         if (cflags & REG_EXTENDED) {
282                 p->allowbranch = true;
283                 p->bre = false;
284                 p->parse_expr = p_ere_exp;
285                 p->pre_parse = NULL;
286                 p->post_parse = NULL;
287         } else {
288                 p->allowbranch = false;
289                 p->bre = true;
290                 p->parse_expr = p_simp_re;
291                 p->pre_parse = p_bre_pre_parse;
292                 p->post_parse = p_bre_post_parse;
293         }
294         g->sets = NULL;
295         g->ncsets = 0;
296         g->cflags = cflags;
297         g->iflags = 0;
298         g->nbol = 0;
299         g->neol = 0;
300         g->must = NULL;
301         g->moffset = -1;
302         g->charjump = NULL;
303         g->matchjump = NULL;
304         g->mlen = 0;
305         g->nsub = 0;
306         g->backrefs = 0;
307
308         /* do it */
309         EMIT(OEND, 0);
310         g->firststate = THERE();
311         if (cflags & REG_NOSPEC)
312                 p_str(p);
313         else
314                 p_re(p, OUT, OUT);
315         EMIT(OEND, 0);
316         g->laststate = THERE();
317
318         /* tidy up loose ends and fill things in */
319         stripsnug(p, g);
320         findmust(p, g);
321         /* only use Boyer-Moore algorithm if the pattern is bigger
322          * than three characters
323          */
324         if(g->mlen > 3) {
325                 computejumps(p, g);
326                 computematchjumps(p, g);
327                 if(g->matchjump == NULL && g->charjump != NULL) {
328                         free(g->charjump);
329                         g->charjump = NULL;
330                 }
331         }
332         g->nplus = pluscount(p, g);
333         g->magic = MAGIC2;
334         preg->re_nsub = g->nsub;
335         preg->re_g = g;
336         preg->re_magic = MAGIC1;
337 #ifndef REDEBUG
338         /* not debugging, so can't rely on the assert() in regexec() */
339         if (g->iflags&BAD)
340                 SETERROR(REG_ASSERT);
341 #endif
342
343         /* win or lose, we're done */
344         if (p->error != 0)      /* lose */
345                 regfree(preg);
346         return(p->error);
347 }
348
349 /*
350  - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op,
351  - return whether we should terminate or not
352  == static bool p_ere_exp(struct parse *p);
353  */
354 static bool
355 p_ere_exp(struct parse *p, struct branchc *bc)
356 {
357         char c;
358         wint_t wc;
359         sopno pos;
360         int count;
361         int count2;
362         sopno subno;
363         int wascaret = 0;
364
365         assert(MORE());         /* caller should have ensured this */
366         c = GETNEXT();
367
368         pos = HERE();
369         switch (c) {
370         case '(':
371                 (void)REQUIRE(MORE(), REG_EPAREN);
372                 p->g->nsub++;
373                 subno = p->g->nsub;
374                 if (subno < NPAREN)
375                         p->pbegin[subno] = HERE();
376                 EMIT(OLPAREN, subno);
377                 if (!SEE(')'))
378                         p_re(p, ')', IGN);
379                 if (subno < NPAREN) {
380                         p->pend[subno] = HERE();
381                         assert(p->pend[subno] != 0);
382                 }
383                 EMIT(ORPAREN, subno);
384                 (void)MUSTEAT(')', REG_EPAREN);
385                 break;
386 #ifndef POSIX_MISTAKE
387         case ')':               /* happens only if no current unmatched ( */
388                 /*
389                  * You may ask, why the ifndef?  Because I didn't notice
390                  * this until slightly too late for 1003.2, and none of the
391                  * other 1003.2 regular-expression reviewers noticed it at
392                  * all.  So an unmatched ) is legal POSIX, at least until
393                  * we can get it fixed.
394                  */
395                 SETERROR(REG_EPAREN);
396                 break;
397 #endif
398         case '^':
399                 EMIT(OBOL, 0);
400                 p->g->iflags |= USEBOL;
401                 p->g->nbol++;
402                 wascaret = 1;
403                 break;
404         case '$':
405                 EMIT(OEOL, 0);
406                 p->g->iflags |= USEEOL;
407                 p->g->neol++;
408                 break;
409         case '|':
410                 SETERROR(REG_EMPTY);
411                 break;
412         case '*':
413         case '+':
414         case '?':
415         case '{':
416                 SETERROR(REG_BADRPT);
417                 break;
418         case '.':
419                 if (p->g->cflags&REG_NEWLINE)
420                         nonnewline(p);
421                 else
422                         EMIT(OANY, 0);
423                 break;
424         case '[':
425                 p_bracket(p);
426                 break;
427         case '\\':
428                 (void)REQUIRE(MORE(), REG_EESCAPE);
429                 wc = WGETNEXT();
430                 switch (wc) {
431                 case '<':
432                         EMIT(OBOW, 0);
433                         break;
434                 case '>':
435                         EMIT(OEOW, 0);
436                         break;
437                 default:
438                         ordinary(p, wc);
439                         break;
440                 }
441                 break;
442         default:
443                 if (p->error != 0)
444                         return (false);
445                 p->next--;
446                 wc = WGETNEXT();
447                 ordinary(p, wc);
448                 break;
449         }
450
451         if (!MORE())
452                 return (false);
453         c = PEEK();
454         /* we call { a repetition if followed by a digit */
455         if (!( c == '*' || c == '+' || c == '?' || c == '{'))
456                 return (false);         /* no repetition, we're done */
457         else if (c == '{')
458                 (void)REQUIRE(MORE2() && \
459                     (isdigit((uch)PEEK2()) || PEEK2() == ','), REG_BADRPT);
460         NEXT();
461
462         (void)REQUIRE(!wascaret, REG_BADRPT);
463         switch (c) {
464         case '*':       /* implemented as +? */
465                 /* this case does not require the (y|) trick, noKLUDGE */
466                 INSERT(OPLUS_, pos);
467                 ASTERN(O_PLUS, pos);
468                 INSERT(OQUEST_, pos);
469                 ASTERN(O_QUEST, pos);
470                 break;
471         case '+':
472                 INSERT(OPLUS_, pos);
473                 ASTERN(O_PLUS, pos);
474                 break;
475         case '?':
476                 /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
477                 INSERT(OCH_, pos);              /* offset slightly wrong */
478                 ASTERN(OOR1, pos);              /* this one's right */
479                 AHEAD(pos);                     /* fix the OCH_ */
480                 EMIT(OOR2, 0);                  /* offset very wrong... */
481                 AHEAD(THERE());                 /* ...so fix it */
482                 ASTERN(O_CH, THERETHERE());
483                 break;
484         case '{':
485                 count = p_count(p);
486                 if (EAT(',')) {
487                         if (isdigit((uch)PEEK())) {
488                                 count2 = p_count(p);
489                                 (void)REQUIRE(count <= count2, REG_BADBR);
490                         } else          /* single number with comma */
491                                 count2 = INFINITY;
492                 } else          /* just a single number */
493                         count2 = count;
494                 repeat(p, pos, count, count2);
495                 if (!EAT('}')) {        /* error heuristics */
496                         while (MORE() && PEEK() != '}')
497                                 NEXT();
498                         (void)REQUIRE(MORE(), REG_EBRACE);
499                         SETERROR(REG_BADBR);
500                 }
501                 break;
502         }
503
504         if (!MORE())
505                 return (false);
506         c = PEEK();
507         if (!( c == '*' || c == '+' || c == '?' ||
508                                 (c == '{' && MORE2() && isdigit((uch)PEEK2())) ) )
509                 return (false);
510         SETERROR(REG_BADRPT);
511         return (false);
512 }
513
514 /*
515  - p_str - string (no metacharacters) "parser"
516  == static void p_str(struct parse *p);
517  */
518 static void
519 p_str(struct parse *p)
520 {
521         (void)REQUIRE(MORE(), REG_EMPTY);
522         while (MORE())
523                 ordinary(p, WGETNEXT());
524 }
525
526 /*
527  * Eat consecutive branch delimiters for the kind of expression that we are
528  * parsing, return the number of delimiters that we ate.
529  */
530 static int
531 p_branch_eat_delim(struct parse *p, struct branchc *bc)
532 {
533         int nskip;
534
535         nskip = 0;
536         while (EAT('|'))
537                 ++nskip;
538         return (nskip);
539 }
540
541 /*
542  * Insert necessary branch book-keeping operations. This emits a
543  * bogus 'next' offset, since we still have more to parse
544  */
545 static void
546 p_branch_ins_offset(struct parse *p, struct branchc *bc)
547 {
548
549         if (bc->nbranch == 0) {
550                 INSERT(OCH_, bc->start);        /* offset is wrong */
551                 bc->fwd = bc->start;
552                 bc->back = bc->start;
553         }
554
555         ASTERN(OOR1, bc->back);
556         bc->back = THERE();
557         AHEAD(bc->fwd);                 /* fix previous offset */
558         bc->fwd = HERE();
559         EMIT(OOR2, 0);                  /* offset is very wrong */
560         ++bc->nbranch;
561 }
562
563 /*
564  * Fix the offset of the tail branch, if we actually had any branches.
565  * This is to correct the bogus placeholder offset that we use.
566  */
567 static void
568 p_branch_fix_tail(struct parse *p, struct branchc *bc)
569 {
570
571         /* Fix bogus offset at the tail if we actually have branches */
572         if (bc->nbranch > 0) {
573                 AHEAD(bc->fwd);
574                 ASTERN(O_CH, bc->back);
575         }
576 }
577
578 /*
579  * Signal to the parser that an empty branch has been encountered; this will,
580  * in the future, be used to allow for more permissive behavior with empty
581  * branches. The return value should indicate whether parsing may continue
582  * or not.
583  */
584 static bool
585 p_branch_empty(struct parse *p, struct branchc *bc)
586 {
587
588         SETERROR(REG_EMPTY);
589         return (false);
590 }
591
592 /*
593  * Take care of any branching requirements. This includes inserting the
594  * appropriate branching instructions as well as eating all of the branch
595  * delimiters until we either run out of pattern or need to parse more pattern.
596  */
597 static bool
598 p_branch_do(struct parse *p, struct branchc *bc)
599 {
600         int ate = 0;
601
602         ate = p_branch_eat_delim(p, bc);
603         if (ate == 0)
604                 return (false);
605         else if ((ate > 1 || (bc->outer && !MORE())) && !p_branch_empty(p, bc))
606                 /*
607                  * Halt parsing only if we have an empty branch and p_branch_empty
608                  * indicates that we must not continue. In the future, this will not
609                  * necessarily be an error.
610                  */
611                 return (false);
612         p_branch_ins_offset(p, bc);
613
614         return (true);
615 }
616
617 static void
618 p_bre_pre_parse(struct parse *p, struct branchc *bc)
619 {
620
621         (void) bc;
622         /*
623          * Does not move cleanly into expression parser because of
624          * ordinary interpration of * at the beginning position of
625          * an expression.
626          */
627         if (EAT('^')) {
628                 EMIT(OBOL, 0);
629                 p->g->iflags |= USEBOL;
630                 p->g->nbol++;
631         }
632 }
633
634 static void
635 p_bre_post_parse(struct parse *p, struct branchc *bc)
636 {
637
638         /* Expression is terminating due to EOL token */
639         if (bc->terminate) {
640                 DROP(1);
641                 EMIT(OEOL, 0);
642                 p->g->iflags |= USEEOL;
643                 p->g->neol++;
644         }
645 }
646
647 /*
648  - p_re - Top level parser, concatenation and BRE anchoring
649  == static void p_re(struct parse *p, int end1, int end2);
650  * Giving end1 as OUT essentially eliminates the end1/end2 check.
651  *
652  * This implementation is a bit of a kludge, in that a trailing $ is first
653  * taken as an ordinary character and then revised to be an anchor.
654  * The amount of lookahead needed to avoid this kludge is excessive.
655  */
656 static void
657 p_re(struct parse *p,
658         int end1,       /* first terminating character */
659         int end2)       /* second terminating character; ignored for EREs */
660 {
661         struct branchc bc;
662
663         bc.nbranch = 0;
664         if (end1 == OUT && end2 == OUT)
665                 bc.outer = true;
666         else
667                 bc.outer = false;
668 #define SEEEND()        (!p->bre ? SEE(end1) : SEETWO(end1, end2))
669         for (;;) {
670                 bc.start = HERE();
671                 bc.nchain = 0;
672                 bc.terminate = false;
673                 if (p->pre_parse != NULL)
674                         p->pre_parse(p, &bc);
675                 while (MORE() && (!p->allowbranch || !SEESPEC('|')) && !SEEEND()) {
676                         bc.terminate = p->parse_expr(p, &bc);
677                         ++bc.nchain;
678                 }
679                 if (p->post_parse != NULL)
680                         p->post_parse(p, &bc);
681                 (void) REQUIRE(HERE() != bc.start, REG_EMPTY);
682                 if (!p->allowbranch)
683                         break;
684                 /*
685                  * p_branch_do's return value indicates whether we should
686                  * continue parsing or not. This is both for correctness and
687                  * a slight optimization, because it will check if we've
688                  * encountered an empty branch or the end of the string
689                  * immediately following a branch delimiter.
690                  */
691                 if (!p_branch_do(p, &bc))
692                         break;
693         }
694 #undef SEE_END
695         if (p->allowbranch)
696                 p_branch_fix_tail(p, &bc);
697         assert(!MORE() || SEE(end1));
698 }
699
700 /*
701  - p_simp_re - parse a simple RE, an atom possibly followed by a repetition
702  == static bool p_simp_re(struct parse *p, struct branchc *bc);
703  */
704 static bool                     /* was the simple RE an unbackslashed $? */
705 p_simp_re(struct parse *p, struct branchc *bc)
706 {
707         int c;
708         int count;
709         int count2;
710         sopno pos;
711         int i;
712         wint_t wc;
713         sopno subno;
714 #       define  BACKSL  (1<<CHAR_BIT)
715
716         pos = HERE();           /* repetition op, if any, covers from here */
717
718         assert(MORE());         /* caller should have ensured this */
719         c = GETNEXT();
720         if (c == '\\') {
721                 (void)REQUIRE(MORE(), REG_EESCAPE);
722                 c = BACKSL | GETNEXT();
723         }
724         switch (c) {
725         case '.':
726                 if (p->g->cflags&REG_NEWLINE)
727                         nonnewline(p);
728                 else
729                         EMIT(OANY, 0);
730                 break;
731         case '[':
732                 p_bracket(p);
733                 break;
734         case BACKSL|'<':
735                 EMIT(OBOW, 0);
736                 break;
737         case BACKSL|'>':
738                 EMIT(OEOW, 0);
739                 break;
740         case BACKSL|'{':
741                 SETERROR(REG_BADRPT);
742                 break;
743         case BACKSL|'(':
744                 p->g->nsub++;
745                 subno = p->g->nsub;
746                 if (subno < NPAREN)
747                         p->pbegin[subno] = HERE();
748                 EMIT(OLPAREN, subno);
749                 /* the MORE here is an error heuristic */
750                 if (MORE() && !SEETWO('\\', ')'))
751                         p_re(p, '\\', ')');
752                 if (subno < NPAREN) {
753                         p->pend[subno] = HERE();
754                         assert(p->pend[subno] != 0);
755                 }
756                 EMIT(ORPAREN, subno);
757                 (void)REQUIRE(EATTWO('\\', ')'), REG_EPAREN);
758                 break;
759         case BACKSL|')':        /* should not get here -- must be user */
760                 SETERROR(REG_EPAREN);
761                 break;
762         case BACKSL|'1':
763         case BACKSL|'2':
764         case BACKSL|'3':
765         case BACKSL|'4':
766         case BACKSL|'5':
767         case BACKSL|'6':
768         case BACKSL|'7':
769         case BACKSL|'8':
770         case BACKSL|'9':
771                 i = (c&~BACKSL) - '0';
772                 assert(i < NPAREN);
773                 if (p->pend[i] != 0) {
774                         assert(i <= p->g->nsub);
775                         EMIT(OBACK_, i);
776                         assert(p->pbegin[i] != 0);
777                         assert(OP(p->strip[p->pbegin[i]]) == OLPAREN);
778                         assert(OP(p->strip[p->pend[i]]) == ORPAREN);
779                         (void) dupl(p, p->pbegin[i]+1, p->pend[i]);
780                         EMIT(O_BACK, i);
781                 } else
782                         SETERROR(REG_ESUBREG);
783                 p->g->backrefs = 1;
784                 break;
785         case '*':
786                 /*
787                  * Ordinary if used as the first character beyond BOL anchor of
788                  * a (sub-)expression, counts as a bad repetition operator if it
789                  * appears otherwise.
790                  */
791                 (void)REQUIRE(bc->nchain == 0, REG_BADRPT);
792                 /* FALLTHROUGH */
793         default:
794                 if (p->error != 0)
795                         return (false); /* Definitely not $... */
796                 p->next--;
797                 wc = WGETNEXT();
798                 ordinary(p, wc);
799                 break;
800         }
801
802         if (EAT('*')) {         /* implemented as +? */
803                 /* this case does not require the (y|) trick, noKLUDGE */
804                 INSERT(OPLUS_, pos);
805                 ASTERN(O_PLUS, pos);
806                 INSERT(OQUEST_, pos);
807                 ASTERN(O_QUEST, pos);
808         } else if (EATTWO('\\', '{')) {
809                 count = p_count(p);
810                 if (EAT(',')) {
811                         if (MORE() && isdigit((uch)PEEK())) {
812                                 count2 = p_count(p);
813                                 (void)REQUIRE(count <= count2, REG_BADBR);
814                         } else          /* single number with comma */
815                                 count2 = INFINITY;
816                 } else          /* just a single number */
817                         count2 = count;
818                 repeat(p, pos, count, count2);
819                 if (!EATTWO('\\', '}')) {       /* error heuristics */
820                         while (MORE() && !SEETWO('\\', '}'))
821                                 NEXT();
822                         (void)REQUIRE(MORE(), REG_EBRACE);
823                         SETERROR(REG_BADBR);
824                 }
825         } else if (c == '$')     /* $ (but not \$) ends it */
826                 return (true);
827
828         return (false);
829 }
830
831 /*
832  - p_count - parse a repetition count
833  == static int p_count(struct parse *p);
834  */
835 static int                      /* the value */
836 p_count(struct parse *p)
837 {
838         int count = 0;
839         int ndigits = 0;
840
841         while (MORE() && isdigit((uch)PEEK()) && count <= DUPMAX) {
842                 count = count*10 + (GETNEXT() - '0');
843                 ndigits++;
844         }
845
846         (void)REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR);
847         return(count);
848 }
849
850 /*
851  - p_bracket - parse a bracketed character list
852  == static void p_bracket(struct parse *p);
853  */
854 static void
855 p_bracket(struct parse *p)
856 {
857         cset *cs;
858         wint_t ch;
859
860         /* Dept of Truly Sickening Special-Case Kludges */
861         if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) {
862                 EMIT(OBOW, 0);
863                 NEXTn(6);
864                 return;
865         }
866         if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) {
867                 EMIT(OEOW, 0);
868                 NEXTn(6);
869                 return;
870         }
871
872         if ((cs = allocset(p)) == NULL)
873                 return;
874
875         if (p->g->cflags&REG_ICASE)
876                 cs->icase = 1;
877         if (EAT('^'))
878                 cs->invert = 1;
879         if (EAT(']'))
880                 CHadd(p, cs, ']');
881         else if (EAT('-'))
882                 CHadd(p, cs, '-');
883         while (MORE() && PEEK() != ']' && !SEETWO('-', ']'))
884                 p_b_term(p, cs);
885         if (EAT('-'))
886                 CHadd(p, cs, '-');
887         (void)MUSTEAT(']', REG_EBRACK);
888
889         if (p->error != 0)      /* don't mess things up further */
890                 return;
891
892         if (cs->invert && p->g->cflags&REG_NEWLINE)
893                 cs->bmp['\n' >> 3] |= 1 << ('\n' & 7);
894
895         if ((ch = singleton(cs)) != OUT) {      /* optimize singleton sets */
896                 ordinary(p, ch);
897                 freeset(p, cs);
898         } else
899                 EMIT(OANYOF, (int)(cs - p->g->sets));
900 }
901
902 /*
903  - p_b_term - parse one term of a bracketed character list
904  == static void p_b_term(struct parse *p, cset *cs);
905  */
906 static void
907 p_b_term(struct parse *p, cset *cs)
908 {
909         char c;
910         wint_t start, finish;
911         wint_t i;
912         struct xlocale_collate *table =
913                 (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE];
914
915         /* classify what we've got */
916         switch ((MORE()) ? PEEK() : '\0') {
917         case '[':
918                 c = (MORE2()) ? PEEK2() : '\0';
919                 break;
920         case '-':
921                 SETERROR(REG_ERANGE);
922                 return;                 /* NOTE RETURN */
923         default:
924                 c = '\0';
925                 break;
926         }
927
928         switch (c) {
929         case ':':               /* character class */
930                 NEXT2();
931                 (void)REQUIRE(MORE(), REG_EBRACK);
932                 c = PEEK();
933                 (void)REQUIRE(c != '-' && c != ']', REG_ECTYPE);
934                 p_b_cclass(p, cs);
935                 (void)REQUIRE(MORE(), REG_EBRACK);
936                 (void)REQUIRE(EATTWO(':', ']'), REG_ECTYPE);
937                 break;
938         case '=':               /* equivalence class */
939                 NEXT2();
940                 (void)REQUIRE(MORE(), REG_EBRACK);
941                 c = PEEK();
942                 (void)REQUIRE(c != '-' && c != ']', REG_ECOLLATE);
943                 p_b_eclass(p, cs);
944                 (void)REQUIRE(MORE(), REG_EBRACK);
945                 (void)REQUIRE(EATTWO('=', ']'), REG_ECOLLATE);
946                 break;
947         default:                /* symbol, ordinary character, or range */
948                 start = p_b_symbol(p);
949                 if (SEE('-') && MORE2() && PEEK2() != ']') {
950                         /* range */
951                         NEXT();
952                         if (EAT('-'))
953                                 finish = '-';
954                         else
955                                 finish = p_b_symbol(p);
956                 } else
957                         finish = start;
958                 if (start == finish)
959                         CHadd(p, cs, start);
960                 else {
961                         if (table->__collate_load_error || MB_CUR_MAX > 1) {
962                                 (void)REQUIRE(start <= finish, REG_ERANGE);
963                                 CHaddrange(p, cs, start, finish);
964                         } else {
965                                 (void)REQUIRE(__wcollate_range_cmp(start, finish) <= 0, REG_ERANGE);
966                                 for (i = 0; i <= UCHAR_MAX; i++) {
967                                         if (   __wcollate_range_cmp(start, i) <= 0
968                                             && __wcollate_range_cmp(i, finish) <= 0
969                                            )
970                                                 CHadd(p, cs, i);
971                                 }
972                         }
973                 }
974                 break;
975         }
976 }
977
978 /*
979  - p_b_cclass - parse a character-class name and deal with it
980  == static void p_b_cclass(struct parse *p, cset *cs);
981  */
982 static void
983 p_b_cclass(struct parse *p, cset *cs)
984 {
985         const char *sp = p->next;
986         size_t len;
987         wctype_t wct;
988         char clname[16];
989
990         while (MORE() && isalpha((uch)PEEK()))
991                 NEXT();
992         len = p->next - sp;
993         if (len >= sizeof(clname) - 1) {
994                 SETERROR(REG_ECTYPE);
995                 return;
996         }
997         memcpy(clname, sp, len);
998         clname[len] = '\0';
999         if ((wct = wctype(clname)) == 0) {
1000                 SETERROR(REG_ECTYPE);
1001                 return;
1002         }
1003         CHaddtype(p, cs, wct);
1004 }
1005
1006 /*
1007  - p_b_eclass - parse an equivalence-class name and deal with it
1008  == static void p_b_eclass(struct parse *p, cset *cs);
1009  *
1010  * This implementation is incomplete. xxx
1011  */
1012 static void
1013 p_b_eclass(struct parse *p, cset *cs)
1014 {
1015         wint_t c;
1016
1017         c = p_b_coll_elem(p, '=');
1018         CHadd(p, cs, c);
1019 }
1020
1021 /*
1022  - p_b_symbol - parse a character or [..]ed multicharacter collating symbol
1023  == static wint_t p_b_symbol(struct parse *p);
1024  */
1025 static wint_t                   /* value of symbol */
1026 p_b_symbol(struct parse *p)
1027 {
1028         wint_t value;
1029
1030         (void)REQUIRE(MORE(), REG_EBRACK);
1031         if (!EATTWO('[', '.'))
1032                 return(WGETNEXT());
1033
1034         /* collating symbol */
1035         value = p_b_coll_elem(p, '.');
1036         (void)REQUIRE(EATTWO('.', ']'), REG_ECOLLATE);
1037         return(value);
1038 }
1039
1040 /*
1041  - p_b_coll_elem - parse a collating-element name and look it up
1042  == static wint_t p_b_coll_elem(struct parse *p, wint_t endc);
1043  */
1044 static wint_t                   /* value of collating element */
1045 p_b_coll_elem(struct parse *p,
1046         wint_t endc)            /* name ended by endc,']' */
1047 {
1048         const char *sp = p->next;
1049         struct cname *cp;
1050         mbstate_t mbs;
1051         wchar_t wc;
1052         size_t clen, len;
1053
1054         while (MORE() && !SEETWO(endc, ']'))
1055                 NEXT();
1056         if (!MORE()) {
1057                 SETERROR(REG_EBRACK);
1058                 return(0);
1059         }
1060         len = p->next - sp;
1061         for (cp = cnames; cp->name != NULL; cp++)
1062                 if (strncmp(cp->name, sp, len) == 0 && strlen(cp->name) == len)
1063                         return(cp->code);       /* known name */
1064         memset(&mbs, 0, sizeof(mbs));
1065         if ((clen = mbrtowc(&wc, sp, len, &mbs)) == len)
1066                 return (wc);                    /* single character */
1067         else if (clen == (size_t)-1 || clen == (size_t)-2)
1068                 SETERROR(REG_ILLSEQ);
1069         else
1070                 SETERROR(REG_ECOLLATE);         /* neither */
1071         return(0);
1072 }
1073
1074 /*
1075  - othercase - return the case counterpart of an alphabetic
1076  == static wint_t othercase(wint_t ch);
1077  */
1078 static wint_t                   /* if no counterpart, return ch */
1079 othercase(wint_t ch)
1080 {
1081         assert(iswalpha(ch));
1082         if (iswupper(ch))
1083                 return(towlower(ch));
1084         else if (iswlower(ch))
1085                 return(towupper(ch));
1086         else                    /* peculiar, but could happen */
1087                 return(ch);
1088 }
1089
1090 /*
1091  - bothcases - emit a dualcase version of a two-case character
1092  == static void bothcases(struct parse *p, wint_t ch);
1093  *
1094  * Boy, is this implementation ever a kludge...
1095  */
1096 static void
1097 bothcases(struct parse *p, wint_t ch)
1098 {
1099         const char *oldnext = p->next;
1100         const char *oldend = p->end;
1101         char bracket[3 + MB_LEN_MAX];
1102         size_t n;
1103         mbstate_t mbs;
1104
1105         assert(othercase(ch) != ch);    /* p_bracket() would recurse */
1106         p->next = bracket;
1107         memset(&mbs, 0, sizeof(mbs));
1108         n = wcrtomb(bracket, ch, &mbs);
1109         assert(n != (size_t)-1);
1110         bracket[n] = ']';
1111         bracket[n + 1] = '\0';
1112         p->end = bracket+n+1;
1113         p_bracket(p);
1114         assert(p->next == p->end);
1115         p->next = oldnext;
1116         p->end = oldend;
1117 }
1118
1119 /*
1120  - ordinary - emit an ordinary character
1121  == static void ordinary(struct parse *p, wint_t ch);
1122  */
1123 static void
1124 ordinary(struct parse *p, wint_t ch)
1125 {
1126         cset *cs;
1127
1128         if ((p->g->cflags&REG_ICASE) && iswalpha(ch) && othercase(ch) != ch)
1129                 bothcases(p, ch);
1130         else if ((ch & OPDMASK) == ch)
1131                 EMIT(OCHAR, ch);
1132         else {
1133                 /*
1134                  * Kludge: character is too big to fit into an OCHAR operand.
1135                  * Emit a singleton set.
1136                  */
1137                 if ((cs = allocset(p)) == NULL)
1138                         return;
1139                 CHadd(p, cs, ch);
1140                 EMIT(OANYOF, (int)(cs - p->g->sets));
1141         }
1142 }
1143
1144 /*
1145  - nonnewline - emit REG_NEWLINE version of OANY
1146  == static void nonnewline(struct parse *p);
1147  *
1148  * Boy, is this implementation ever a kludge...
1149  */
1150 static void
1151 nonnewline(struct parse *p)
1152 {
1153         const char *oldnext = p->next;
1154         const char *oldend = p->end;
1155         char bracket[4];
1156
1157         p->next = bracket;
1158         p->end = bracket+3;
1159         bracket[0] = '^';
1160         bracket[1] = '\n';
1161         bracket[2] = ']';
1162         bracket[3] = '\0';
1163         p_bracket(p);
1164         assert(p->next == bracket+3);
1165         p->next = oldnext;
1166         p->end = oldend;
1167 }
1168
1169 /*
1170  - repeat - generate code for a bounded repetition, recursively if needed
1171  == static void repeat(struct parse *p, sopno start, int from, int to);
1172  */
1173 static void
1174 repeat(struct parse *p,
1175         sopno start,            /* operand from here to end of strip */
1176         int from,               /* repeated from this number */
1177         int to)                 /* to this number of times (maybe INFINITY) */
1178 {
1179         sopno finish = HERE();
1180 #       define  N       2
1181 #       define  INF     3
1182 #       define  REP(f, t)       ((f)*8 + (t))
1183 #       define  MAP(n)  (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N)
1184         sopno copy;
1185
1186         if (p->error != 0)      /* head off possible runaway recursion */
1187                 return;
1188
1189         assert(from <= to);
1190
1191         switch (REP(MAP(from), MAP(to))) {
1192         case REP(0, 0):                 /* must be user doing this */
1193                 DROP(finish-start);     /* drop the operand */
1194                 break;
1195         case REP(0, 1):                 /* as x{1,1}? */
1196         case REP(0, N):                 /* as x{1,n}? */
1197         case REP(0, INF):               /* as x{1,}? */
1198                 /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
1199                 INSERT(OCH_, start);            /* offset is wrong... */
1200                 repeat(p, start+1, 1, to);
1201                 ASTERN(OOR1, start);
1202                 AHEAD(start);                   /* ... fix it */
1203                 EMIT(OOR2, 0);
1204                 AHEAD(THERE());
1205                 ASTERN(O_CH, THERETHERE());
1206                 break;
1207         case REP(1, 1):                 /* trivial case */
1208                 /* done */
1209                 break;
1210         case REP(1, N):                 /* as x?x{1,n-1} */
1211                 /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
1212                 INSERT(OCH_, start);
1213                 ASTERN(OOR1, start);
1214                 AHEAD(start);
1215                 EMIT(OOR2, 0);                  /* offset very wrong... */
1216                 AHEAD(THERE());                 /* ...so fix it */
1217                 ASTERN(O_CH, THERETHERE());
1218                 copy = dupl(p, start+1, finish+1);
1219                 assert(copy == finish+4);
1220                 repeat(p, copy, 1, to-1);
1221                 break;
1222         case REP(1, INF):               /* as x+ */
1223                 INSERT(OPLUS_, start);
1224                 ASTERN(O_PLUS, start);
1225                 break;
1226         case REP(N, N):                 /* as xx{m-1,n-1} */
1227                 copy = dupl(p, start, finish);
1228                 repeat(p, copy, from-1, to-1);
1229                 break;
1230         case REP(N, INF):               /* as xx{n-1,INF} */
1231                 copy = dupl(p, start, finish);
1232                 repeat(p, copy, from-1, to);
1233                 break;
1234         default:                        /* "can't happen" */
1235                 SETERROR(REG_ASSERT);   /* just in case */
1236                 break;
1237         }
1238 }
1239
1240 /*
1241  - wgetnext - helper function for WGETNEXT() macro. Gets the next wide
1242  - character from the parse struct, signals a REG_ILLSEQ error if the
1243  - character can't be converted. Returns the number of bytes consumed.
1244  */
1245 static wint_t
1246 wgetnext(struct parse *p)
1247 {
1248         mbstate_t mbs;
1249         wchar_t wc;
1250         size_t n;
1251
1252         memset(&mbs, 0, sizeof(mbs));
1253         n = mbrtowc(&wc, p->next, p->end - p->next, &mbs);
1254         if (n == (size_t)-1 || n == (size_t)-2) {
1255                 SETERROR(REG_ILLSEQ);
1256                 return (0);
1257         }
1258         if (n == 0)
1259                 n = 1;
1260         p->next += n;
1261         return (wc);
1262 }
1263
1264 /*
1265  - seterr - set an error condition
1266  == static int seterr(struct parse *p, int e);
1267  */
1268 static int                      /* useless but makes type checking happy */
1269 seterr(struct parse *p, int e)
1270 {
1271         if (p->error == 0)      /* keep earliest error condition */
1272                 p->error = e;
1273         p->next = nuls;         /* try to bring things to a halt */
1274         p->end = nuls;
1275         return(0);              /* make the return value well-defined */
1276 }
1277
1278 /*
1279  - allocset - allocate a set of characters for []
1280  == static cset *allocset(struct parse *p);
1281  */
1282 static cset *
1283 allocset(struct parse *p)
1284 {
1285         cset *cs, *ncs;
1286
1287         ncs = reallocarray(p->g->sets, p->g->ncsets + 1, sizeof(*ncs));
1288         if (ncs == NULL) {
1289                 SETERROR(REG_ESPACE);
1290                 return (NULL);
1291         }
1292         p->g->sets = ncs;
1293         cs = &p->g->sets[p->g->ncsets++];
1294         memset(cs, 0, sizeof(*cs));
1295
1296         return(cs);
1297 }
1298
1299 /*
1300  - freeset - free a now-unused set
1301  == static void freeset(struct parse *p, cset *cs);
1302  */
1303 static void
1304 freeset(struct parse *p, cset *cs)
1305 {
1306         cset *top = &p->g->sets[p->g->ncsets];
1307
1308         free(cs->wides);
1309         free(cs->ranges);
1310         free(cs->types);
1311         memset(cs, 0, sizeof(*cs));
1312         if (cs == top-1)        /* recover only the easy case */
1313                 p->g->ncsets--;
1314 }
1315
1316 /*
1317  - singleton - Determine whether a set contains only one character,
1318  - returning it if so, otherwise returning OUT.
1319  */
1320 static wint_t
1321 singleton(cset *cs)
1322 {
1323         wint_t i, s, n;
1324
1325         for (i = n = 0; i < NC; i++)
1326                 if (CHIN(cs, i)) {
1327                         n++;
1328                         s = i;
1329                 }
1330         if (n == 1)
1331                 return (s);
1332         if (cs->nwides == 1 && cs->nranges == 0 && cs->ntypes == 0 &&
1333             cs->icase == 0)
1334                 return (cs->wides[0]);
1335         /* Don't bother handling the other cases. */
1336         return (OUT);
1337 }
1338
1339 /*
1340  - CHadd - add character to character set.
1341  */
1342 static void
1343 CHadd(struct parse *p, cset *cs, wint_t ch)
1344 {
1345         wint_t nch, *newwides;
1346         assert(ch >= 0);
1347         if (ch < NC)
1348                 cs->bmp[ch >> 3] |= 1 << (ch & 7);
1349         else {
1350                 newwides = reallocarray(cs->wides, cs->nwides + 1,
1351                     sizeof(*cs->wides));
1352                 if (newwides == NULL) {
1353                         SETERROR(REG_ESPACE);
1354                         return;
1355                 }
1356                 cs->wides = newwides;
1357                 cs->wides[cs->nwides++] = ch;
1358         }
1359         if (cs->icase) {
1360                 if ((nch = towlower(ch)) < NC)
1361                         cs->bmp[nch >> 3] |= 1 << (nch & 7);
1362                 if ((nch = towupper(ch)) < NC)
1363                         cs->bmp[nch >> 3] |= 1 << (nch & 7);
1364         }
1365 }
1366
1367 /*
1368  - CHaddrange - add all characters in the range [min,max] to a character set.
1369  */
1370 static void
1371 CHaddrange(struct parse *p, cset *cs, wint_t min, wint_t max)
1372 {
1373         crange *newranges;
1374
1375         for (; min < NC && min <= max; min++)
1376                 CHadd(p, cs, min);
1377         if (min >= max)
1378                 return;
1379         newranges = reallocarray(cs->ranges, cs->nranges + 1,
1380             sizeof(*cs->ranges));
1381         if (newranges == NULL) {
1382                 SETERROR(REG_ESPACE);
1383                 return;
1384         }
1385         cs->ranges = newranges;
1386         cs->ranges[cs->nranges].min = min;
1387         cs->ranges[cs->nranges].max = max;
1388         cs->nranges++;
1389 }
1390
1391 /*
1392  - CHaddtype - add all characters of a certain type to a character set.
1393  */
1394 static void
1395 CHaddtype(struct parse *p, cset *cs, wctype_t wct)
1396 {
1397         wint_t i;
1398         wctype_t *newtypes;
1399
1400         for (i = 0; i < NC; i++)
1401                 if (iswctype(i, wct))
1402                         CHadd(p, cs, i);
1403         newtypes = reallocarray(cs->types, cs->ntypes + 1,
1404             sizeof(*cs->types));
1405         if (newtypes == NULL) {
1406                 SETERROR(REG_ESPACE);
1407                 return;
1408         }
1409         cs->types = newtypes;
1410         cs->types[cs->ntypes++] = wct;
1411 }
1412
1413 /*
1414  - dupl - emit a duplicate of a bunch of sops
1415  == static sopno dupl(struct parse *p, sopno start, sopno finish);
1416  */
1417 static sopno                    /* start of duplicate */
1418 dupl(struct parse *p,
1419         sopno start,            /* from here */
1420         sopno finish)           /* to this less one */
1421 {
1422         sopno ret = HERE();
1423         sopno len = finish - start;
1424
1425         assert(finish >= start);
1426         if (len == 0)
1427                 return(ret);
1428         if (!enlarge(p, p->ssize + len)) /* this many unexpected additions */
1429                 return(ret);
1430         (void) memcpy((char *)(p->strip + p->slen),
1431                 (char *)(p->strip + start), (size_t)len*sizeof(sop));
1432         p->slen += len;
1433         return(ret);
1434 }
1435
1436 /*
1437  - doemit - emit a strip operator
1438  == static void doemit(struct parse *p, sop op, size_t opnd);
1439  *
1440  * It might seem better to implement this as a macro with a function as
1441  * hard-case backup, but it's just too big and messy unless there are
1442  * some changes to the data structures.  Maybe later.
1443  */
1444 static void
1445 doemit(struct parse *p, sop op, size_t opnd)
1446 {
1447         /* avoid making error situations worse */
1448         if (p->error != 0)
1449                 return;
1450
1451         /* deal with oversize operands ("can't happen", more or less) */
1452         assert(opnd < 1<<OPSHIFT);
1453
1454         /* deal with undersized strip */
1455         if (p->slen >= p->ssize)
1456                 if (!enlarge(p, (p->ssize+1) / 2 * 3))  /* +50% */
1457                         return;
1458
1459         /* finally, it's all reduced to the easy case */
1460         p->strip[p->slen++] = SOP(op, opnd);
1461 }
1462
1463 /*
1464  - doinsert - insert a sop into the strip
1465  == static void doinsert(struct parse *p, sop op, size_t opnd, sopno pos);
1466  */
1467 static void
1468 doinsert(struct parse *p, sop op, size_t opnd, sopno pos)
1469 {
1470         sopno sn;
1471         sop s;
1472         int i;
1473
1474         /* avoid making error situations worse */
1475         if (p->error != 0)
1476                 return;
1477
1478         sn = HERE();
1479         EMIT(op, opnd);         /* do checks, ensure space */
1480         assert(HERE() == sn+1);
1481         s = p->strip[sn];
1482
1483         /* adjust paren pointers */
1484         assert(pos > 0);
1485         for (i = 1; i < NPAREN; i++) {
1486                 if (p->pbegin[i] >= pos) {
1487                         p->pbegin[i]++;
1488                 }
1489                 if (p->pend[i] >= pos) {
1490                         p->pend[i]++;
1491                 }
1492         }
1493
1494         memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos],
1495                                                 (HERE()-pos-1)*sizeof(sop));
1496         p->strip[pos] = s;
1497 }
1498
1499 /*
1500  - dofwd - complete a forward reference
1501  == static void dofwd(struct parse *p, sopno pos, sop value);
1502  */
1503 static void
1504 dofwd(struct parse *p, sopno pos, sop value)
1505 {
1506         /* avoid making error situations worse */
1507         if (p->error != 0)
1508                 return;
1509
1510         assert(value < 1<<OPSHIFT);
1511         p->strip[pos] = OP(p->strip[pos]) | value;
1512 }
1513
1514 /*
1515  - enlarge - enlarge the strip
1516  == static int enlarge(struct parse *p, sopno size);
1517  */
1518 static int
1519 enlarge(struct parse *p, sopno size)
1520 {
1521         sop *sp;
1522
1523         if (p->ssize >= size)
1524                 return 1;
1525
1526         sp = reallocarray(p->strip, size, sizeof(sop));
1527         if (sp == NULL) {
1528                 SETERROR(REG_ESPACE);
1529                 return 0;
1530         }
1531         p->strip = sp;
1532         p->ssize = size;
1533         return 1;
1534 }
1535
1536 /*
1537  - stripsnug - compact the strip
1538  == static void stripsnug(struct parse *p, struct re_guts *g);
1539  */
1540 static void
1541 stripsnug(struct parse *p, struct re_guts *g)
1542 {
1543         g->nstates = p->slen;
1544         g->strip = reallocarray((char *)p->strip, p->slen, sizeof(sop));
1545         if (g->strip == NULL) {
1546                 SETERROR(REG_ESPACE);
1547                 g->strip = p->strip;
1548         }
1549 }
1550
1551 /*
1552  - findmust - fill in must and mlen with longest mandatory literal string
1553  == static void findmust(struct parse *p, struct re_guts *g);
1554  *
1555  * This algorithm could do fancy things like analyzing the operands of |
1556  * for common subsequences.  Someday.  This code is simple and finds most
1557  * of the interesting cases.
1558  *
1559  * Note that must and mlen got initialized during setup.
1560  */
1561 static void
1562 findmust(struct parse *p, struct re_guts *g)
1563 {
1564         sop *scan;
1565         sop *start = NULL;
1566         sop *newstart = NULL;
1567         sopno newlen;
1568         sop s;
1569         char *cp;
1570         int offset;
1571         char buf[MB_LEN_MAX];
1572         size_t clen;
1573         mbstate_t mbs;
1574
1575         /* avoid making error situations worse */
1576         if (p->error != 0)
1577                 return;
1578
1579         /*
1580          * It's not generally safe to do a ``char'' substring search on
1581          * multibyte character strings, but it's safe for at least
1582          * UTF-8 (see RFC 3629).
1583          */
1584         if (MB_CUR_MAX > 1 &&
1585             strcmp(_CurrentRuneLocale->__encoding, "UTF-8") != 0)
1586                 return;
1587
1588         /* find the longest OCHAR sequence in strip */
1589         newlen = 0;
1590         offset = 0;
1591         g->moffset = 0;
1592         scan = g->strip + 1;
1593         do {
1594                 s = *scan++;
1595                 switch (OP(s)) {
1596                 case OCHAR:             /* sequence member */
1597                         if (newlen == 0) {              /* new sequence */
1598                                 memset(&mbs, 0, sizeof(mbs));
1599                                 newstart = scan - 1;
1600                         }
1601                         clen = wcrtomb(buf, OPND(s), &mbs);
1602                         if (clen == (size_t)-1)
1603                                 goto toohard;
1604                         newlen += clen;
1605                         break;
1606                 case OPLUS_:            /* things that don't break one */
1607                 case OLPAREN:
1608                 case ORPAREN:
1609                         break;
1610                 case OQUEST_:           /* things that must be skipped */
1611                 case OCH_:
1612                         offset = altoffset(scan, offset);
1613                         scan--;
1614                         do {
1615                                 scan += OPND(s);
1616                                 s = *scan;
1617                                 /* assert() interferes w debug printouts */
1618                                 if (OP(s) != O_QUEST && OP(s) != O_CH &&
1619                                                         OP(s) != OOR2) {
1620                                         g->iflags |= BAD;
1621                                         return;
1622                                 }
1623                         } while (OP(s) != O_QUEST && OP(s) != O_CH);
1624                         /* FALLTHROUGH */
1625                 case OBOW:              /* things that break a sequence */
1626                 case OEOW:
1627                 case OBOL:
1628                 case OEOL:
1629                 case O_QUEST:
1630                 case O_CH:
1631                 case OEND:
1632                         if (newlen > g->mlen) {         /* ends one */
1633                                 start = newstart;
1634                                 g->mlen = newlen;
1635                                 if (offset > -1) {
1636                                         g->moffset += offset;
1637                                         offset = newlen;
1638                                 } else
1639                                         g->moffset = offset;
1640                         } else {
1641                                 if (offset > -1)
1642                                         offset += newlen;
1643                         }
1644                         newlen = 0;
1645                         break;
1646                 case OANY:
1647                         if (newlen > g->mlen) {         /* ends one */
1648                                 start = newstart;
1649                                 g->mlen = newlen;
1650                                 if (offset > -1) {
1651                                         g->moffset += offset;
1652                                         offset = newlen;
1653                                 } else
1654                                         g->moffset = offset;
1655                         } else {
1656                                 if (offset > -1)
1657                                         offset += newlen;
1658                         }
1659                         if (offset > -1)
1660                                 offset++;
1661                         newlen = 0;
1662                         break;
1663                 case OANYOF:            /* may or may not invalidate offset */
1664                         /* First, everything as OANY */
1665                         if (newlen > g->mlen) {         /* ends one */
1666                                 start = newstart;
1667                                 g->mlen = newlen;
1668                                 if (offset > -1) {
1669                                         g->moffset += offset;
1670                                         offset = newlen;
1671                                 } else
1672                                         g->moffset = offset;
1673                         } else {
1674                                 if (offset > -1)
1675                                         offset += newlen;
1676                         }
1677                         if (offset > -1)
1678                                 offset++;
1679                         newlen = 0;
1680                         break;
1681                 toohard:
1682                 default:
1683                         /* Anything here makes it impossible or too hard
1684                          * to calculate the offset -- so we give up;
1685                          * save the last known good offset, in case the
1686                          * must sequence doesn't occur later.
1687                          */
1688                         if (newlen > g->mlen) {         /* ends one */
1689                                 start = newstart;
1690                                 g->mlen = newlen;
1691                                 if (offset > -1)
1692                                         g->moffset += offset;
1693                                 else
1694                                         g->moffset = offset;
1695                         }
1696                         offset = -1;
1697                         newlen = 0;
1698                         break;
1699                 }
1700         } while (OP(s) != OEND);
1701
1702         if (g->mlen == 0) {             /* there isn't one */
1703                 g->moffset = -1;
1704                 return;
1705         }
1706
1707         /* turn it into a character string */
1708         g->must = malloc((size_t)g->mlen + 1);
1709         if (g->must == NULL) {          /* argh; just forget it */
1710                 g->mlen = 0;
1711                 g->moffset = -1;
1712                 return;
1713         }
1714         cp = g->must;
1715         scan = start;
1716         memset(&mbs, 0, sizeof(mbs));
1717         while (cp < g->must + g->mlen) {
1718                 while (OP(s = *scan++) != OCHAR)
1719                         continue;
1720                 clen = wcrtomb(cp, OPND(s), &mbs);
1721                 assert(clen != (size_t)-1);
1722                 cp += clen;
1723         }
1724         assert(cp == g->must + g->mlen);
1725         *cp++ = '\0';           /* just on general principles */
1726 }
1727
1728 /*
1729  - altoffset - choose biggest offset among multiple choices
1730  == static int altoffset(sop *scan, int offset);
1731  *
1732  * Compute, recursively if necessary, the largest offset among multiple
1733  * re paths.
1734  */
1735 static int
1736 altoffset(sop *scan, int offset)
1737 {
1738         int largest;
1739         int try;
1740         sop s;
1741
1742         /* If we gave up already on offsets, return */
1743         if (offset == -1)
1744                 return -1;
1745
1746         largest = 0;
1747         try = 0;
1748         s = *scan++;
1749         while (OP(s) != O_QUEST && OP(s) != O_CH) {
1750                 switch (OP(s)) {
1751                 case OOR1:
1752                         if (try > largest)
1753                                 largest = try;
1754                         try = 0;
1755                         break;
1756                 case OQUEST_:
1757                 case OCH_:
1758                         try = altoffset(scan, try);
1759                         if (try == -1)
1760                                 return -1;
1761                         scan--;
1762                         do {
1763                                 scan += OPND(s);
1764                                 s = *scan;
1765                                 if (OP(s) != O_QUEST && OP(s) != O_CH &&
1766                                                         OP(s) != OOR2)
1767                                         return -1;
1768                         } while (OP(s) != O_QUEST && OP(s) != O_CH);
1769                         /* We must skip to the next position, or we'll
1770                          * leave altoffset() too early.
1771                          */
1772                         scan++;
1773                         break;
1774                 case OANYOF:
1775                 case OCHAR:
1776                 case OANY:
1777                         try++;
1778                 case OBOW:
1779                 case OEOW:
1780                 case OLPAREN:
1781                 case ORPAREN:
1782                 case OOR2:
1783                         break;
1784                 default:
1785                         try = -1;
1786                         break;
1787                 }
1788                 if (try == -1)
1789                         return -1;
1790                 s = *scan++;
1791         }
1792
1793         if (try > largest)
1794                 largest = try;
1795
1796         return largest+offset;
1797 }
1798
1799 /*
1800  - computejumps - compute char jumps for BM scan
1801  == static void computejumps(struct parse *p, struct re_guts *g);
1802  *
1803  * This algorithm assumes g->must exists and is has size greater than
1804  * zero. It's based on the algorithm found on Computer Algorithms by
1805  * Sara Baase.
1806  *
1807  * A char jump is the number of characters one needs to jump based on
1808  * the value of the character from the text that was mismatched.
1809  */
1810 static void
1811 computejumps(struct parse *p, struct re_guts *g)
1812 {
1813         int ch;
1814         int mindex;
1815
1816         /* Avoid making errors worse */
1817         if (p->error != 0)
1818                 return;
1819
1820         g->charjump = (int*) malloc((NC + 1) * sizeof(int));
1821         if (g->charjump == NULL)        /* Not a fatal error */
1822                 return;
1823         /* Adjust for signed chars, if necessary */
1824         g->charjump = &g->charjump[-(CHAR_MIN)];
1825
1826         /* If the character does not exist in the pattern, the jump
1827          * is equal to the number of characters in the pattern.
1828          */
1829         for (ch = CHAR_MIN; ch < (CHAR_MAX + 1); ch++)
1830                 g->charjump[ch] = g->mlen;
1831
1832         /* If the character does exist, compute the jump that would
1833          * take us to the last character in the pattern equal to it
1834          * (notice that we match right to left, so that last character
1835          * is the first one that would be matched).
1836          */
1837         for (mindex = 0; mindex < g->mlen; mindex++)
1838                 g->charjump[(int)g->must[mindex]] = g->mlen - mindex - 1;
1839 }
1840
1841 /*
1842  - computematchjumps - compute match jumps for BM scan
1843  == static void computematchjumps(struct parse *p, struct re_guts *g);
1844  *
1845  * This algorithm assumes g->must exists and is has size greater than
1846  * zero. It's based on the algorithm found on Computer Algorithms by
1847  * Sara Baase.
1848  *
1849  * A match jump is the number of characters one needs to advance based
1850  * on the already-matched suffix.
1851  * Notice that all values here are minus (g->mlen-1), because of the way
1852  * the search algorithm works.
1853  */
1854 static void
1855 computematchjumps(struct parse *p, struct re_guts *g)
1856 {
1857         int mindex;             /* General "must" iterator */
1858         int suffix;             /* Keeps track of matching suffix */
1859         int ssuffix;            /* Keeps track of suffixes' suffix */
1860         int* pmatches;          /* pmatches[k] points to the next i
1861                                  * such that i+1...mlen is a substring
1862                                  * of k+1...k+mlen-i-1
1863                                  */
1864
1865         /* Avoid making errors worse */
1866         if (p->error != 0)
1867                 return;
1868
1869         pmatches = (int*) malloc(g->mlen * sizeof(int));
1870         if (pmatches == NULL) {
1871                 g->matchjump = NULL;
1872                 return;
1873         }
1874
1875         g->matchjump = (int*) malloc(g->mlen * sizeof(int));
1876         if (g->matchjump == NULL) {     /* Not a fatal error */
1877                 free(pmatches);
1878                 return;
1879         }
1880
1881         /* Set maximum possible jump for each character in the pattern */
1882         for (mindex = 0; mindex < g->mlen; mindex++)
1883                 g->matchjump[mindex] = 2*g->mlen - mindex - 1;
1884
1885         /* Compute pmatches[] */
1886         for (mindex = g->mlen - 1, suffix = g->mlen; mindex >= 0;
1887             mindex--, suffix--) {
1888                 pmatches[mindex] = suffix;
1889
1890                 /* If a mismatch is found, interrupting the substring,
1891                  * compute the matchjump for that position. If no
1892                  * mismatch is found, then a text substring mismatched
1893                  * against the suffix will also mismatch against the
1894                  * substring.
1895                  */
1896                 while (suffix < g->mlen
1897                     && g->must[mindex] != g->must[suffix]) {
1898                         g->matchjump[suffix] = MIN(g->matchjump[suffix],
1899                             g->mlen - mindex - 1);
1900                         suffix = pmatches[suffix];
1901                 }
1902         }
1903
1904         /* Compute the matchjump up to the last substring found to jump
1905          * to the beginning of the largest must pattern prefix matching
1906          * it's own suffix.
1907          */
1908         for (mindex = 0; mindex <= suffix; mindex++)
1909                 g->matchjump[mindex] = MIN(g->matchjump[mindex],
1910                     g->mlen + suffix - mindex);
1911
1912         ssuffix = pmatches[suffix];
1913         while (suffix < g->mlen) {
1914                 while (suffix <= ssuffix && suffix < g->mlen) {
1915                         g->matchjump[suffix] = MIN(g->matchjump[suffix],
1916                             g->mlen + ssuffix - suffix);
1917                         suffix++;
1918                 }
1919                 if (suffix < g->mlen)
1920                         ssuffix = pmatches[ssuffix];
1921         }
1922
1923         free(pmatches);
1924 }
1925
1926 /*
1927  - pluscount - count + nesting
1928  == static sopno pluscount(struct parse *p, struct re_guts *g);
1929  */
1930 static sopno                    /* nesting depth */
1931 pluscount(struct parse *p, struct re_guts *g)
1932 {
1933         sop *scan;
1934         sop s;
1935         sopno plusnest = 0;
1936         sopno maxnest = 0;
1937
1938         if (p->error != 0)
1939                 return(0);      /* there may not be an OEND */
1940
1941         scan = g->strip + 1;
1942         do {
1943                 s = *scan++;
1944                 switch (OP(s)) {
1945                 case OPLUS_:
1946                         plusnest++;
1947                         break;
1948                 case O_PLUS:
1949                         if (plusnest > maxnest)
1950                                 maxnest = plusnest;
1951                         plusnest--;
1952                         break;
1953                 }
1954         } while (OP(s) != OEND);
1955         if (plusnest != 0)
1956                 g->iflags |= BAD;
1957         return(maxnest);
1958 }