]> git.pld-linux.org Git - packages/apparmor-parser.git/blob - apparmor-parser-bzr.patch
- rel 2; fix skipping unwanted profiles; allow to pass own options to parser
[packages/apparmor-parser.git] / apparmor-parser-bzr.patch
1 === added file '.bzrignore'
2 --- .bzrignore  1970-01-01 00:00:00 +0000
3 +++ .bzrignore  2010-08-03 17:27:13 +0000
4 @@ -0,0 +1,165 @@
5 +parser/po/*.mo
6 +parser/af_names.h
7 +parser/cap_names.h
8 +parser/tst_misc
9 +parser/tst_regex
10 +parser/tst_symtab
11 +parser/tst_variable
12 +parser/parser_lex.c
13 +parser/parser_version.h
14 +parser/parser_yacc.c
15 +parser/parser_yacc.h
16 +parser/pod2htm*.tmp
17 +parser/*.7
18 +parser/*.5
19 +parser/*.8
20 +parser/*.7.html
21 +parser/*.5.html
22 +parser/*.8.html
23 +parser/common
24 +parser/apparmor_parser
25 +parser/libapparmor_re/regexp.cc
26 +parser/techdoc.aux
27 +parser/techdoc.log
28 +parser/techdoc.pdf
29 +parser/techdoc.toc
30 +libraries/libapparmor/Makefile
31 +libraries/libapparmor/Makefile.in
32 +libraries/libapparmor/aclocal.m4
33 +libraries/libapparmor/audit.log
34 +libraries/libapparmor/autom4te.cache
35 +libraries/libapparmor/compile
36 +libraries/libapparmor/config.guess
37 +libraries/libapparmor/config.log
38 +libraries/libapparmor/config.status
39 +libraries/libapparmor/config.sub
40 +libraries/libapparmor/configure
41 +libraries/libapparmor/depcomp
42 +libraries/libapparmor/install-sh
43 +libraries/libapparmor/libtool
44 +libraries/libapparmor/ltmain.sh
45 +libraries/libapparmor/missing
46 +libraries/libapparmor/ylwrap
47 +libraries/libapparmor/doc/Makefile
48 +libraries/libapparmor/doc/Makefile.in
49 +libraries/libapparmor/doc/aa_change_hat.2
50 +libraries/libapparmor/src/.deps
51 +libraries/libapparmor/src/.libs
52 +libraries/libapparmor/src/Makefile
53 +libraries/libapparmor/src/Makefile.in
54 +libraries/libapparmor/src/af_protos.h
55 +libraries/libapparmor/src/change_hat.lo
56 +libraries/libapparmor/src/grammar.lo
57 +libraries/libapparmor/src/libaalogparse.lo
58 +libraries/libapparmor/src/libimmunix_warning.lo
59 +libraries/libapparmor/src/scanner.lo
60 +libraries/libapparmor/src/libapparmor.la
61 +libraries/libapparmor/src/libimmunix.la
62 +libraries/libapparmor/src/grammar.c
63 +libraries/libapparmor/src/grammar.h
64 +libraries/libapparmor/src/scanner.c
65 +libraries/libapparmor/src/scanner.h
66 +libraries/libapparmor/src/tst_aalogmisc
67 +libraries/libapparmor/swig/Makefile
68 +libraries/libapparmor/swig/Makefile.in
69 +libraries/libapparmor/swig/perl/LibAppArmor.bs
70 +libraries/libapparmor/swig/perl/LibAppArmor.pm
71 +libraries/libapparmor/swig/perl/Makefile
72 +libraries/libapparmor/swig/perl/Makefile.PL
73 +libraries/libapparmor/swig/perl/Makefile.in
74 +libraries/libapparmor/swig/perl/Makefile.perl
75 +libraries/libapparmor/swig/perl/blib
76 +libraries/libapparmor/swig/perl/libapparmor_wrap.c
77 +libraries/libapparmor/swig/perl/pm_to_blib
78 +libraries/libapparmor/swig/python/Makefile
79 +libraries/libapparmor/swig/python/Makefile.in
80 +libraries/libapparmor/swig/python/setup.py
81 +libraries/libapparmor/swig/ruby/Makefile
82 +libraries/libapparmor/swig/ruby/Makefile.in
83 +libraries/libapparmor/testsuite/.deps
84 +libraries/libapparmor/testsuite/.libs
85 +libraries/libapparmor/testsuite/Makefile
86 +libraries/libapparmor/testsuite/Makefile.in
87 +libraries/libapparmor/testsuite/libaalogparse.log
88 +libraries/libapparmor/testsuite/libaalogparse.sum
89 +libraries/libapparmor/testsuite/site.exp
90 +libraries/libapparmor/testsuite/test_multi.multi
91 +libraries/libapparmor/testsuite/config/Makefile
92 +libraries/libapparmor/testsuite/config/Makefile.in
93 +libraries/libapparmor/testsuite/lib/Makefile
94 +libraries/libapparmor/testsuite/lib/Makefile.in
95 +libraries/libapparmor/testsuite/libaalogparse.test/Makefile
96 +libraries/libapparmor/testsuite/libaalogparse.test/Makefile.in
97 +libraries/libapparmor/testsuite/test_multi/out
98 +changehat/mod_apparmor/.libs
99 +changehat/mod_apparmor/common
100 +changehat/pam_apparmor/common
101 +changehat/tomcat_apparmor/common
102 +utils/common
103 +utils/*.8
104 +utils/*.8.html
105 +utils/*.5
106 +utils/*.5.html
107 +utils/*.tmp
108 +utils/po/*.mo
109 +tests/regression/apparmor/access
110 +tests/regression/apparmor/changehat
111 +tests/regression/apparmor/changehat_fail
112 +tests/regression/apparmor/changehat_fork
113 +tests/regression/apparmor/changehat_misc
114 +tests/regression/apparmor/changehat_misc2
115 +tests/regression/apparmor/changehat_pthread
116 +tests/regression/apparmor/changehat_twice
117 +tests/regression/apparmor/changehat_wrapper
118 +tests/regression/apparmor/changeprofile
119 +tests/regression/apparmor/chdir
120 +tests/regression/apparmor/chgrp
121 +tests/regression/apparmor/chmod
122 +tests/regression/apparmor/chown
123 +tests/regression/apparmor/clone
124 +tests/regression/apparmor/deleted
125 +tests/regression/apparmor/env_check
126 +tests/regression/apparmor/environ
127 +tests/regression/apparmor/exec
128 +tests/regression/apparmor/exec_qual
129 +tests/regression/apparmor/exec_qual2
130 +tests/regression/apparmor/fchdir
131 +tests/regression/apparmor/fchgrp
132 +tests/regression/apparmor/fchmod
133 +tests/regression/apparmor/fchown
134 +tests/regression/apparmor/fork
135 +tests/regression/apparmor/link
136 +tests/regression/apparmor/link_subset
137 +tests/regression/apparmor/mkdir
138 +tests/regression/apparmor/mmap
139 +tests/regression/apparmor/mount
140 +tests/regression/apparmor/named_pipe
141 +tests/regression/apparmor/net_raw
142 +tests/regression/apparmor/open
143 +tests/regression/apparmor/openat
144 +tests/regression/apparmor/pipe
145 +tests/regression/apparmor/ptrace
146 +tests/regression/apparmor/ptrace_helper
147 +tests/regression/apparmor/pwrite
148 +tests/regression/apparmor/readdir
149 +tests/regression/apparmor/rename
150 +tests/regression/apparmor/rw
151 +tests/regression/apparmor/swap
152 +tests/regression/apparmor/symlink
153 +tests/regression/apparmor/syscall_chroot
154 +tests/regression/apparmor/syscall_mknod
155 +tests/regression/apparmor/syscall_mlockall
156 +tests/regression/apparmor/syscall_ptrace
157 +tests/regression/apparmor/syscall_reboot
158 +tests/regression/apparmor/syscall_setdomainname
159 +tests/regression/apparmor/syscall_sethostname
160 +tests/regression/apparmor/syscall_setpriority
161 +tests/regression/apparmor/syscall_setscheduler
162 +tests/regression/apparmor/syscall_sysctl
163 +tests/regression/apparmor/sysctl_proc
164 +tests/regression/apparmor/tcp
165 +tests/regression/apparmor/unix_fd_client
166 +tests/regression/apparmor/unix_fd_server
167 +tests/regression/apparmor/unlink
168 +tests/regression/apparmor/xattrs
169 +tests/regression/apparmor/coredump
170
171 === added file 'README'
172 --- README      1970-01-01 00:00:00 +0000
173 +++ README      2010-08-03 17:27:13 +0000
174 @@ -0,0 +1,155 @@
175 +------------
176 +Introduction
177 +------------
178 +AppArmor protects systems from insecure or untrusted processes by
179 +running them in restricted confinement, while still allowing processes
180 +to share files, exercise privilege and communicate with other processes.
181 +AppArmor is a Mandatory Access Control (MAC) mechanism which uses the
182 +Linux Security Module (LSM) framework. The confinement's restrictions
183 +are mandatory and are not bound to identity, group membership, or object
184 +ownership. The protections provided are in addition to the kernel's
185 +regular access control mechanisms (including DAC) and can be used to
186 +restrict the superuser.
187 +
188 +The AppArmor kernel module and accompanying user-space tools are
189 +available under the GPL license (the exception is the libapparmor
190 +library, available under the LGPL license, which allows change_hat(2)
191 +and change_profile(2) to be used by non-GPL binaries).
192 +
193 +For more information, you can read the techdoc.pdf (available after
194 +building the parser) and http://apparmor.wiki.kernel.org.
195 +
196 +
197 +-------------
198 +Source Layout
199 +-------------
200 +
201 +AppArmor consists of several different parts:
202 +
203 +changehat/     source for using changehat with Apache, PAM and Tomcat
204 +common/                common makefile rules
205 +desktop/       empty
206 +kernel-patches/        patches for various kernel versions
207 +libraries/     libapparmor source and language bindings
208 +parser/                source for parser/loader and corresponding documentation
209 +profiles/      configuration files, reference profiles and abstractions
210 +tests/         regression and stress testsuites
211 +utils/         high-level utilities for working with AppArmor
212 +
213 +
214 +------------------------------------------
215 +Building and Installing AppArmor Userspace
216 +------------------------------------------
217 +
218 +To build and install AppArmor userspace on your system, build and install in
219 +the following order.
220 +
221 +
222 +libapparmor:
223 +$ cd ./libraries/libapparmor
224 +$ sh ./autogen.sh
225 +$ sh ./configure --prefix=/usr --with-perl
226 +$ make
227 +$ make check
228 +
229 +
230 +Utilities:
231 +$ cd utils
232 +$ make
233 +$ make install
234 +
235 +
236 +parser:
237 +$ cd parser
238 +$ make
239 +$ make tests   # not strictly necessary as they are run during the
240 +               # build by default
241 +$ make install
242 +
243 +
244 +Apache mod_apparmor:
245 +$ cd changehat/mod_apparmor
246 +$ LIBS="-lapparmor" make
247 +$ make install
248 +
249 +
250 +PAM AppArmor:
251 +$ cd changehat/pam_apparmor
252 +$ LIBS="-lapparmor -lpam" make
253 +$ make install
254 +
255 +
256 +Profiles:
257 +$ cd profiles
258 +$ make
259 +$ make install
260 +
261 +
262 +
263 +-------------------
264 +AppArmor Testsuites
265 +-------------------
266 +
267 +A number of testsuites are in the AppArmor sources. Most have documentation on
268 +usage and how to update and add tests. Below is a quick overview of their
269 +location and how to run them.
270 +
271 +
272 +Regression tests
273 +----------------
274 +For details on structure and adding tests, see
275 +tests/regression/apparmor/README.
276 +
277 +To run:
278 +$ cd tests/regression/apparmor (requires root)
279 +$ make
280 +$ sudo make tests
281 +$ sudo bash open.sh -r  # runs and saves the last testcase from open.sh
282 +
283 +
284 +Parser tests
285 +------------
286 +For details on structure and adding tests, see parser/tst/README.
287 +
288 +To run:
289 +$ cd parser/tst
290 +$ make
291 +$ make tests
292 +
293 +
294 +Libapparmor
295 +-----------
296 +For details on structure and adding tests, see libraries/libapparmor/README.
297 +$ cd libraries/libapparmor
298 +$ make check
299 +
300 +
301 +Stress Tests
302 +------------
303 +To run AppArmor stress tests:
304 +$ make all
305 +
306 +Use these:
307 +$ ./change_hat
308 +$ ./child
309 +$ ./kill.sh
310 +$ ./open
311 +$ ./s.sh
312 +
313 +Or run all at once:
314 +$ ./stress.sh
315 +
316 +Please note that the above will stress the system so much it may end up
317 +invoking the OOM killer.
318 +
319 +To run parser stress tests (requires /usr/bin/ruby):
320 +$ ./stress.sh
321 +
322 +(see stress.sh -h for options)
323 +
324 +-----------------------------------------------
325 +Building and Installing AppArmor Kernel Patches
326 +-----------------------------------------------
327 +
328 +TODO
329 +
330
331 === modified file 'common/Make.rules'
332 --- common/Make.rules   2010-03-11 07:07:29 +0000
333 +++ common/Make.rules   2010-08-03 17:27:13 +0000
334 @@ -48,7 +48,7 @@
335                     echo "/tmp/${NAME}"  ; \
336                   fi ;)
337  endif
338 -RPMHOSTVENDOR=$(shell rpm --eval "%{_host_vendor}")
339 +RPMHOSTVENDOR=$(shell which rpm && rpm --eval "%{_host_vendor}")
340  ifndef DISTRO
341  DISTRO=$(shell if [ -f /etc/slackware-version ] ; then \
342                   echo slackware ; \
343 @@ -92,30 +92,16 @@
344  ifndef SPECFILE
345  SPECFILE        = $(NAME).spec
346  endif
347 -RELEASE = $(shell rpm -q --specfile --define "_sourcedir ." ${RPMARG} --qf "%{RELEASE}" ${SPECFILE})
348 +RELEASE                = $(shell lsb_release -is) $(shell lsb_release -rs)
349  RELEASE_DIR    = $(NAME)-$(VERSION)
350  TARBALL                = $(NAME)-$(VERSION)-${REPO_VERSION}.tar.gz
351 -TAR            = /bin/tar czvp -h --exclude .svn --exclude CVS --exclude .cvsignore --exclude ${TARBALL} --exclude ${RELEASE_DIR}/${RELEASE_DIR}  $(shell test -f ${NAME}.exclude && echo "-X ${NAME}.exclude")
352 +TAR            = /bin/tar czvp -h --exclude .svn --exclude .bzr --exclude .bzrignore --exclude ${TARBALL} --exclude ${RELEASE_DIR}/${RELEASE_DIR}  $(shell test -f ${NAME}.exclude && echo "-X ${NAME}.exclude")
353  LDCONFIG       = /sbin/ldconfig
354  
355 -CVSPKG_VERSION=$(shell rpm -q --specfile --define "_sourcedir ." ${RPMARG} ${SPECFILE} | head -1 | tr "." "_")
356 -
357  RPMSUBDIRS=SOURCES SPECS BUILD BUILDROOT SRPMS RPMS/i386 RPMS/i586 \
358          RPMS/i686 RPMS/athlon RPMS/noarch RPMS/x86_64
359  BUILDRPMSUBDIRS=$(foreach subdir, $(RPMSUBDIRS), $(BUILDDIR:/=)/$(subdir))
360  
361 -.PHONY: cvs_tag
362 -cvs_tag:
363 -       cvs tag IMMUNIX-${CVSPKG_VERSION}
364 -
365 -.PHONY: checkin
366 -checkin:
367 -       if cvs -q up -d | grep -q "^\?" ; then echo "Hey! You have" \
368 -               "files in the directory you have not added into cvs."; exit 1; \
369 -       fi
370 -       cvs ci
371 -       make cvs_tag
372 -
373  ifdef EXTERNAL_PACKAGE
374  .PHONY: rpm
375  rpm: clean $(BUILDRPMSUBDIRS)
376
377 === modified file 'libraries/libapparmor/src/aalogparse.h'
378 --- libraries/libapparmor/src/aalogparse.h      2009-09-18 21:13:04 +0000
379 +++ libraries/libapparmor/src/aalogparse.h      2010-08-03 17:27:13 +0000
380 @@ -129,6 +129,7 @@
381         unsigned long fsuid;            /* fsuid of task - if logged */
382         unsigned long ouid;             /* ouid of task - if logged */
383         char *profile;                  /* The name of the profile */
384 +       char *comm;                     /* Command that triggered msg */
385         char *name;
386         char *name2;
387         char *namespace;
388
389 === modified file 'libraries/libapparmor/src/change_hat.c'
390 --- libraries/libapparmor/src/change_hat.c      2010-02-11 23:38:24 +0000
391 +++ libraries/libapparmor/src/change_hat.c      2010-08-03 17:27:13 +0000
392 @@ -194,7 +194,7 @@
393         /* setup command string which is of the form
394          * changehat <token>^hat1\0hat2\0hat3\0..\0
395          */
396 -       sprintf(buf, "%s %016x^", cmd, token);
397 +       sprintf(buf, "%s %016lx^", cmd, token);
398         pos = buf + strlen(buf);
399         if (subprofiles) {
400                 for (hats = subprofiles; *hats; hats++) {
401
402 === modified file 'libraries/libapparmor/src/grammar.y'
403 --- libraries/libapparmor/src/grammar.y 2009-09-18 21:13:04 +0000
404 +++ libraries/libapparmor/src/grammar.y 2010-08-03 17:27:13 +0000
405 @@ -1,6 +1,7 @@
406  /*
407   *   Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
408   *   NOVELL (All rights reserved)
409 + *   Copyright (c) 2010, Canonical, Ltd.
410   *
411   *   This program is free software; you can redistribute it and/or
412   *   modify it under the terms of version 2 of the GNU General Public
413 @@ -96,6 +97,13 @@
414  %token TOK_TYPE_HINT
415  %token TOK_TYPE_STATUS
416  %token TOK_TYPE_ERROR
417 +%token TOK_TYPE_AA_REJECT
418 +%token TOK_TYPE_AA_AUDIT
419 +%token TOK_TYPE_AA_COMPLAIN
420 +%token TOK_TYPE_AA_HINT
421 +%token TOK_TYPE_AA_STATUS
422 +%token TOK_TYPE_AA_ERROR
423 +%token TOK_TYPE_LSM_AVC
424  %token TOK_OLD_TYPE_APPARMOR
425  %token TOK_OLD_APPARMOR_REJECT
426  %token TOK_OLD_APPARMOR_PERMIT
427 @@ -123,6 +131,7 @@
428  %token TOK_OLD_FORK
429  %token TOK_OLD_CHILD
430  
431 +%token TOK_KEY_APPARMOR
432  %token TOK_KEY_TYPE
433  %token TOK_KEY_MSG
434  %token TOK_KEY_OPERATION
435 @@ -146,6 +155,7 @@
436  %token TOK_KEY_ERROR
437  %token TOK_KEY_FSUID
438  %token TOK_KEY_OUID
439 +%token TOK_KEY_COMM
440  
441  %token TOK_SYSLOG_KERNEL
442  
443 @@ -168,13 +178,14 @@
444         ;
445  
446  new_syntax:
447 -         TOK_TYPE_REJECT audit_msg key_list { ret_record->event = AA_RECORD_DENIED; }
448 -       | TOK_TYPE_AUDIT audit_msg key_list { ret_record->event = AA_RECORD_AUDIT; }
449 -       | TOK_TYPE_COMPLAIN audit_msg key_list { ret_record->event = AA_RECORD_ALLOWED; }
450 -       | TOK_TYPE_HINT audit_msg key_list { ret_record->event = AA_RECORD_HINT; }
451 -       | TOK_TYPE_STATUS audit_msg key_list { ret_record->event = AA_RECORD_STATUS; }
452 -       | TOK_TYPE_ERROR audit_msg key_list { ret_record->event = AA_RECORD_ERROR; }
453 +         TOK_TYPE_AA_REJECT audit_msg key_list { ret_record->event = AA_RECORD_DENIED; }
454 +       | TOK_TYPE_AA_AUDIT audit_msg key_list { ret_record->event = AA_RECORD_AUDIT; }
455 +       | TOK_TYPE_AA_COMPLAIN audit_msg key_list { ret_record->event = AA_RECORD_ALLOWED; }
456 +       | TOK_TYPE_AA_HINT audit_msg key_list { ret_record->event = AA_RECORD_HINT; }
457 +       | TOK_TYPE_AA_STATUS audit_msg key_list { ret_record->event = AA_RECORD_STATUS; }
458 +       | TOK_TYPE_AA_ERROR audit_msg key_list { ret_record->event = AA_RECORD_ERROR; }
459         | TOK_TYPE_UNKNOWN audit_msg key_list { ret_record->event = lookup_aa_event($1); }
460 +       | TOK_TYPE_LSM_AVC audit_msg key_list
461         ;
462  
463  other_audit: TOK_TYPE_OTHER audit_msg TOK_MSG_REST
464 @@ -366,7 +377,8 @@
465  
466  audit_id: TOK_AUDIT TOK_OPEN_PAREN TOK_AUDIT_DIGITS TOK_PERIOD TOK_AUDIT_DIGITS TOK_COLON TOK_AUDIT_DIGITS TOK_CLOSE_PAREN TOK_COLON
467         {
468 -               asprintf(&ret_record->audit_id, "%s.%s:%s", $3, $5, $7);
469 +               if (!asprintf(&ret_record->audit_id, "%s.%s:%s", $3, $5, $7))
470 +                       yyerror(scanner, YY_("Out of memory"));
471                 ret_record->epoch = atol($3);
472                 ret_record->audit_sub_id = atoi($7);
473                 free($3);
474 @@ -420,6 +432,18 @@
475         { ret_record->fsuid = $3;}
476         | TOK_KEY_OUID TOK_EQUALS TOK_DIGITS
477         { ret_record->ouid = $3;}
478 +       | TOK_KEY_COMM TOK_EQUALS TOK_QUOTED_STRING
479 +       { ret_record->comm = $3;}
480 +       | TOK_KEY_APPARMOR TOK_EQUALS apparmor_event
481 +       ;
482 +
483 +apparmor_event:
484 +         TOK_TYPE_REJECT       { ret_record->event = AA_RECORD_DENIED; }
485 +       | TOK_TYPE_AUDIT        { ret_record->event = AA_RECORD_AUDIT; }
486 +       | TOK_TYPE_COMPLAIN     { ret_record->event = AA_RECORD_ALLOWED; }
487 +       | TOK_TYPE_HINT         { ret_record->event = AA_RECORD_HINT; }
488 +       | TOK_TYPE_STATUS       { ret_record->event = AA_RECORD_STATUS; }
489 +       | TOK_TYPE_ERROR        { ret_record->event = AA_RECORD_ERROR; }
490         ;
491  
492  key_pid: TOK_KEY_PID TOK_EQUALS TOK_DIGITS { ret_record->pid = $3; }
493
494 === modified file 'libraries/libapparmor/src/libaalogparse.c'
495 --- libraries/libapparmor/src/libaalogparse.c   2009-09-18 21:13:04 +0000
496 +++ libraries/libapparmor/src/libaalogparse.c   2010-08-03 17:27:13 +0000
497 @@ -56,6 +56,8 @@
498                         free(record->denied_mask);
499                 if (record->profile != NULL)
500                         free(record->profile);
501 +               if (record->comm != NULL)
502 +                       free(record->comm);
503                 if (record->name != NULL)
504                         free(record->name);
505                 if (record->name2 != NULL)
506 @@ -151,7 +153,8 @@
507         if (current->protocol_name) {
508                 ret = strdup(current->protocol_name);
509         } else {
510 -               asprintf(&ret, "unknown(%u)", proto);
511 +               if (!asprintf(&ret, "unknown(%u)", proto))
512 +                       ret = NULL;
513         }
514  
515         return ret;
516
517 === modified file 'libraries/libapparmor/src/scanner.l'
518 --- libraries/libapparmor/src/scanner.l 2010-02-10 23:13:55 +0000
519 +++ libraries/libapparmor/src/scanner.l 2010-08-03 17:27:13 +0000
520 @@ -1,6 +1,7 @@
521  /*
522   *   Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
523   *   NOVELL (All rights reserved)
524 + *   Copyright (c) 2010, Canonical, Ltd.
525   *
526   *   This program is free software; you can redistribute it and/or
527   *   modify it under the terms of version 2 of the GNU General Public
528 @@ -30,6 +31,8 @@
529  
530  #include <assert.h>
531  
532 +#define YY_NO_INPUT
533 +
534  unsigned int string_buf_alloc = 0;
535  unsigned int string_buf_len = 0;
536  char *string_buf = NULL;
537 @@ -84,12 +87,19 @@
538  modes          ({mode_chars}+)|({mode_chars}+::{mode_chars}*)|(::{mode_chars}*)
539  /* New message types */
540  
541 -reject_type            "APPARMOR_DENIED"
542 -audit_type             "APPARMOR_AUDIT"
543 -complain_type          "APPARMOR_ALLOWED"
544 -hint_type              "APPARMOR_HINT"
545 -status_type            "APPARMOR_STATUS"
546 -error_type             "APPARMOR_ERROR"
547 +aa_reject_type         "APPARMOR_DENIED"
548 +aa_audit_type          "APPARMOR_AUDIT"
549 +aa_complain_type       "APPARMOR_ALLOWED"
550 +aa_hint_type           "APPARMOR_HINT"
551 +aa_status_type         "APPARMOR_STATUS"
552 +aa_error_type          "APPARMOR_ERROR"
553 +reject_type            "\"DENIED\""
554 +audit_type             "\"AUDIT\""
555 +complain_type          "\"ALLOWED\""
556 +hint_type              "\"HINT\""
557 +status_type            "\"STATUS\""
558 +error_type             "\"ERROR\""
559 +lsm_avc_type           "AVC"
560  unknown_type           UNKNOWN\[{digits}+\]
561  other_audit_type       [[:alnum:]\[\]_-]+
562  
563 @@ -125,6 +135,7 @@
564  
565  /* Key tokens */
566  
567 +key_apparmor           "apparmor"
568  key_type               "type"
569  key_msg                        "msg"
570  key_operation          "operation"
571 @@ -147,6 +158,7 @@
572  key_error              "error"
573  key_fsuid              "fsuid"
574  key_ouid               "ouid"
575 +key_comm               "comm"
576  audit                  "audit"
577  
578  /* syslog tokens */
579 @@ -240,6 +252,13 @@
580         {hint_type}     { BEGIN(INITIAL); return(TOK_TYPE_HINT); }
581         {status_type}   { BEGIN(INITIAL); return(TOK_TYPE_STATUS); }
582         {error_type}    { BEGIN(INITIAL); return(TOK_TYPE_ERROR); }
583 +       {aa_reject_type}        { BEGIN(INITIAL); return(TOK_TYPE_AA_REJECT); }
584 +       {aa_audit_type} { BEGIN(INITIAL); return(TOK_TYPE_AA_AUDIT); }
585 +       {aa_complain_type}      { BEGIN(INITIAL); return(TOK_TYPE_AA_COMPLAIN); }
586 +       {aa_hint_type}  { BEGIN(INITIAL); return(TOK_TYPE_AA_HINT); }
587 +       {aa_status_type}        { BEGIN(INITIAL); return(TOK_TYPE_AA_STATUS); }
588 +       {aa_error_type} { BEGIN(INITIAL); return(TOK_TYPE_AA_ERROR); }
589 +       {lsm_avc_type}  { BEGIN(INITIAL); return(TOK_TYPE_LSM_AVC); }
590         {unknown_type}  { char *yptr = yytext;
591                           while (*yptr && *yptr != '[')
592                                 yptr++;
593 @@ -300,6 +319,7 @@
594         {key_attribute} { BEGIN(sub_id); return(TOK_KEY_ATTRIBUTE); }
595  }
596  
597 +{key_apparmor}         { BEGIN(audit_types); return(TOK_KEY_APPARMOR); }
598  {key_type}             { BEGIN(audit_types); return(TOK_KEY_TYPE); }
599  {key_msg}              { return(TOK_KEY_MSG); }
600  {key_operation}                { return(TOK_KEY_OPERATION); }
601 @@ -321,6 +341,7 @@
602  {key_error}            { return(TOK_KEY_ERROR); }
603  {key_fsuid}            { return(TOK_KEY_FSUID); }
604  {key_ouid}             { return(TOK_KEY_OUID); }
605 +{key_comm}             { return(TOK_KEY_COMM); }
606  
607  {syslog_kernel}                { BEGIN(dmesg_timestamp); return(TOK_SYSLOG_KERNEL); }
608  {syslog_month}         { yylval->t_str = strdup(yytext); return(TOK_DATE_MONTH); }
609
610 === modified file 'libraries/libapparmor/swig/perl/Makefile.am'
611 --- libraries/libapparmor/swig/perl/Makefile.am 2009-05-12 21:56:56 +0000
612 +++ libraries/libapparmor/swig/perl/Makefile.am 2010-05-31 18:58:40 +0000
613 @@ -1,7 +1,8 @@
614  EXTRA_DIST =Makefile.PL libapparmor_wrap.c LibAppArmor.pm examples/*.pl
615 +
616 +if HAVE_PERL
617  noinst_DATA =LibAppArmor.so
618  
619 -if HAVE_PERL
620  libapparmor_wrap.c: $(srcdir)/../SWIG/libapparmor.i
621         $(SWIG) -perl -I$(srcdir)/../../src -module LibAppArmor -o $@ $(srcdir)/../SWIG/libapparmor.i
622  
623 @@ -27,4 +28,4 @@
624  #rm -f Makefile.perl Makefile.perl.old
625         rm -f *.so # *.o
626  
627 -endif
628 \ No newline at end of file
629 +endif
630
631 === modified file 'libraries/libapparmor/testsuite/test_multi.c'
632 --- libraries/libapparmor/testsuite/test_multi.c        2009-09-18 21:13:04 +0000
633 +++ libraries/libapparmor/testsuite/test_multi.c        2010-08-03 17:27:13 +0000
634 @@ -129,6 +129,10 @@
635                 {
636                         printf("Name: %s\n", record->name);
637                 }
638 +               if (record->comm != NULL)
639 +               {
640 +                       printf("Command: %s\n", record->comm);
641 +               }
642                 if (record->name2 != NULL)
643                 {
644                         printf("Name2: %s\n", record->name2);
645
646 === added file 'libraries/libapparmor/testsuite/test_multi/avc_audit_01.in'
647 --- libraries/libapparmor/testsuite/test_multi/avc_audit_01.in  1970-01-01 00:00:00 +0000
648 +++ libraries/libapparmor/testsuite/test_multi/avc_audit_01.in  2010-08-03 17:27:13 +0000
649 @@ -0,0 +1,1 @@
650 +type=AVC msg=audit(1279948288.415:39): apparmor="DENIED" operation="open" parent=12332 profile="/usr/sbin/cupsd" name="/home/user/.ssh/" pid=12333 comm="ls" requested_mask="r" denied_mask="r" fsuid=0 ouid=1000
651
652 === added file 'libraries/libapparmor/testsuite/test_multi/avc_audit_01.out'
653 --- libraries/libapparmor/testsuite/test_multi/avc_audit_01.out 1970-01-01 00:00:00 +0000
654 +++ libraries/libapparmor/testsuite/test_multi/avc_audit_01.out 2010-08-03 17:27:13 +0000
655 @@ -0,0 +1,16 @@
656 +START
657 +File: test_multi/avc_audit_01.in
658 +Event type: AA_RECORD_DENIED
659 +Audit ID: 1279948288.415:39
660 +Operation: open
661 +Mask: r
662 +Denied Mask: r
663 +fsuid: 0
664 +ouid: 1000
665 +Profile: /usr/sbin/cupsd
666 +Name: /home/user/.ssh/
667 +Command: ls
668 +Parent: 12332
669 +PID: 12333
670 +Epoch: 1279948288
671 +Audit subid: 39
672
673 === added file 'libraries/libapparmor/testsuite/test_multi/avc_audit_02.in'
674 --- libraries/libapparmor/testsuite/test_multi/avc_audit_02.in  1970-01-01 00:00:00 +0000
675 +++ libraries/libapparmor/testsuite/test_multi/avc_audit_02.in  2010-08-03 17:27:13 +0000
676 @@ -0,0 +1,1 @@
677 +type=AVC msg=audit(1279948227.175:27): apparmor="STATUS" operation="profile_replace" name="/sbin/dhclient3" pid=12291 comm="apparmor_parser"
678
679 === added file 'libraries/libapparmor/testsuite/test_multi/avc_audit_02.out'
680 --- libraries/libapparmor/testsuite/test_multi/avc_audit_02.out 1970-01-01 00:00:00 +0000
681 +++ libraries/libapparmor/testsuite/test_multi/avc_audit_02.out 2010-08-03 17:27:13 +0000
682 @@ -0,0 +1,10 @@
683 +START
684 +File: test_multi/avc_audit_02.in
685 +Event type: AA_RECORD_STATUS
686 +Audit ID: 1279948227.175:27
687 +Operation: profile_replace
688 +Name: /sbin/dhclient3
689 +Command: apparmor_parser
690 +PID: 12291
691 +Epoch: 1279948227
692 +Audit subid: 27
693
694 === added file 'libraries/libapparmor/testsuite/test_multi/avc_audit_03.in'
695 --- libraries/libapparmor/testsuite/test_multi/avc_audit_03.in  1970-01-01 00:00:00 +0000
696 +++ libraries/libapparmor/testsuite/test_multi/avc_audit_03.in  2010-08-03 17:27:13 +0000
697 @@ -0,0 +1,1 @@
698 +type=AVC msg=audit(1279968846.035:77): apparmor="ALLOWED" operation="open" parent=7014 profile="/tmp/cat" name="/etc/passwd" pid=21645 comm="cat" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
699
700 === added file 'libraries/libapparmor/testsuite/test_multi/avc_audit_03.out'
701 --- libraries/libapparmor/testsuite/test_multi/avc_audit_03.out 1970-01-01 00:00:00 +0000
702 +++ libraries/libapparmor/testsuite/test_multi/avc_audit_03.out 2010-08-03 17:27:13 +0000
703 @@ -0,0 +1,16 @@
704 +START
705 +File: test_multi/avc_audit_03.in
706 +Event type: AA_RECORD_ALLOWED
707 +Audit ID: 1279968846.035:77
708 +Operation: open
709 +Mask: r
710 +Denied Mask: r
711 +fsuid: 1000
712 +ouid: 0
713 +Profile: /tmp/cat
714 +Name: /etc/passwd
715 +Command: cat
716 +Parent: 7014
717 +PID: 21645
718 +Epoch: 1279968846
719 +Audit subid: 77
720
721 === added file 'libraries/libapparmor/testsuite/test_multi/avc_syslog_01.in'
722 --- libraries/libapparmor/testsuite/test_multi/avc_syslog_01.in 1970-01-01 00:00:00 +0000
723 +++ libraries/libapparmor/testsuite/test_multi/avc_syslog_01.in 2010-08-03 17:27:13 +0000
724 @@ -0,0 +1,1 @@
725 +Jul 24 12:25:33 spriggan kernel: [42416.178567] type=1400 audit(1279967133.365:54): apparmor="DENIED" operation="open" parent=19650 profile="/usr/sbin/cupsd" name="/boot/" pid=19651 comm="ls" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
726
727 === added file 'libraries/libapparmor/testsuite/test_multi/avc_syslog_01.out'
728 --- libraries/libapparmor/testsuite/test_multi/avc_syslog_01.out        1970-01-01 00:00:00 +0000
729 +++ libraries/libapparmor/testsuite/test_multi/avc_syslog_01.out        2010-08-03 17:27:13 +0000
730 @@ -0,0 +1,16 @@
731 +START
732 +File: test_multi/avc_syslog_01.in
733 +Event type: AA_RECORD_DENIED
734 +Audit ID: 1279967133.365:54
735 +Operation: open
736 +Mask: r
737 +Denied Mask: r
738 +fsuid: 0
739 +ouid: 0
740 +Profile: /usr/sbin/cupsd
741 +Name: /boot/
742 +Command: ls
743 +Parent: 19650
744 +PID: 19651
745 +Epoch: 1279967133
746 +Audit subid: 54
747
748 === added file 'libraries/libapparmor/testsuite/test_multi/avc_syslog_02.in'
749 --- libraries/libapparmor/testsuite/test_multi/avc_syslog_02.in 1970-01-01 00:00:00 +0000
750 +++ libraries/libapparmor/testsuite/test_multi/avc_syslog_02.in 2010-08-03 17:27:13 +0000
751 @@ -0,0 +1,1 @@
752 +Jul 24 12:24:41 spriggan kernel: [42364.269117] type=1400 audit(1279967081.455:42): apparmor="STATUS" operation="profile_replace" name="/sbin/dhclient3" pid=19610 comm="apparmor_parser"
753
754 === added file 'libraries/libapparmor/testsuite/test_multi/avc_syslog_02.out'
755 --- libraries/libapparmor/testsuite/test_multi/avc_syslog_02.out        1970-01-01 00:00:00 +0000
756 +++ libraries/libapparmor/testsuite/test_multi/avc_syslog_02.out        2010-08-03 17:27:13 +0000
757 @@ -0,0 +1,10 @@
758 +START
759 +File: test_multi/avc_syslog_02.in
760 +Event type: AA_RECORD_STATUS
761 +Audit ID: 1279967081.455:42
762 +Operation: profile_replace
763 +Name: /sbin/dhclient3
764 +Command: apparmor_parser
765 +PID: 19610
766 +Epoch: 1279967081
767 +Audit subid: 42
768
769 === added file 'libraries/libapparmor/testsuite/test_multi/avc_syslog_03.in'
770 --- libraries/libapparmor/testsuite/test_multi/avc_syslog_03.in 1970-01-01 00:00:00 +0000
771 +++ libraries/libapparmor/testsuite/test_multi/avc_syslog_03.in 2010-08-03 17:27:13 +0000
772 @@ -0,0 +1,1 @@
773 +Jul 24 12:54:06 spriggan kernel: [44128.842691] type=1400 audit(1279968846.035:77): apparmor="ALLOWED" operation="open" parent=7014 profile="/tmp/cat" name="/etc/passwd" pid=21645 comm="cat" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
774
775 === added file 'libraries/libapparmor/testsuite/test_multi/avc_syslog_03.out'
776 --- libraries/libapparmor/testsuite/test_multi/avc_syslog_03.out        1970-01-01 00:00:00 +0000
777 +++ libraries/libapparmor/testsuite/test_multi/avc_syslog_03.out        2010-08-03 17:27:13 +0000
778 @@ -0,0 +1,16 @@
779 +START
780 +File: test_multi/avc_syslog_03.in
781 +Event type: AA_RECORD_ALLOWED
782 +Audit ID: 1279968846.035:77
783 +Operation: open
784 +Mask: r
785 +Denied Mask: r
786 +fsuid: 1000
787 +ouid: 0
788 +Profile: /tmp/cat
789 +Name: /etc/passwd
790 +Command: cat
791 +Parent: 7014
792 +PID: 21645
793 +Epoch: 1279968846
794 +Audit subid: 77
795
796 === modified file 'parser/COPYING.GPL'
797 --- parser/COPYING.GPL  2006-04-11 21:52:54 +0000
798 +++ parser/COPYING.GPL  2010-08-03 17:27:13 +0000
799 @@ -1,6 +1,5 @@
800  This license applies to all source files within the SubDomain parser
801 -package, with the exception of md5.c and the files in the pcre/
802 -subdirectory, as they are covered under their own respective licenses.
803 +package.
804  
805                     GNU GENERAL PUBLIC LICENSE
806                        Version 2, June 1991
807
808 === modified file 'parser/Makefile'
809 --- parser/Makefile     2009-11-11 18:58:57 +0000
810 +++ parser/Makefile     2010-08-03 17:27:13 +0000
811 @@ -82,9 +82,6 @@
812  AAREDIR= libapparmor_re
813  AAREOBJECTS = ${AAREDIR}/libapparmor_re.a
814  
815 -PCREDIR= pcre
816 -PCREOBJECTS = ${PCREDIR}/pcre.o
817 -
818  LEX_C_FILES    = parser_lex.c
819  YACC_C_FILES   = parser_yacc.c parser_yacc.h
820  
821 @@ -94,7 +91,7 @@
822  
823  TEST_OBJECTS = $(filter-out parser_lex.o, \
824                $(filter-out parser_yacc.o, \
825 -              $(filter-out parser_main.o, ${OBJECTS} ${PCREOBJECTS})))
826 +              $(filter-out parser_main.o, ${OBJECTS})))
827  
828  ifdef V
829    VERBOSE = 1
830 @@ -125,14 +122,25 @@
831  techdoc.txt: techdoc/index.html
832         w3m -dump $< > $@
833  
834 -all:   $(TOOLS) $(MANPAGES) ${HTMLMANPAGES} techdoc.pdf
835 +# targets arranged this way so that people who don't want full docs can
836 +# pick specific targets they want.
837 +main:  $(TOOLS)
838         $(Q)make -C po all
839 -       $(Q)make -s tests
840 -
841 -apparmor_parser: $(OBJECTS) $(PCREOBJECTS) $(AAREOBJECTS)
842 +
843 +manpages:      $(MANPAGES)
844 +
845 +htmlmanpages:  $(HTMLMANPAGES)
846 +
847 +pdf:   techdoc.pdf
848 +
849 +docs:  manpages htmlmanpages pdf
850 +
851 +all:   main docs tests
852 +
853 +apparmor_parser: $(OBJECTS) $(AAREOBJECTS)
854         rm -f ./libstdc++.a
855         ln -s `g++ -print-file-name=libstdc++.a`
856 -       g++ $(EXTRA_CFLAGS) -o $@ $(OBJECTS) $(PCREOBJECTS) $(LIBS) \
857 +       g++ $(EXTRA_CFLAGS) -o $@ $(OBJECTS) $(LIBS) \
858               ${LEXLIB}  $(AAREOBJECTS) -static-libgcc -L.
859  
860  parser_yacc.c parser_yacc.h: parser_yacc.y parser.h
861 @@ -191,7 +199,7 @@
862  af_names.h: /usr/include/bits/socket.h
863         LC_ALL=C sed -n -e '/$(__FILTER)/d' -e "s/^\#define[ \\t]\\+PF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/#ifndef AF_\\1\\n#  define AF_\\1 \\2\\n#endif\\nAA_GEN_NET_ENT(\"\\L\\1\", \\UAF_\\1)\\n/p" $< > $@
864         LC_ALL=C sed -n -e "s/^\#define[ \\t]\\+PF_MAX[ \\t]\\+\\([0-9]\\+\\)[ \\t]\\+.*/#define AA_AF_MAX \\1\n/p" $< >> $@
865 -       cat $@
866 +       # cat $@
867  
868  cap_names.h: /usr/include/linux/capability.h
869         LC_ALL=C sed -n -e "/CAP_EMPTY_SET/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9xa-f]\\+\\)\\(.*\\)\$$/\{\"\\L\\1\", \\UCAP_\\1\},/p" $< > $@
870 @@ -205,8 +213,8 @@
871  tst_misc: parser_misc.c parser.h parser_yacc.h af_names.h cap_names.h
872         $(Q)$(CC) -DUNIT_TEST $(EXTRA_CFLAGS) $(TEST_FLAGS) -o $@ $< $(BUILD_OUTPUT)
873  
874 -tst_regex: parser_regex.c parser.h parser_yacc.h $(PCREOBJECTS)
875 -       $(Q)$(CC) -DUNIT_TEST $(EXTRA_CFLAGS) $(TEST_FLAGS) -o $@ $< $(PCREOBJECTS) $(BUILD_OUTPUT)
876 +tst_regex: parser_regex.c parser.h parser_yacc.h
877 +       $(Q)$(CC) -DUNIT_TEST $(EXTRA_CFLAGS) $(TEST_FLAGS) -o $@ $< $(BUILD_OUTPUT)
878  
879  .SILENT: check
880  .PHONY: check
881 @@ -214,7 +222,7 @@
882  
883  .SILENT: tests
884  tests: ${TESTS}
885 -       for test in ${TESTS} ; do echo "*** running $${test}" && ./$${test} $(BUILD_OUTPUT) ; done
886 +       sh -e -c 'for test in ${TESTS} ; do echo "*** running $${test}" && ./$${test} $(BUILD_OUTPUT) ; done'
887         $(Q)make -s -C tst tests
888  
889  .SILENT: check
890 @@ -226,11 +234,6 @@
891  $(AAREOBJECTS):
892         make -C $(AAREDIR)
893  
894 -.SILENT: $(PCREOBJECTS)
895 -.PHONY: $(PCREOBJECTS)
896 -$(PCREOBJECTS):
897 -       make -C $(PCREDIR) "CFLAGS=$(EXTRA_CFLAGS)"
898 -
899  .PHONY: install-rhel4
900  install-rhel4: install-redhat
901  
902 @@ -293,7 +296,6 @@
903         rm -f af_names.h
904         rm -f cap_names.h
905         -rm -rf techdoc.{aux,log,pdf,toc,txt} techdoc/
906 -       make -s -C $(PCREDIR) clean
907         make -s -C $(AAREDIR) clean
908         make -s -C po clean
909  
910
911 === modified file 'parser/README'
912 --- parser/README       2007-04-25 20:50:21 +0000
913 +++ parser/README       2010-08-03 17:27:13 +0000
914 @@ -11,11 +11,6 @@
915  where we will attempt to conform to the RFP vulnerability disclosure
916  protocol: http://www.wiretrip.net/rfp/policy.html
917  
918 -The parser uses the PCRE (Perl Compatible Regular Expression) engine,
919 -which was written by Philip Hazel and is copyright by the University
920 -of Cambridge, England. For more information on the PCRE engine, see
921 -<ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/>
922 -
923  Thanks.
924  
925  -- The AppArmor development team
926
927 === modified file 'parser/apparmor_parser.pod'
928 --- parser/apparmor_parser.pod  2010-01-07 18:03:49 +0000
929 +++ parser/apparmor_parser.pod  2010-08-03 17:27:13 +0000
930 @@ -80,6 +80,10 @@
931  
932  Writes a binary (cached) profile to stdout (implies -K and -T).
933  
934 +=item -o file, --ofile file
935 +
936 +Writes a binary (cached) profile to the specified file (implies -K and -T)
937 +
938  =item -b n, --base n
939  
940  Set the base directory for resolving #include directives
941 @@ -149,11 +153,43 @@
942  
943  Print the version number and exit.
944  
945 +=item -p, --preprocess
946 +
947 +Dump the input profile to stdout out applying preprocessing flattening
948 +includes into the output profile.
949 +
950  =item -d, --debug
951  
952  Given once, only checks the profiles to ensure syntactic correctness.
953  Given twice, dumps its interpretation of the profile for checking.
954  
955 +=item -D n, --dump=n
956 +
957 +Debug flag for dumping various structures and passes of policy compilation.
958 +A single dump flag can be specified per --dump option, but the dump flag
959 +can be passed multiple times.  Note progress flags tend to also imply
960 +the matching stats flag.
961 +
962 +  apparmor_parser --dump=dfa-stats --dump=trans-stats <file>
963 +
964 +Use --help=dump to see a full list of which dump flags are supported
965 +
966 +=item -O n, --optimize=n
967 +
968 +Set the optimization flags used by policy compilation.  A sinlge optimization
969 +flag can be toggled per -O option, but the optimize flag can be passed
970 +multiple times.  Turning off some phases of the optimization can make
971 +it so that policy can't complete compilation due to size constraints
972 +(it is entirely possible to create a dfa with millions of states that will
973 +take days or longer to compile).
974 +
975 +Note: The parser is set to use a balanced default set of flags, that
976 +will result in resonable compression but not take excessive amounts
977 +of time to complete.
978 +
979 +Use --help=optimize to see a full list of which optimization flags are
980 +supported.
981 +
982  =item -h, --help
983  
984  Give a quick reference guide.
985
986 === modified file 'parser/libapparmor_re/apparmor_re.h'
987 --- parser/libapparmor_re/apparmor_re.h 2010-01-28 01:20:13 +0000
988 +++ parser/libapparmor_re/apparmor_re.h 2010-08-03 17:27:13 +0000
989 @@ -35,6 +35,7 @@
990    DFA_DUMP_EQUIV_STATS =       1 << 19,
991    DFA_DUMP_MINIMIZE =          1 << 20,
992    DFA_DUMP_UNREACHABLE =       1 << 22,
993 +  DFA_DUMP_RULE_EXPR =         1 << 23,
994  } dfaflags_t;
995  
996  #ifdef __cplusplus
997 @@ -48,9 +49,9 @@
998  aare_ruleset_t *aare_new_ruleset(int reverse);
999  void aare_delete_ruleset(aare_ruleset_t *rules);
1000  int aare_add_rule(aare_ruleset_t *rules, char *rule, int deny,
1001 -                 uint32_t perms, uint32_t audit);
1002 +                 uint32_t perms, uint32_t audit, dfaflags_t flags);
1003  int aare_add_rule_vec(aare_ruleset_t *rules, int deny, uint32_t perms,
1004 -                     uint32_t audit, int count, char **rulev);
1005 +                     uint32_t audit, int count, char **rulev, dfaflags_t flags);
1006  void *aare_create_dfa(aare_ruleset_t *rules, size_t *size, dfaflags_t flags);
1007  void aare_reset_matchflags(void);
1008  
1009
1010 === modified file 'parser/libapparmor_re/regexp.y'
1011 --- parser/libapparmor_re/regexp.y      2010-02-01 07:21:00 +0000
1012 +++ parser/libapparmor_re/regexp.y      2010-08-03 17:27:13 +0000
1013 @@ -102,6 +102,7 @@
1014         /* child 0 is left, child 1 is right */
1015         Node *child[2];
1016  
1017 +       unsigned int label;     /* unique number for debug etc */
1018         /**
1019          * We need reference counting for AcceptNodes: sharing AcceptNodes
1020          * avoids introducing duplicate States with identical accept values.
1021 @@ -1208,12 +1209,11 @@
1022   * Assign a consecutive number to each node. This is only needed for
1023   * pretty-printing the debug output.
1024   */
1025 -map<Node *, int> node_label;
1026  void label_nodes(Node *root)
1027  {
1028      int nodes = 0;
1029      for (depth_first_traversal i(root); i; i++)
1030 -       node_label.insert(make_pair(*i, nodes++));
1031 +       i->label = nodes++;
1032  }
1033  
1034  /**
1035 @@ -1225,7 +1225,7 @@
1036      if (!state.empty()) {
1037         State::iterator i = state.begin();
1038         for(;;) {
1039 -           os << node_label[*i];
1040 +          os << (*i)->label;
1041             if (++i == state.end())
1042                 break;
1043             os << ',';
1044 @@ -1240,15 +1240,15 @@
1045   */
1046  void dump_syntax_tree(ostream& os, Node *node) {
1047      for (depth_first_traversal i(node); i; i++) {
1048 -       os << node_label[*i] << '\t';
1049 +       os << i->label << '\t';
1050         if ((*i)->child[0] == 0)
1051             os << **i << '\t' << (*i)->followpos << endl;
1052         else {
1053             if ((*i)->child[1] == 0)
1054 -               os << node_label[(*i)->child[0]] << **i;
1055 +               os << (*i)->child[0]->label << **i;
1056             else
1057 -               os << node_label[(*i)->child[0]] << **i
1058 -                  << node_label[(*i)->child[1]];
1059 +               os << (*i)->child[0]->label << **i
1060 +                  << (*i)->child[1]->label;
1061             os << '\t' << (*i)->firstpos
1062                        << (*i)->lastpos << endl;
1063         }
1064 @@ -1256,22 +1256,17 @@
1065      os << endl;
1066  }
1067  
1068 -/* Comparison operator for sets of <State *>. */
1069 -template<class T>
1070 -class deref_less_than {
1071 -public:
1072 -    deref_less_than() { }
1073 -    bool operator()(T a, T b)
1074 -    {
1075 -       return *a < *b;
1076 -    }
1077 +/* Comparison operator for sets of <State *>.
1078 + * Do compare pointer comparisom on set of <Node *>, the pointer comparison
1079 + * allows us to determine which Sets of <Node *> we have seen already from
1080 + * new ones when constructing the DFA.
1081 + */
1082 +struct deref_less_than {
1083 +  bool operator()(State * const & lhs, State * const & rhs) const
1084 +  { return *lhs < *rhs; }
1085  };
1086  
1087 -/**
1088 - * States in the DFA. The pointer comparison allows us to tell sets we
1089 - * have seen already from new ones when constructing the DFA.
1090 - */
1091 -typedef set<State *, deref_less_than<State *> > States;
1092 +typedef set<State *, deref_less_than > States;
1093  typedef list<State *> Partition;
1094  /* Transitions in the DFA. */
1095  typedef map<State *, Cases> Trans;
1096 @@ -1370,6 +1365,13 @@
1097                 here.cases.insert(*j);
1098         }
1099      }
1100 +
1101 +    for (depth_first_traversal i(root); i; i++) {
1102 +           (*i)->firstpos.clear();
1103 +           (*i)->lastpos.clear();
1104 +           (*i)->followpos.clear();
1105 +    }
1106 +
1107      if (flags & (DFA_DUMP_STATS))
1108             fprintf(stderr, "\033[2KCreated dfa: states %ld\tmatching %d\tnonmatching %d\n", states.size(), match_count, nomatch_count);
1109  
1110 @@ -1715,7 +1717,9 @@
1111                         Trans::iterator j = trans.find(*i);
1112                         if (j != trans.end())
1113                                 trans.erase(j);
1114 +                       State *s = *i;
1115                         states.erase(*i);
1116 +                       delete(s);
1117                 }
1118         }
1119  
1120 @@ -2097,24 +2101,11 @@
1121                 /* if it overflows the next_check array it fits in as we will
1122                  * resize */
1123                 if (c >= next_check.size())
1124 -                       goto resize;
1125 +                       return true;
1126                 if (next_check[c].second)
1127                         return false;
1128         }
1129 -       return true;
1130  
1131 -resize:
1132 -       next_check.resize(base + cases.cases.rbegin()->first + 1);
1133 -       size_t prev = pos;
1134 -       size_t x = pos;
1135 -       /* find last free list entry */
1136 -       while (x) {
1137 -               prev = x;
1138 -               x = free_list[x].second;
1139 -       }
1140 -       x = free_list. size();
1141 -       free_list.resize(base + cases.cases.rbegin()->first + 1);
1142 -       init_free_list(free_list, prev, x);
1143         return true;
1144  }
1145  
1146 @@ -2126,6 +2117,7 @@
1147  {
1148         State *default_state = dfa.nonmatching;
1149         size_t base = 0;
1150 +       int resize;
1151  
1152         Trans::iterator i = dfa.trans.find(from);
1153         if (i == dfa.trans.end()) {
1154 @@ -2142,6 +2134,7 @@
1155                 goto do_insert;
1156  
1157  repeat:
1158 +       resize = 0;
1159         /* get the first free entry that won't underflow */
1160         while (x && (x < c)) {
1161                 prev = x;
1162 @@ -2154,15 +2147,24 @@
1163                 x = free_list[x].second;
1164         }
1165         if (!x) {
1166 +               resize = 256 - cases.begin()->first;
1167 +               x = free_list.size();
1168 +               /* set prev to last free */
1169 +       } else if (x + 255 - cases.begin()->first >= next_check.size()) {
1170 +               resize = (255 - cases.begin()->first - (next_check.size() - 1 - x));
1171 +               for (size_t y = x; y; y = free_list[y].second)
1172 +                       prev = y;
1173 +       }
1174 +       if (resize) {
1175                 /* expand next_check and free_list */
1176 -               x = free_list.size();
1177 -               size_t range = cases.cases.rbegin()->first - cases.begin()->first + 1;
1178 -               next_check.resize(next_check.size() + range);
1179 -               free_list.resize(free_list.size() + range);
1180 -               init_free_list(free_list, prev, x);
1181 +               size_t old_size = free_list.size();
1182 +               next_check.resize(next_check.size() + resize);
1183 +               free_list.resize(free_list.size() + resize);
1184 +               init_free_list(free_list, prev, old_size);
1185                 if (!first_free)
1186 -                       first_free = x;
1187 -               goto repeat;
1188 +                       first_free = old_size;;
1189 +               if (x == old_size)
1190 +                       goto repeat;
1191         }
1192  
1193         base = x - c;
1194 @@ -2194,8 +2196,9 @@
1195         st.insert(make_pair(i->second, i->first));
1196      }
1197  
1198 -    os << "(accept, default, base):" << endl;
1199 +    os << "size=" << default_base.size() << " (accept, default, base):  {state} -> {default state}" << endl;
1200      for (size_t i = 0; i < default_base.size(); i++) {
1201 +        os << i << ": ";
1202         os << "(" << accept[i] << ", "
1203            << num[default_base[i].first] << ", "
1204            << default_base[i].second << ")";
1205 @@ -2206,7 +2209,7 @@
1206         os << endl;
1207      }
1208  
1209 -    os << "(next, check):" << endl;
1210 +    os << "size=" << next_check.size() << " (next, check): {check state} -> {next state} : offset from base" << endl;
1211      for (size_t i = 0; i < next_check.size(); i++) {
1212         if (!next_check[i].second)
1213             continue;
1214 @@ -2565,9 +2568,9 @@
1215  }
1216  
1217  extern "C" int aare_add_rule(aare_ruleset_t *rules, char *rule, int deny,
1218 -                            uint32_t perms, uint32_t audit)
1219 +                            uint32_t perms, uint32_t audit,  dfaflags_t flags)
1220  {
1221 -       return aare_add_rule_vec(rules, deny, perms, audit, 1, &rule);
1222 +       return aare_add_rule_vec(rules, deny, perms, audit, 1, &rule, flags);
1223  }
1224  
1225  #define FLAGS_WIDTH 2
1226 @@ -2598,7 +2601,8 @@
1227  
1228  extern "C" int aare_add_rule_vec(aare_ruleset_t *rules, int deny,
1229                                  uint32_t perms, uint32_t audit,
1230 -                                int count, char **rulev)
1231 +                                int count, char **rulev,
1232 +                                dfaflags_t flags)
1233  {
1234      Node *tree = NULL, *accept;
1235      int exact_match;
1236 @@ -2715,6 +2719,18 @@
1237         }
1238      }
1239  
1240 +    if (flags & DFA_DUMP_RULE_EXPR) {
1241 +           cerr << "rule: ";
1242 +           cerr << rulev[0];
1243 +           for (int i = 1; i < count; i++) {
1244 +                   cerr << "\\x00";
1245 +                   cerr << rulev[i];
1246 +           }
1247 +           cerr << "  ->  ";
1248 +           tree->dump(cerr);
1249 +           cerr << "\n\n";
1250 +    }
1251 +
1252      if (rules->root)
1253         rules->root = new AltNode(rules->root, new CatNode(tree, accept));
1254      else
1255
1256 === modified file 'parser/parser.h'
1257 --- parser/parser.h     2010-02-17 20:21:52 +0000
1258 +++ parser/parser.h     2010-08-03 17:27:13 +0000
1259 @@ -4,6 +4,9 @@
1260   *   Copyright (c) 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007
1261   *   NOVELL (All rights reserved)
1262   *
1263 + *   Copyright (c) 2010
1264 + *   Canonical, Ltd. (All rights reserved)
1265 + *
1266   *   This program is free software; you can redistribute it and/or
1267   *   modify it under the terms of version 2 of the GNU General Public
1268   *   License published by the Free Software Foundation.
1269 @@ -14,12 +17,12 @@
1270   *   GNU General Public License for more details.
1271   *
1272   *   You should have received a copy of the GNU General Public License
1273 - *   along with this program; if not, contact Novell, Inc.
1274 + *   along with this program; if not, contact Novell, Inc. or Canonical
1275 + *   Ltd.
1276   */
1277  
1278  #include <netinet/in.h>
1279  #include <sys/resource.h>
1280 -#include "pcre/internal.h"
1281  #include "immunix.h"
1282  #include "libapparmor_re/apparmor_re.h"
1283  
1284 @@ -40,7 +43,6 @@
1285  
1286  struct cod_pattern {
1287         char *regex;            // posix regex
1288 -       pcre *compiled;         // compiled regex, size is compiled->size
1289  };
1290  
1291  struct cod_entry {
1292 @@ -168,17 +170,20 @@
1293  #define OPTION_REMOVE   2
1294  #define OPTION_REPLACE  3
1295  #define OPTION_STDOUT  4
1296 +#define OPTION_OFILE   5
1297  
1298  #define AARE_NONE 0
1299 -#define AARE_PCRE 1
1300  #define AARE_DFA 2
1301  
1302 +#define BOOL int
1303 +
1304  #define FLAG_CHANGEHAT_1_4  2
1305  #define FLAG_CHANGEHAT_1_5  3
1306  extern int flag_changehat_version;
1307  extern int read_implies_exec;
1308  extern dfaflags_t dfaflags;
1309 -
1310 +extern int preprocess_only;
1311 +extern FILE *ofile;
1312  
1313  #define PATH_CHROOT_REL 0x1
1314  #define PATH_NS_REL 0x2
1315 @@ -280,12 +285,16 @@
1316  extern void free_cod_entries(struct cod_entry *list);
1317  
1318  /* parser_symtab.c */
1319 +struct set_value {;
1320 +       char *val;
1321 +       struct set_value *next;
1322 +};
1323  extern int add_boolean_var(const char *var, int boolean);
1324  extern int get_boolean_var(const char *var);
1325  extern int new_set_var(const char *var, const char *value);
1326  extern int add_set_value(const char *var, const char *value);
1327 -extern void *get_set_var(const char *var);
1328 -extern char *get_next_set_value(void **context);
1329 +extern struct set_value *get_set_var(const char *var);
1330 +extern char *get_next_set_value(struct set_value **context);
1331  extern void dump_symtab(void);
1332  extern void dump_expanded_symtab(void);
1333  void free_symtabs(void);
1334 @@ -312,7 +321,7 @@
1335  extern void add_hat_to_policy(struct codomain *policy, struct codomain *hat);
1336  extern void add_entry_to_policy(struct codomain *policy, struct cod_entry *entry);
1337  extern void post_process_nt_entries(struct codomain *cod);
1338 -extern int post_process_policy(void);
1339 +extern int post_process_policy(int debug_only);
1340  extern int process_hat_regex(struct codomain *cod);
1341  extern int process_hat_variables(struct codomain *cod);
1342  extern int post_merge_rules(void);
1343
1344 === modified file 'parser/parser_include.c'
1345 --- parser/parser_include.c     2009-07-24 12:18:12 +0000
1346 +++ parser/parser_include.c     2010-08-03 17:27:13 +0000
1347 @@ -1,8 +1,8 @@
1348 -/* $Id$ */
1349 -
1350  /*
1351   *   Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
1352   *   NOVELL (All rights reserved)
1353 + *   Copyright (c) 2010
1354 + *   Canonical, Ltd.
1355   *
1356   *   This program is free software; you can redistribute it and/or
1357   *   modify it under the terms of version 2 of the GNU General Public
1358 @@ -14,7 +14,7 @@
1359   *   GNU General Public License for more details.
1360   *
1361   *   You should have received a copy of the GNU General Public License
1362 - *   along with this program; if not, contact Novell, Inc.
1363 + *   along with this program; if not, contact Canonical, Ltd.
1364   */
1365  
1366  /* Handle subdomain includes, as a straight forward preprocessing phase.
1367 @@ -270,3 +270,63 @@
1368         *s = 0;
1369         return c;
1370  }
1371 +
1372 +struct include_stack_t {
1373 +       char *filename;
1374 +       int lineno;
1375 +       struct include_stack_t *next;
1376 +};
1377 +
1378 +struct include_stack_t *include_stack_head = NULL;
1379 +
1380 +static void start_include_position(char *filename)
1381 +{
1382 +       if (current_filename)
1383 +               free(current_filename);
1384 +       current_filename = strdup(filename ? filename : "stdin");
1385 +       current_lineno   = 1;
1386 +}
1387 +
1388 +void push_include_stack(char *filename)
1389 +{
1390 +       struct include_stack_t *include = NULL;
1391 +
1392 +       include = malloc(sizeof(*include));
1393 +       if (!include) {
1394 +               perror("malloc of included file stack tracker");
1395 +               /* failures in this area are non-fatal */
1396 +               return;
1397 +       }
1398 +
1399 +       include->filename  = strdup(current_filename);
1400 +       include->lineno    = current_lineno;
1401 +       include->next      = include_stack_head;
1402 +       include_stack_head = include;
1403 +
1404 +       start_include_position(filename);
1405 +}
1406 +
1407 +void pop_include_stack(void)
1408 +{
1409 +       struct include_stack_t *include = NULL;
1410 +
1411 +       if (!include_stack_head)
1412 +               return;
1413 +
1414 +       include = include_stack_head;
1415 +       include_stack_head = include->next;
1416 +
1417 +       if (current_filename)
1418 +               free(current_filename);
1419 +       current_filename = include->filename;
1420 +       current_lineno   = include->lineno;
1421 +       free(include);
1422 +}
1423 +
1424 +void reset_include_stack(char *filename)
1425 +{
1426 +       while (include_stack_head)
1427 +               pop_include_stack();
1428 +
1429 +       start_include_position(filename);
1430 +}
1431
1432 === modified file 'parser/parser_include.h'
1433 --- parser/parser_include.h     2009-07-24 07:35:39 +0000
1434 +++ parser/parser_include.h     2010-06-05 06:11:20 +0000
1435 @@ -1,8 +1,8 @@
1436 -/* $Id$ */
1437 -
1438  /*
1439   *   Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
1440   *   NOVELL (All rights reserved)
1441 + *   Copyright (c) 2010
1442 + *   Canonical, Ltd.
1443   *
1444   *   This program is free software; you can redistribute it and/or
1445   *   modify it under the terms of version 2 of the GNU General Public
1446 @@ -14,13 +14,15 @@
1447   *   GNU General Public License for more details.
1448   *
1449   *   You should have received a copy of the GNU General Public License
1450 - *   along with this program; if not, contact Novell, Inc.
1451 + *   along with this program; if not, contact Canonical, Ltd.
1452   */
1453  
1454  #ifndef PARSER_INCLUDE_H
1455  #define PARSER_INCLUDE_H
1456  
1457  extern int preprocess_only;
1458 +extern int current_lineno;
1459 +extern char *current_filename;
1460  
1461  extern int add_search_dir(char *dir);
1462  extern void init_base_dir(void);
1463 @@ -29,4 +31,8 @@
1464  extern int do_include_preprocessing(char *profilename);
1465  FILE *search_path(char *filename, char **fullpath);
1466  
1467 +extern void push_include_stack(char *filename);
1468 +extern void pop_include_stack(void);
1469 +extern void reset_include_stack(char *filename);
1470 +
1471  #endif
1472
1473 === modified file 'parser/parser_interface.c'
1474 --- parser/parser_interface.c   2010-03-09 09:38:12 +0000
1475 +++ parser/parser_interface.c   2010-08-03 17:27:13 +0000
1476 @@ -133,6 +133,9 @@
1477                         PERROR(_("%s: Unable to write to stdout\n"),
1478                                progname);
1479                         break;
1480 +               case OPTION_OFILE:
1481 +                       PERROR(_("%s: Unable to write to output file\n"),
1482 +                              progname);
1483                 default:
1484                         PERROR(_("%s: ASSERT: Invalid option: %d\n"),
1485                                progname, option);
1486 @@ -155,6 +158,7 @@
1487                                cod->name);
1488                         break;
1489                 case OPTION_STDOUT:
1490 +               case OPTION_OFILE:
1491                         break;
1492                 default:
1493                         PERROR(_("%s: ASSERT: Invalid option: %d\n"),
1494 @@ -451,57 +455,6 @@
1495         return 1;
1496  }
1497  
1498 -int sd_serialize_pattern(sd_serialize *p, pcre *pat)
1499 -{
1500 -       if (!sd_write_struct(p, "pcre"))
1501 -               return 0;
1502 -       if (!sd_write32(p, pat->size - sizeof(pcre)))
1503 -               return 0;
1504 -       if (!sd_write32(p, pat->magic_number))
1505 -               return 0;
1506 -       if (!sd_write32(p, pat->options))
1507 -               return 0;
1508 -       if (!sd_write16(p, pat->top_bracket))
1509 -               return 0;
1510 -       if (!sd_write16(p, pat->top_backref))
1511 -               return 0;
1512 -       if (!sd_write8(p, pat->first_char))
1513 -               return 0;
1514 -       if (!sd_write8(p, pat->req_char))
1515 -               return 0;
1516 -       if (!sd_write8(p, pat->code[0]))
1517 -               return 0;
1518 -       if (!sd_write_blob(p, &pat->code[1], pat->size - sizeof(pcre), NULL))
1519 -               return 0;
1520 -       if (!sd_write_structend(p))
1521 -               return 0;
1522 -
1523 -       return 1;
1524 -}
1525 -
1526 -int sd_serialize_file_entry(sd_serialize *p, struct cod_entry *file_entry)
1527 -{
1528 -       PDEBUG("Writing file entry. name '%s'\n", file_entry->name);
1529 -       if (!sd_write_struct(p, "fe"))
1530 -               return 0;
1531 -       if (!sd_write_string(p, file_entry->name, NULL))
1532 -               return 0;
1533 -       if (!sd_write32(p, file_entry->mode))
1534 -               return 0;
1535 -       if (!sd_write32(p, file_entry->pattern_type))
1536 -               return 0;
1537 -       if (file_entry->pattern_type == ePatternRegex) {
1538 -               if (!sd_write_string(p, file_entry->pat.regex, NULL))
1539 -                       return 0;
1540 -               if (!sd_serialize_pattern(p, file_entry->pat.compiled))
1541 -                       return 0;
1542 -       }
1543 -       if (!sd_write_structend(p))
1544 -               return 0;
1545 -
1546 -       return 1;
1547 -}
1548 -
1549  int sd_serialize_dfa(sd_serialize *p, void *dfa, size_t size)
1550  {
1551         if (dfa && !sd_write_aligned_blob(p, dfa, size, "aadfa"))
1552 @@ -594,18 +547,6 @@
1553         return count;
1554  }
1555  
1556 -int count_pcre_ents(struct cod_entry *list)
1557 -{
1558 -       struct cod_entry *entry;
1559 -       int count = 0;
1560 -       list_for_each(list, entry) {
1561 -               if (entry->pattern_type == ePatternRegex) {
1562 -                       count++;
1563 -               }
1564 -       }
1565 -       return count;
1566 -}
1567 -
1568  int sd_serialize_profile(sd_serialize *p, struct codomain *profile,
1569                          int flattened)
1570  {
1571 @@ -724,47 +665,8 @@
1572                 if (!sd_serialize_xtable(p, profile->exec_table))
1573                         return 0;
1574         } else {
1575 -               /* pcre globbing entries */
1576 -               if (count_pcre_ents(profile->entries)) {
1577 -                       if (!sd_write_list(p, "pgent"))
1578 -                               return 0;
1579 -                       list_for_each(profile->entries, entry) {
1580 -                               if (entry->pattern_type == ePatternRegex) {
1581 -                                       if (!sd_serialize_file_entry(p, entry))
1582 -                                               return 0;
1583 -                               }
1584 -                       }
1585 -                       if (!sd_write_listend(p))
1586 -                               return 0;
1587 -               }
1588 -
1589 -               /* simple globbing entries */
1590 -               if (count_tailglob_ents(profile->entries)) {
1591 -                       if (!sd_write_list(p, "sgent"))
1592 -                               return 0;
1593 -                       list_for_each(profile->entries, entry) {
1594 -                               if (entry->pattern_type == ePatternTailGlob) {
1595 -                                       if (!sd_serialize_file_entry(p, entry))
1596 -                                               return 0;
1597 -                               }
1598 -                       }
1599 -                       if (!sd_write_listend(p))
1600 -                               return 0;
1601 -               }
1602 -
1603 -               /* basic file entries */
1604 -               if (count_file_ents(profile->entries)) {
1605 -                       if (!sd_write_list(p, "fent"))
1606 -                               return 0;
1607 -                       list_for_each(profile->entries, entry) {
1608 -                               if (entry->pattern_type == ePatternBasic) {
1609 -                                       if (!sd_serialize_file_entry(p, entry))
1610 -                                               return 0;
1611 -                               }
1612 -                       }
1613 -                       if (!sd_write_listend(p))
1614 -                               return 0;
1615 -               }
1616 +               PERROR(_("Unknown pattern type\n"));
1617 +               return 1;
1618         }
1619  
1620         if (profile->hat_table && regex_type != AARE_DFA) {
1621 @@ -812,7 +714,7 @@
1622  int cache_fd = -1;
1623  int sd_serialize_codomain(int option, struct codomain *cod)
1624  {
1625 -       int fd;
1626 +       int fd = -1;
1627         int error = -ENOMEM, size, wsize;
1628         sd_serialize *work_area;
1629         char *filename = NULL;
1630 @@ -837,22 +739,29 @@
1631                 filename = "stdout";
1632                 fd = dup(1);
1633                 break;
1634 +       case OPTION_OFILE:
1635 +               fd = dup(fileno(ofile));
1636 +               break;
1637         default:
1638                 error = -EINVAL;
1639                 goto exit;
1640                 break;
1641         }
1642  
1643 -       if (kernel_load && fd < 0) {
1644 -               PERROR(_("Unable to open %s - %s\n"), filename,
1645 -                      strerror(errno));
1646 +       if (fd < 0) {
1647 +               if (kernel_load)
1648 +                       PERROR(_("Unable to open %s - %s\n"), filename,
1649 +                              strerror(errno));
1650 +               else
1651 +                       PERROR(_("Unable to open output file - %s\n"),
1652 +                              strerror(errno));
1653                 error = -errno;
1654                 goto exit;
1655         }
1656  
1657         error = 0;
1658  
1659 -       if (option != OPTION_STDOUT)
1660 +       if (option != OPTION_STDOUT && option != OPTION_OFILE)
1661                 free(filename);
1662  
1663         if (option == OPTION_REMOVE) {
1664 @@ -918,7 +827,7 @@
1665                 }
1666  
1667                 size = work_area->pos - work_area->buffer;
1668 -               if (kernel_load || option == OPTION_STDOUT) {
1669 +               if (kernel_load || option == OPTION_STDOUT || option == OPTION_OFILE) {
1670                         wsize = write(fd, work_area->buffer, size);
1671                         if (wsize < 0) {
1672                                 error = -errno;
1673 @@ -941,7 +850,7 @@
1674                 free_sd_serial(work_area);
1675         }
1676  
1677 -       if (kernel_load) close(fd);
1678 +       close(fd);
1679  
1680         if (cod->hat_table && regex_type == AARE_DFA && option != OPTION_REMOVE) {
1681                 if (load_flattened_hats(cod) != 0)
1682 @@ -973,7 +882,7 @@
1683  
1684  int sd_load_buffer(int option, char *buffer, int size)
1685  {
1686 -       int fd;
1687 +       int fd = -1;
1688         int error = -ENOMEM, wsize, bsize;
1689         char *filename = NULL;
1690         char *b;
1691
1692 === modified file 'parser/parser_lex.l'
1693 --- parser/parser_lex.l 2010-03-09 05:49:16 +0000
1694 +++ parser/parser_lex.l 2010-08-03 17:27:13 +0000
1695 @@ -1,8 +1,8 @@
1696 -/* $Id$ */
1697 -
1698  /*
1699   *   Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
1700   *   NOVELL (All rights reserved)
1701 + *   Copyright (c) 2010
1702 + *   Canonical, Ltd.
1703   *
1704   *   This program is free software; you can redistribute it and/or
1705   *   modify it under the terms of version 2 of the GNU General Public
1706 @@ -14,7 +14,7 @@
1707   *   GNU General Public License for more details.
1708   *
1709   *   You should have received a copy of the GNU General Public License
1710 - *   along with this program; if not, contact Novell, Inc.
1711 + *   along with this program; if not, contact Canonical, Ltd.
1712   */
1713  
1714  /* Definitions section */
1715 @@ -49,7 +49,12 @@
1716  #endif
1717  #define NPDEBUG(fmt, args...)  /* Do nothing */
1718  
1719 -int current_lineno = 1;
1720 +#define DUMP_PREPROCESS do { if (preprocess_only) ECHO; } while (0)
1721 +
1722 +#define YY_NO_INPUT
1723 +
1724 +int current_lineno     = 1;
1725 +char *current_filename = NULL;
1726  
1727  struct ignored_suffix_t {
1728         char * text;
1729 @@ -80,14 +85,19 @@
1730         char *fullpath = NULL;
1731  
1732         if (search) {
1733 +               if (preprocess_only)
1734 +                       fprintf(yyout, "\n\n##included <%s>\n", filename);
1735                 include_file = search_path(filename, &fullpath);
1736         } else {
1737 +               if (preprocess_only)
1738 +                       fprintf(yyout, "\n\n##included \"%s\"\n", filename);
1739                 fullpath = strdup(filename);
1740                 include_file = fopen(fullpath, "r");
1741         }
1742  
1743         if (!include_file)
1744 -               yyerror(_("Could not open '%s'"), fullpath);
1745 +               yyerror(_("Could not open '%s'"),
1746 +                        fullpath ? fullpath: filename);
1747  
1748          if (fstat(fileno(include_file), &my_stat))
1749                 yyerror(_("fstat failed for '%s'"), fullpath);
1750 @@ -95,6 +105,7 @@
1751          if (S_ISREG(my_stat.st_mode)) {
1752                 yyin = include_file;
1753                 PDEBUG("Opened include \"%s\"\n", fullpath);
1754 +               push_include_stack(fullpath);
1755                 yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
1756          }
1757  
1758 @@ -139,8 +150,9 @@
1759                                 yyerror(_("stat failed for '%s'"), dirent_path);
1760                         if (S_ISREG(my_stat.st_mode)) {
1761                                 if (!(yyin = fopen(dirent_path,"r")))
1762 -                                       yyerror(_("Could not open '%s'"), filename);
1763 -                               PDEBUG("Opened include \"%s\"\n", filename);
1764 +                                       yyerror(_("Could not open '%s' in '%s'"), dirent_path, filename);
1765 +                               PDEBUG("Opened include \"%s\" in \"%s\"\n", dirent_path, filename);
1766 +                               push_include_stack(dirent_path);
1767                                 yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
1768                         }
1769                 }
1770 @@ -227,6 +239,8 @@
1771  }
1772  
1773  <<EOF>> {
1774 +       fclose(yyin);
1775 +       pop_include_stack();
1776         yypop_buffer_state();
1777         if ( !YY_CURRENT_BUFFER ) yyterminate();
1778  }
1779 @@ -240,6 +254,7 @@
1780                            * a longer match). So now, when I want to
1781                            * match any random string, I go into a
1782                            * separate state. */
1783 +                       DUMP_PREPROCESS;
1784                         yylval.id =  processunquoted(yytext, yyleng);
1785                         PDEBUG("Found sub name: \"%s\"\n",  yylval.id);
1786                         BEGIN(INITIAL);
1787 @@ -253,6 +268,7 @@
1788                            * a longer match). So now, when I want to
1789                            * match any random string, I go into a
1790                            * separate state. */
1791 +                       DUMP_PREPROCESS;
1792                         yylval.id = processquoted(yytext, yyleng);
1793                         PDEBUG("Found sub name: \"%s\"\n", yylval.id);
1794                         BEGIN(INITIAL);
1795 @@ -260,6 +276,7 @@
1796                 }
1797  
1798         [^\n]   {
1799 +                       DUMP_PREPROCESS;
1800                         /* Something we didn't expect */
1801                         yyerror(_("Found unexpected character: '%s'"), yytext);
1802                 }
1803 @@ -274,6 +291,7 @@
1804                            * a longer match). So now, when I want to
1805                            * match any random string, I go into a
1806                            * separate state. */
1807 +                       DUMP_PREPROCESS;
1808                         yylval.id = processunquoted(yytext, yyleng);
1809                         PDEBUG("Found sub name: \"%s\"\n", yylval.id);
1810                         BEGIN(INITIAL);
1811 @@ -287,14 +305,16 @@
1812                            * a longer match). So now, when I want to
1813                            * match any random string, I go into a
1814                            * separate state. */
1815 +                       DUMP_PREPROCESS;
1816                         yylval.id  = processquoted(yytext, yyleng);
1817                         PDEBUG("Found sub name: \"%s\"\n", yylval.id);
1818                         BEGIN(INITIAL);
1819                         return TOK_ID;
1820                 }
1821  
1822 -       {WS}+                   {  /* Ignoring whitespace */ }
1823 +       {WS}+   { DUMP_PREPROCESS; /* Ignoring whitespace */ }
1824         [^\n]   {
1825 +                       DUMP_PREPROCESS;
1826                         /* Something we didn't expect */
1827                         yyerror(_("Found unexpected character: '%s'"), yytext);
1828                 }
1829 @@ -302,85 +322,99 @@
1830  
1831  <FLAGS_MODE>{
1832         {FLAGOPEN_PAREN}        {
1833 +                       DUMP_PREPROCESS;
1834                         PDEBUG("FLag (\n");
1835                         return TOK_FLAG_OPENPAREN;
1836                         }
1837         {FLAGCLOSE_PAREN}       {
1838 +                       DUMP_PREPROCESS;
1839                         PDEBUG("Flag )\n");
1840                         BEGIN(INITIAL);
1841                         return TOK_FLAG_CLOSEPAREN;
1842                         }
1843  
1844 -       {WS}+           { /* Eat whitespace */ }
1845 +       {WS}+           { DUMP_PREPROCESS; /* Eat whitespace */ }
1846  
1847         {FLAGSEP}       {
1848 +                       DUMP_PREPROCESS;
1849                         PDEBUG("Flag , \n");
1850                         return TOK_FLAG_SEP;
1851                         }
1852  
1853         {EQUALS}        {
1854 +                       DUMP_PREPROCESS;
1855                         PDEBUG("Flag = \n");
1856                         return TOK_EQUALS;
1857                         }
1858         {KEYWORD}       {
1859 +                       DUMP_PREPROCESS;
1860                         yylval.flag_id = strdup(yytext);
1861                         PDEBUG("Found flag: \"%s\"\n", yylval.flag_id);
1862                         return TOK_FLAG_ID;
1863                         }
1864  
1865         [^\n]           {
1866 +                       DUMP_PREPROCESS;
1867                         /* Something we didn't expect */
1868                         yyerror(_("Found unexpected character: '%s'"), yytext);
1869                         }
1870  }
1871  
1872  <ASSIGN_MODE>{
1873 -       {WS}+           { /* Eat whitespace */ }
1874 +       {WS}+           { DUMP_PREPROCESS; /* Eat whitespace */ }
1875  
1876         {ID}+           {
1877 +                       DUMP_PREPROCESS;
1878                         yylval.var_val = processunquoted(yytext, yyleng);
1879                         PDEBUG("Found assignment value: \"%s\"\n", yylval.var_val);
1880                         return TOK_VALUE;
1881                         }
1882  
1883         {QUOTED_ID}     {
1884 +                       DUMP_PREPROCESS;
1885                         yylval.var_val = processquoted(yytext, yyleng);
1886                         PDEBUG("Found assignment value: \"%s\"\n", yylval.var_val);
1887                         return TOK_VALUE;
1888                         }
1889  
1890 -       \\\n            { current_lineno++ ; }
1891 +       \\\n            { DUMP_PREPROCESS; current_lineno++ ; }
1892  
1893         \r?\n           {
1894 +                       DUMP_PREPROCESS;
1895                         current_lineno++;
1896                         BEGIN(INITIAL);
1897                         }
1898  }
1899  
1900  <NETWORK_MODE>{
1901 -       {WS}+           { /* Eat whitespace */ }
1902 +       {WS}+           { DUMP_PREPROCESS; /* Eat whitespace */ }
1903  
1904         {ID}+           {
1905 +                       DUMP_PREPROCESS;
1906                         yylval.id = strdup(yytext);
1907                         return TOK_ID;
1908                         }
1909         {END_OF_RULE}   {
1910 +                       DUMP_PREPROCESS;
1911                         BEGIN(INITIAL);
1912                         return TOK_END_OF_RULE;
1913                 }
1914         [^\n]           {
1915 +                       DUMP_PREPROCESS;
1916                           /* Something we didn't expect */
1917                         yylval.id = strdup(yytext);
1918                         yyerror(_("(network_mode) Found unexpected character: '%s'"), yylval.id);
1919                         }
1920  
1921         \r?\n           {
1922 +                       DUMP_PREPROCESS;
1923                         current_lineno++;
1924                         }
1925  }
1926  
1927  <CHANGE_PROFILE_MODE>{
1928         {ARROW}         {
1929 +                       DUMP_PREPROCESS;
1930                         PDEBUG("Matched a change profile arrow\n");
1931                         return TOK_ARROW;
1932                         }
1933 @@ -393,6 +427,7 @@
1934                            * a longer match). So now, when I want to
1935                            * match any random string, I go into a
1936                            * separate state. */
1937 +                       DUMP_PREPROCESS;
1938                         yylval.id = processunquoted(yytext, yyleng);
1939                         PDEBUG("Found change profile name: \"%s\"\n", yylval.id);
1940                         BEGIN(INITIAL);
1941 @@ -406,14 +441,16 @@
1942                            * a longer match). So now, when I want to
1943                            * match any random string, I go into a
1944                            * separate state. */
1945 +                       DUMP_PREPROCESS;
1946                         yylval.id = processquoted(yytext, yyleng);
1947                         PDEBUG("Found change profile quoted name: \"%s\"\n", yylval.id);
1948                         BEGIN(INITIAL);
1949                         return TOK_ID;
1950                 }
1951  
1952 -       {WS}+                   {  /* Ignoring whitespace */ }
1953 +       {WS}+                   {  DUMP_PREPROCESS; /* Ignoring whitespace */ }
1954         [^\n]   {
1955 +                       DUMP_PREPROCESS;
1956                         /* Something we didn't expect */
1957                         yyerror(_("Found unexpected character: '%s'"), yytext);
1958                 }
1959 @@ -421,127 +458,147 @@
1960  
1961  #include/.*\r?\n        { /* include */
1962                         PDEBUG("Matched #include\n");
1963 -                       current_lineno++;
1964                         BEGIN(INCLUDE);
1965                         }
1966  
1967  #.*\r?\n               { /* normal comment */
1968 +                       DUMP_PREPROCESS;
1969                         PDEBUG("comment(%d): %s\n", current_lineno, yytext);
1970                         current_lineno++;
1971                         BEGIN(INITIAL);
1972  }
1973  
1974 -{END_OF_RULE}          { return TOK_END_OF_RULE; }
1975 +{END_OF_RULE}          { DUMP_PREPROCESS; return TOK_END_OF_RULE; }
1976  
1977  {SEPARATOR}            {
1978 +                       DUMP_PREPROCESS;
1979                         PDEBUG("Matched a separator\n");
1980                         BEGIN(SUB_NAME);
1981                         return TOK_SEP;
1982                         }
1983  {ARROW}                        {
1984 +                       DUMP_PREPROCESS;
1985                         PDEBUG("Matched a arrow\n");
1986                         return TOK_ARROW;
1987                         }
1988  {EQUALS}               {
1989 +                       DUMP_PREPROCESS;
1990                         PDEBUG("Matched equals for assignment\n");
1991                         BEGIN(ASSIGN_MODE);
1992                         return TOK_EQUALS;
1993                         }
1994  {ADD_ASSIGN}           {
1995 +                       DUMP_PREPROCESS;
1996                         PDEBUG("Matched additive value assignment\n");
1997                         BEGIN(ASSIGN_MODE);
1998                         return TOK_ADD_ASSIGN;
1999                         }
2000  <RLIMIT_MODE>{
2001 -       {WS}+           { /* Eat whitespace */ }
2002 +       {WS}+           { DUMP_PREPROCESS; /* Eat whitespace */ }
2003  
2004  
2005         -?{NUMBER}[kKMG]?  {
2006 +                       DUMP_PREPROCESS;
2007                         yylval.var_val = strdup(yytext);
2008                         return TOK_VALUE;
2009                         }
2010  
2011         {KEYWORD}       {
2012 +                       DUMP_PREPROCESS;
2013                         yylval.id = strdup(yytext);
2014                         if (strcmp(yytext, "infinity") == 0)
2015                                 return TOK_VALUE;
2016                         return TOK_ID;
2017                         }
2018  
2019 -       {LT_EQUAL}      { return TOK_LE; }
2020 +       {LT_EQUAL}      { DUMP_PREPROCESS; return TOK_LE; }
2021  
2022         {END_OF_RULE}   {
2023 +                       DUMP_PREPROCESS;
2024                         BEGIN(INITIAL);
2025                         return TOK_END_OF_RULE;
2026                         }
2027  
2028         \\\n            {
2029 +                       DUMP_PREPROCESS;
2030                         current_lineno++;
2031                         BEGIN(INITIAL);
2032                         }
2033  
2034         \r?\n           {
2035 +                       DUMP_PREPROCESS;
2036                         current_lineno++;
2037                         BEGIN(INITIAL);
2038                         }
2039  }
2040  
2041  {SET_VARIABLE}         {
2042 +                       DUMP_PREPROCESS;
2043                         yylval.set_var = strdup(yytext);
2044                         PDEBUG("Found set variable %s\n", yylval.set_var);
2045                         return TOK_SET_VAR;
2046                         }
2047  
2048  {BOOL_VARIABLE}                {
2049 +                       DUMP_PREPROCESS;
2050                         yylval.bool_var = strdup(yytext);
2051                         PDEBUG("Found boolean variable %s\n", yylval.bool_var);
2052                         return TOK_BOOL_VAR;
2053                         }
2054  
2055  {OPEN_BRACE}           {
2056 +                       DUMP_PREPROCESS;
2057                         PDEBUG("Open Brace\n");
2058                         return TOK_OPEN;
2059                         }
2060  {CLOSE_BRACE}          {
2061 +                       DUMP_PREPROCESS;
2062                         PDEBUG("Close Brace\n");
2063                         return TOK_CLOSE;
2064                         }
2065  
2066  {PATHNAME}             {
2067 +                       DUMP_PREPROCESS;
2068                         yylval.id = processunquoted(yytext, yyleng);
2069                         PDEBUG("Found id: \"%s\"\n", yylval.id);
2070                         return TOK_ID;
2071                         }
2072  
2073  {QPATHNAME}            {
2074 +                       DUMP_PREPROCESS;
2075                         yylval.id = processquoted(yytext, yyleng);
2076                         PDEBUG("Found id: \"%s\"\n", yylval.id);
2077                         return TOK_ID;
2078                         }
2079  
2080  {MODES}                        {
2081 +                       DUMP_PREPROCESS;
2082                         yylval.mode = strdup(yytext);
2083                         PDEBUG("Found modes: %s\n", yylval.mode);
2084                         return TOK_MODE;
2085                         }
2086  
2087  {HAT}                  {
2088 +                       DUMP_PREPROCESS;
2089                         BEGIN(SUB_NAME2);
2090                         return TOK_HAT;
2091                         }
2092  
2093  {COLON}                        {
2094 +                       DUMP_PREPROCESS;
2095                         PDEBUG("Found a colon\n");
2096                         return TOK_COLON;
2097                         }
2098  
2099  {FLAGOPEN_PAREN}       {
2100 +                       DUMP_PREPROCESS;
2101                         PDEBUG("FLag (\n");
2102                         BEGIN(FLAGS_MODE);
2103                         return TOK_FLAG_OPENPAREN;
2104                         }
2105  
2106  {VARIABLE_NAME}                {
2107 +                       DUMP_PREPROCESS;
2108                         int token = get_keyword_token(yytext);
2109  
2110                         /* special cases */
2111 @@ -573,11 +630,13 @@
2112                         return token;
2113                         }
2114  
2115 -{WS}+                  {  /* Ignoring whitespace */ }
2116 +{WS}+                  {  DUMP_PREPROCESS; /* Ignoring whitespace */ }
2117  
2118 -\r?\n                  { current_lineno++ ; }
2119 +\r?\n                  { DUMP_PREPROCESS; current_lineno++ ; }
2120  
2121  [^\n]                  {
2122 +                       DUMP_PREPROCESS;
2123 +
2124                           /* Something we didn't expect */
2125                         yyerror(_("Found unexpected character: '%s'"), yytext);
2126                         }
2127
2128 === modified file 'parser/parser_main.c'
2129 --- parser/parser_main.c        2010-01-28 01:20:13 +0000
2130 +++ parser/parser_main.c        2010-08-03 17:27:13 +0000
2131 @@ -4,6 +4,9 @@
2132   *   Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
2133   *   NOVELL (All rights reserved)
2134   *
2135 + *   Copyright (c) 2010
2136 + *   Canonical, Ltd. (All rights reserved)
2137 + *
2138   *   This program is free software; you can redistribute it and/or
2139   *   modify it under the terms of version 2 of the GNU General Public
2140   *   License published by the Free Software Foundation.
2141 @@ -14,7 +17,8 @@
2142   *   GNU General Public License for more details.
2143   *
2144   *   You should have received a copy of the GNU General Public License
2145 - *   along with this program; if not, contact Novell, Inc.
2146 + *   along with this program; if not, contact Novell, Inc. or Canonical,
2147 + *   Ltd.
2148   */
2149  
2150  #include <stdio.h>
2151 @@ -26,6 +30,7 @@
2152  #include <fcntl.h>
2153  #include <mntent.h>
2154  #include <libintl.h>
2155 +#include <linux/limits.h>
2156  #include <locale.h>
2157  #define _(s) gettext(s)
2158  
2159 @@ -34,6 +39,8 @@
2160  
2161  #include <unistd.h>
2162  #include <sys/sysctl.h>
2163 +#include <sys/types.h>
2164 +#include <sys/stat.h>
2165  
2166  #include "parser.h"
2167  #include "parser_version.h"
2168 @@ -47,7 +54,6 @@
2169  #define MATCH_STRING "/sys/kernel/security/" MODULE_NAME "/matching"
2170  #define FLAGS_FILE "/sys/kernel/security/" MODULE_NAME "/features"
2171  #define MOUNTED_FS "/proc/mounts"
2172 -#define PCRE "pattern=pcre"
2173  #define AADFA "pattern=aadfa"
2174  
2175  #define PRIVILEGED_OPS (write_cache || kernel_load)
2176 @@ -76,6 +82,8 @@
2177  #else
2178  int read_implies_exec = 0;
2179  #endif
2180 +int preprocess_only = 0;
2181 +int skip_mode_force = 0;
2182  
2183  char *subdomainbase = NULL;
2184  char *match_string = NULL;
2185 @@ -84,8 +92,7 @@
2186  int perms_create = 0;          /* perms contain create flag */
2187  char *profile_namespace = NULL;
2188  int flag_changehat_version = FLAG_CHANGEHAT_1_5;
2189 -
2190 -extern int current_lineno;
2191 +FILE *ofile = NULL;
2192  
2193  /* per-profile settings */
2194  int force_complain = 0;
2195 @@ -106,6 +113,7 @@
2196         {"remove",              0, 0, 'R'},
2197         {"names",               0, 0, 'N'},
2198         {"stdout",              0, 0, 'S'},
2199 +       {"ofile",               1, 0, 'o'},
2200         {"match-string",        1, 0, 'm'},
2201         {"quiet",               0, 0, 'q'},
2202         {"skip-kernel-load",    0, 0, 'Q'},
2203 @@ -121,6 +129,7 @@
2204         {"Dump",                1, 0, 'D'},
2205         {"optimize",            1, 0, 'O'},
2206         {"Optimize",            1, 0, 'O'},
2207 +       {"preprocess",          0, 0, 'p'},
2208         {NULL, 0, 0, 0},
2209  };
2210  
2211 @@ -145,6 +154,7 @@
2212                "-B, --binary            Input is precompiled profile\n"
2213                "-N, --names             Dump names of profiles in input.\n"
2214                "-S, --stdout            Dump compiled profile to stdout\n"
2215 +              "-o n, --ofile n         Write output to file n\n"
2216                "-b n, --base n          Set base dir and cwd\n"
2217                "-I n, --Include n       Add n to the search path\n"
2218                "-f n, --subdomainfs n   Set location of apparmor filesystem\n"
2219 @@ -160,9 +170,10 @@
2220                "-Q, --skip-kernel-load  Do everything except loading into kernel\n"
2221                "-V, --version           Display version info and exit\n"
2222                "-d, --debug             Debug apparmor definitions\n"
2223 +              "-p, --preprocess        Dump preprocessed profile\n"
2224                "-D [n], --dump          Dump internal info for debugging\n"
2225                "-O [n], --Optimize      Control dfa optimizations\n"
2226 -              "-h [command], --help    Display this text or info about command\n"
2227 +              "-h [cmd], --help[=cmd]  Display this text or info about cmd\n"
2228                ,command);
2229  }
2230  
2231 @@ -175,6 +186,7 @@
2232                "no option specified     Dump variables\n"
2233                "variables               Dump variables\n"
2234                "expanded-variables      Dump expanded variables\n"
2235 +              "rule-exprs              Dump rule to expr tree conversions\n"
2236                "expr-stats              Dump stats on expr tree\n"
2237                "expr-tree               Dump expression tree\n"
2238                "expr-simple             Dump simplified expression tree\n"
2239 @@ -224,8 +236,10 @@
2240         if (conf_quiet || names_only || option == OPTION_REMOVE)
2241                 return;
2242  
2243 -       rc = asprintf(&newfmt, _("Warning (%s line %d): %s"),
2244 +       rc = asprintf(&newfmt, _("Warning from %s (%s%sline %d): %s"),
2245                       profilename ? profilename : "stdin",
2246 +                     current_filename ? current_filename : "",
2247 +                     current_filename ? " " : "",
2248                       current_lineno,
2249                       fmt);
2250         if (!newfmt)
2251 @@ -244,7 +258,7 @@
2252         int count = 0;
2253         option = OPTION_ADD;
2254  
2255 -       while ((c = getopt_long(argc, argv, "adf:h::rRVvI:b:BCD:NSm:qQn:XKTWkO:", long_options, &o)) != -1)
2256 +       while ((c = getopt_long(argc, argv, "adf:h::rRVvI:b:BCD:NSm:qQn:XKTWkO:po:", long_options, &o)) != -1)
2257         {
2258                 switch (c) {
2259                 case 0:
2260 @@ -258,7 +272,7 @@
2261                         break;
2262                 case 'd':
2263                         debug++;
2264 -                       skip_cache = 1;
2265 +                       skip_read_cache = 1;
2266                         break;
2267                 case 'h':
2268                         if (!optarg) {
2269 @@ -285,6 +299,7 @@
2270                 case 'R':
2271                         count++;
2272                         option = OPTION_REMOVE;
2273 +                       skip_cache = 1;
2274                         break;
2275                 case 'V':
2276                         display_version();
2277 @@ -297,10 +312,12 @@
2278                         set_base_dir(optarg);
2279                         break;
2280                 case 'B':
2281 -                       binary_input =1;
2282 +                       binary_input = 1;
2283 +                       skip_cache = 1;
2284                         break;
2285                 case 'C':
2286                         opt_force_complain = 1;
2287 +                       skip_cache = 1;
2288                         break;
2289                 case 'N':
2290                         names_only = 1;
2291 @@ -312,17 +329,31 @@
2292                         skip_read_cache = 1;
2293                         kernel_load = 0;
2294                         break;
2295 +               case 'o':
2296 +                       count++;
2297 +                       option = OPTION_OFILE;
2298 +                       skip_read_cache = 1;
2299 +                       kernel_load = 0;
2300 +                       ofile = fopen(optarg, "w");
2301 +                       if (!ofile) {
2302 +                               PERROR("%s: Could not open file %s\n",
2303 +                                      progname, optarg);
2304 +                               exit(1);
2305 +                       }
2306 +                       break;
2307                 case 'f':
2308                         subdomainbase = strndup(optarg, PATH_MAX);
2309                         break;
2310                 case 'D':
2311 -                       skip_cache = 1;
2312 +                       skip_read_cache = 1;
2313                         if (!optarg) {
2314                                 dump_vars = 1;
2315                         } else if (strcmp(optarg, "variables") == 0) {
2316                                 dump_vars = 1;
2317                         } else if (strcmp(optarg, "expanded-variables") == 0) {
2318                                 dump_expanded_vars = 1;
2319 +                       } else if (strcmp(optarg, "rule-exprs") == 0) {
2320 +                               dfaflags |= DFA_DUMP_RULE_EXPR;
2321                         } else if (strcmp(optarg, "expr-tree") == 0) {
2322                                 dfaflags |= DFA_DUMP_TREE;
2323                         } else if (strcmp(optarg, "expr-simple") == 0) {
2324 @@ -359,7 +390,7 @@
2325                         }
2326                         break;
2327                 case 'O':
2328 -                       skip_cache = 1;
2329 +                       skip_read_cache = 1;
2330                         if (strcmp(optarg, "0") == 0) {
2331                                 dfaflags |= DFA_CONTROL_NO_TREE_NORMAL |
2332                                         DFA_CONTROL_NO_TREE_SIMPLE |
2333 @@ -435,6 +466,13 @@
2334                 case 'Q':
2335                         kernel_load = 0;
2336                         break;
2337 +               case 'p':
2338 +                       count++;
2339 +                       kernel_load = 0;
2340 +                       skip_cache = 1;
2341 +                       preprocess_only = 1;
2342 +                       skip_mode_force = 1;
2343 +                       break;
2344                 default:
2345                         display_usage(progname);
2346                         exit(0);
2347 @@ -569,9 +607,6 @@
2348  
2349  out:
2350         if (match_string) {
2351 -               if (strstr(match_string, PCRE))
2352 -                       regex_type = AARE_PCRE;
2353 -
2354                 if (strstr(match_string, AADFA))
2355                         regex_type = AARE_DFA;
2356  
2357 @@ -620,20 +655,6 @@
2358         return;
2359  }
2360  
2361 -/* return 1 --> PCRE should work fine
2362 -   return 0 --> no PCRE support */
2363 -static int regex_support(void) {
2364 -       /* no match string, predates (or postdates?) the split matching
2365 -       module design */
2366 -       if (!match_string)
2367 -               return 1;
2368 -
2369 -       if (regex_type != AARE_NONE)
2370 -               return 1;
2371 -
2372 -       return 0;
2373 -}
2374 -
2375  int process_binary(int option, char *profilename)
2376  {
2377         char *buffer = NULL;
2378 @@ -695,12 +716,33 @@
2379         return retval;
2380  }
2381  
2382 -void reset_parser(void)
2383 +void reset_parser(char *filename)
2384  {
2385         free_aliases();
2386         free_symtabs();
2387         free_policies();
2388         reset_regex();
2389 +       reset_include_stack(filename);
2390 +}
2391 +
2392 +int test_for_dir_mode(const char *basename, const char *linkdir)
2393 +{
2394 +       int rc = 0;
2395 +
2396 +       if (!skip_mode_force) {
2397 +               char *target = NULL;
2398 +               if (asprintf(&target, "%s/%s/%s", basedir, linkdir, basename) < 0) {
2399 +                       perror("asprintf");
2400 +                       exit(1);
2401 +               }
2402 +
2403 +               if (access(target, R_OK) == 0)
2404 +                       rc = 1;
2405 +
2406 +               free(target);
2407 +       }
2408 +
2409 +       return rc;
2410  }
2411  
2412  int process_profile(int option, char *profilename)
2413 @@ -727,37 +769,22 @@
2414  
2415         if (profilename && option != OPTION_REMOVE) {
2416                 /* make decisions about disabled or complain-mode profiles */
2417 -               char *target = NULL;
2418                 char *basename = strrchr(profilename, '/');
2419                 if (basename)
2420                         basename++;
2421                 else
2422                         basename = profilename;
2423  
2424 -               if (asprintf(&target, "%s/%s/%s", basedir, "disable", basename) < 0) {
2425 -                       perror("asprintf");
2426 -                       exit(1);
2427 -               }
2428 -
2429 -               if (access(target, R_OK) == 0) {
2430 -                       if (!conf_quiet)
2431 -                               PERROR("Skipping profile in %s/disable: %s\n", basedir, basename);
2432 -                       free(target);
2433 +               if (test_for_dir_mode(basename, "disable")) {
2434 +                       if (!conf_quiet)
2435 +                               PERROR("Skipping profile in %s/disable: %s\n", basedir, basename);
2436                         goto out;
2437                 }
2438 -               free(target);
2439 -
2440 -               if (asprintf(&target, "%s/%s/%s", basedir, "force-complain", basename)<0) {
2441 -                       perror("asprintf");
2442 -                       exit(1);
2443 -               }
2444 -
2445 -               if (access(target, R_OK) == 0) {
2446 -                       if (!conf_quiet)
2447 -                               PERROR("Warning: found %s in %s/force-complain, forcing complain mode\n", basename, basedir);
2448 -                       force_complain = 1;
2449 -               }
2450 -               free(target);
2451 +
2452 +               if (test_for_dir_mode(basename, "force-complain")) {
2453 +                       PERROR("Warning: found %s in %s/force-complain, forcing complain mode\n", basename, basedir);
2454 +                       force_complain = 1;
2455 +               }
2456  
2457                 if (!force_complain && !skip_cache) {
2458                         fstat(fileno(yyin), &stat_text);
2459 @@ -796,12 +823,15 @@
2460  
2461         if (yyin)
2462                 yyrestart(yyin);
2463 -       reset_parser();
2464 +       reset_parser(profilename);
2465  
2466         retval = yyparse();
2467         if (retval != 0)
2468                 goto out;
2469  
2470 +       if (preprocess_only)
2471 +               goto out;
2472 +
2473         if (names_only) {
2474                 dump_policy_names();
2475                 goto out;
2476 @@ -812,7 +842,7 @@
2477                 goto out;
2478         }
2479  
2480 -       retval = post_process_policy();
2481 +       retval = post_process_policy(debug);
2482         if (retval != 0) {
2483                 PERROR(_("%s: Errors found in file. Aborting.\n"), progname);
2484                 goto out;
2485 @@ -829,10 +859,6 @@
2486                 goto out;
2487         }
2488  
2489 -       if (!regex_support()) {
2490 -               die_if_any_regex();
2491 -       }
2492 -
2493         retval = load_policy(option);
2494  
2495  out:
2496 @@ -969,5 +995,8 @@
2497                 profilename = NULL;
2498         }
2499  
2500 +       if (ofile)
2501 +               fclose(ofile);
2502 +
2503         return retval;
2504  }
2505
2506 === modified file 'parser/parser_misc.c'
2507 --- parser/parser_misc.c        2010-03-09 04:38:54 +0000
2508 +++ parser/parser_misc.c        2010-08-03 17:27:13 +0000
2509 @@ -19,6 +19,7 @@
2510  
2511  /* assistance routines */
2512  
2513 +#include <ctype.h>
2514  #include <stdio.h>
2515  #include <stdlib.h>
2516  #include <stdarg.h>
2517 @@ -27,6 +28,7 @@
2518  #define _(s) gettext(s)
2519  #include <netinet/in.h>
2520  #include <linux/socket.h>
2521 +#include <linux/limits.h>
2522  #include <arpa/inet.h>
2523  #include <linux/capability.h>
2524  
2525 @@ -35,8 +37,10 @@
2526  
2527  /* #define DEBUG */
2528  #ifdef DEBUG
2529 +#undef PDEBUG
2530  #define PDEBUG(fmt, args...) printf("Lexer: " fmt, ## args)
2531  #else
2532 +#undef PDEBUG
2533  #define PDEBUG(fmt, args...)   /* Do nothing */
2534  #endif
2535  #define NPDEBUG(fmt, args...)  /* Do nothing */
2536 @@ -102,7 +106,7 @@
2537  };
2538  
2539  /* for alpha matches, check for keywords */
2540 -static int get_table_token(const char *name, struct keyword_table *table,
2541 +static int get_table_token(const char *name __unused, struct keyword_table *table,
2542                            const char *keyword)
2543  {
2544         int i;
2545 @@ -142,42 +146,6 @@
2546         return get_table_token("rlimit", rlimit_table, name);
2547  }
2548  
2549 -static struct keyword_table address_family[] = {
2550 -/*     {"unix",        AF_UNIX},
2551 -       {"local",       AF_LOCAL},      */
2552 -       {"inet",        AF_INET},
2553 -/*     {"ax25",        AF_AX25},
2554 -       {"ipx",         AF_IPX},
2555 -       {"appletalk",   AF_APPLETALK},
2556 -       {"netrom",      AF_NETROM},
2557 -       {"bridge",      AF_BRIDGE},
2558 -       {"atmpvc",      AF_ATMPVC},
2559 -       {"x25",         AF_X25}, */
2560 -       {"inet6",       AF_INET6},
2561 -/*     {"rose",        AF_ROSE},
2562 -       {"decnet",      AF_DECnet},
2563 -       {"netbeui",     AF_NETBEUI},
2564 -       {"security",    AF_SECURITY},
2565 -       {"key",         AF_KEY},
2566 -       {"netlink",     AF_NETLINK},
2567 -       {"route",       AF_ROUTE},
2568 -       {"packet",      AF_PACKET},
2569 -       {"ash",         AF_ASH},
2570 -       {"econet",      AF_ECONET},
2571 -       {"atmsvc",      AF_ATMSVC},
2572 -       {"sna",         AF_SNA},
2573 -       {"irda",        AF_IRDA},
2574 -       {"pppox",       AF_PPPOX},
2575 -       {"wanpipe",     AF_WANPIPE},
2576 -       {"llc",         AF_LLC},
2577 -       {"tipc",        AF_TIPC},
2578 -       {"bluetooth",   AF_BLUETOOTH},
2579 -       {"iucv",        AF_IUCV},
2580 -       {"rxrpc",       AF_RXRPC}, */
2581 -       /* terminate */
2582 -       {NULL, 0}
2583 -};
2584 -
2585  struct network_tuple {
2586         char *family_name;
2587         unsigned int family;
2588 @@ -462,7 +430,7 @@
2589         }
2590  }
2591  
2592 -static int parse_sub_mode(const char *str_mode, const char *mode_desc)
2593 +static int parse_sub_mode(const char *str_mode, const char *mode_desc __unused)
2594  {
2595  
2596  #define IS_DIFF_QUAL(mode, q) (((mode) & AA_MAY_EXEC) && (((mode) & AA_EXEC_TYPE) != ((q) & AA_EXEC_TYPE)))
2597 @@ -666,7 +634,6 @@
2598  
2599         entry->pattern_type = ePatternInvalid;
2600         entry->pat.regex = NULL;
2601 -       entry->pat.compiled = NULL;
2602  
2603         entry->next = NULL;
2604  
2605 @@ -692,7 +659,6 @@
2606         /* XXX - need to create copies of the patterns, too */
2607         entry->pattern_type = orig->pattern_type;
2608         entry->pat.regex = NULL;
2609 -       entry->pat.compiled = NULL;
2610  
2611         entry->next = orig->next;
2612  
2613 @@ -713,8 +679,6 @@
2614                 free(list->link_name);
2615         if (list->pat.regex)
2616                 free(list->pat.regex);
2617 -       if (list->pat.compiled)
2618 -               free(list->pat.compiled);
2619         free(list);
2620  }
2621  
2622
2623 === modified file 'parser/parser_policy.c'
2624 --- parser/parser_policy.c      2009-08-20 15:27:12 +0000
2625 +++ parser/parser_policy.c      2010-05-31 18:58:40 +0000
2626 @@ -4,6 +4,9 @@
2627   *   Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
2628   *   NOVELL (All rights reserved)
2629   *
2630 + *   Copyright (c) 2010
2631 + *   Canonical, Ltd. (All rights reserved)
2632 + *
2633   *   This program is free software; you can redistribute it and/or
2634   *   modify it under the terms of version 2 of the GNU General Public
2635   *   License published by the Free Software Foundation.
2636 @@ -14,7 +17,8 @@
2637   *   GNU General Public License for more details.
2638   *
2639   *   You should have received a copy of the GNU General Public License
2640 - *   along with this program; if not, contact Novell, Inc.
2641 + *   along with this program; if not, contact Novell, Inc. or Canonical,
2642 + *   Ltd.
2643   */
2644  
2645  #include <stdio.h>
2646 @@ -664,7 +668,7 @@
2647         return ret;
2648  }
2649  
2650 -int post_process_policy(void)
2651 +int post_process_policy(int debug_only)
2652  {
2653         int retval = 0;
2654  
2655 @@ -696,11 +700,13 @@
2656                 return retval;
2657         }
2658  
2659 -       retval = post_process_regex();
2660 -       if (retval != 0) {
2661 -               PERROR(_("%s: Errors found during regex postprocess.  Aborting.\n"),
2662 -                      progname);
2663 -               return retval;
2664 +       if (!debug_only) {
2665 +               retval = post_process_regex();
2666 +               if (retval != 0) {
2667 +                       PERROR(_("%s: Errors found during regex postprocess.  Aborting.\n"),
2668 +                              progname);
2669 +                       return retval;
2670 +               }
2671         }
2672  
2673         return retval;
2674
2675 === modified file 'parser/parser_regex.c'
2676 --- parser/parser_regex.c       2010-02-12 21:49:58 +0000
2677 +++ parser/parser_regex.c       2010-08-03 17:27:13 +0000
2678 @@ -21,6 +21,7 @@
2679  #include <stdarg.h>
2680  #include <string.h>
2681  #include <libintl.h>
2682 +#include <linux/limits.h>
2683  #define _(s) gettext(s)
2684  
2685  /* #define DEBUG */
2686 @@ -74,7 +75,6 @@
2687  {
2688         char *sptr, *dptr;
2689         BOOL seen_slash = 0;
2690 -       int len;
2691  
2692         if (!path || (strlen(path) < 2))
2693                 return;
2694 @@ -106,19 +106,6 @@
2695                 }
2696         }
2697         *dptr = 0;
2698 -
2699 -       if (regex_type != AARE_DFA) {
2700 -               /* eliminate trailing slashes for versions of apparmor that
2701 -                * do not use the dfa engine.
2702 -                * Versions of apparmor which use the dfa engine use the
2703 -                * trailing / to differentiate between file and directory
2704 -                * matches
2705 -                */
2706 -               len = strlen(path);
2707 -               if (len > 2 && path[len -1] == '/') {
2708 -                       path[len - 1] = 0;
2709 -               }
2710 -       }
2711  }
2712  
2713  static pattern_t convert_aaregex_to_pcre(const char *aare, int anchor,
2714 @@ -154,6 +141,9 @@
2715         sptr = aare;
2716         dptr = pcre;
2717  
2718 +       if (dfaflags & DFA_DUMP_RULE_EXPR)
2719 +               fprintf(stderr, "aare: %s   ->   ", aare);
2720 +
2721         if (anchor)
2722                 /* anchor beginning of regular expression */
2723                 *dptr++ = '^';
2724 @@ -406,85 +396,13 @@
2725  out:
2726         if (ret == FALSE)
2727                 ptype = ePatternInvalid;
2728 +
2729 +       if (dfaflags & DFA_DUMP_RULE_EXPR)
2730 +               fprintf(stderr, "%s\n", pcre);
2731 +
2732         return ptype;
2733  }
2734  
2735 -static int process_pcre_entry(struct cod_entry *entry)
2736 -{
2737 -       char tbuf[PATH_MAX + 3];        /* +3 for ^, $ and \0 */
2738 -       int ret = TRUE;
2739 -       pattern_t ptype;
2740 -       int pos;
2741 -       if (!entry)             /* shouldn't happen */
2742 -               return TRUE;
2743 -
2744 -       ptype = convert_aaregex_to_pcre(entry->name, 1, tbuf, PATH_MAX+3, &pos);
2745 -       if (ptype == ePatternInvalid)
2746 -               return FALSE;
2747 -
2748 -       entry->pattern_type = ptype;
2749 -
2750 -       /*
2751 -        * Only use buffer (tbuf) that we built above, if we
2752 -        * identified a pattern requiring full regex support.
2753 -        */
2754 -       if (ptype == ePatternRegex) {
2755 -               int pattlen = strlen(tbuf);
2756 -
2757 -               if ((entry->pat.regex = malloc(pattlen + 1))) {
2758 -                       const char *errorreason;
2759 -                       int errpos;
2760 -
2761 -                       strcpy(entry->pat.regex, tbuf);
2762 -
2763 -                       if ((entry->pat.compiled =
2764 -                            pcre_compile(entry->pat.regex, 0,
2765 -                                         &errorreason, &errpos,
2766 -                                         NULL))) {
2767 -                               /* NULL out tables, kernel will use a
2768 -                                * private version
2769 -                                */
2770 -                               entry->pat.compiled->tables = NULL;
2771 -                       } else {
2772 -                               int i;
2773 -
2774 -                               PERROR(_("%s: Failed to compile regex '%s' [original: '%s']\n"),
2775 -                                      progname, entry->pat.regex,
2776 -                                      entry->name);
2777 -
2778 -                               PERROR(_("%s: error near               "),
2779 -                                      progname);
2780 -
2781 -                               for (i = 0; i < errpos; i++) {
2782 -                                       fputc('.', stderr);
2783 -                               }
2784 -
2785 -                               fputc('^', stderr);
2786 -                               fputc('\n', stderr);
2787 -
2788 -                               PERROR(_("%s: error reason: '%s'\n"),
2789 -                                      progname, errorreason);
2790 -
2791 -                               free(entry->pat.regex);
2792 -                               entry->pat.regex = NULL;
2793 -
2794 -                               ret = FALSE;
2795 -                       }
2796 -               } else {
2797 -                       PERROR(_("%s: Failed to compile regex '%s' [original: '%s'] - malloc failed\n"),
2798 -                              progname, entry->pat.regex, entry->name);
2799 -
2800 -                       ret = FALSE;
2801 -               }
2802 -       } else {
2803 -               /* not a regex, scan input for any escape characters
2804 -                * and remove, and reduce double \\ to a single */
2805 -               filter_escapes(entry->name);
2806 -       }               /* ptype == ePatternRegex */
2807 -
2808 -       return ret;
2809 -}
2810 -
2811  static const char *local_name(const char *name)
2812  {
2813         const char *t;
2814 @@ -519,7 +437,7 @@
2815                 aare_ruleset_t *rule = aare_new_ruleset(0);
2816                 if (!rule)
2817                         return FALSE;
2818 -               if (!aare_add_rule(rule, tbuf, 0, AA_MAY_EXEC, 0)) {
2819 +               if (!aare_add_rule(rule, tbuf, 0, AA_MAY_EXEC, 0, dfaflags)) {
2820                         aare_delete_ruleset(rule);
2821                         return FALSE;
2822                 }
2823 @@ -529,7 +447,7 @@
2824                                 int len;
2825                                 convert_aaregex_to_pcre(alt->name, 0, tbuf,
2826                                                         PATH_MAX + 3, &len);
2827 -                               if (!aare_add_rule(rule, tbuf, 0, AA_MAY_EXEC, 0)) {
2828 +                               if (!aare_add_rule(rule, tbuf, 0, AA_MAY_EXEC, 0, dfaflags)) {
2829                                         aare_delete_ruleset(rule);
2830                                         return FALSE;
2831                                 }
2832 @@ -538,7 +456,7 @@
2833                 cod->xmatch = aare_create_dfa(rule, &cod->xmatch_size,
2834                                               dfaflags);
2835                 aare_delete_ruleset(rule);
2836 -               if (!cod->xmatch)
2837 +               if (!cod->xmatch)
2838                         return FALSE;
2839         }
2840  
2841 @@ -581,11 +499,11 @@
2842         if (entry->deny && (entry->mode & AA_LINK_BITS)) {
2843                 if (!aare_add_rule(dfarules, tbuf, entry->deny,
2844                                    entry->mode & ~AA_LINK_BITS,
2845 -                                  entry->audit & ~AA_LINK_BITS))
2846 +                                  entry->audit & ~AA_LINK_BITS, dfaflags))
2847                         return FALSE;
2848         } else if (entry->mode & ~AA_CHANGE_PROFILE) {
2849                 if (!aare_add_rule(dfarules, tbuf, entry->deny, entry->mode,
2850 -                                  entry->audit))
2851 +                                  entry->audit, dfaflags))
2852                         return FALSE;
2853         }
2854  
2855 @@ -607,7 +525,7 @@
2856                         perms |= LINK_TO_LINK_SUBSET(perms);
2857                         vec[1] = "/[^/].*";
2858                 }
2859 -               if (!aare_add_rule_vec(dfarules, entry->deny, perms, entry->audit & AA_LINK_BITS, 2, vec))
2860 +               if (!aare_add_rule_vec(dfarules, entry->deny, perms, entry->audit & AA_LINK_BITS, 2, vec, dfaflags))
2861                         return FALSE;
2862         }
2863         if (entry->mode & AA_CHANGE_PROFILE) {
2864 @@ -618,10 +536,10 @@
2865                         ptype = convert_aaregex_to_pcre(entry->namespace, 0, lbuf, PATH_MAX + 8, &pos);
2866                         vec[0] = lbuf;
2867                         vec[1] = tbuf;
2868 -                       if (!aare_add_rule_vec(dfarules, 0, AA_CHANGE_PROFILE, 0, 2, vec))
2869 +                       if (!aare_add_rule_vec(dfarules, 0, AA_CHANGE_PROFILE, 0, 2, vec, dfaflags))
2870                             return FALSE;
2871                 } else {
2872 -                       if (!aare_add_rule(dfarules, tbuf, 0, AA_CHANGE_PROFILE, 0))
2873 +                 if (!aare_add_rule(dfarules, tbuf, 0, AA_CHANGE_PROFILE, 0, dfaflags))
2874                                 return FALSE;
2875                 }
2876         }
2877 @@ -631,10 +549,10 @@
2878                         char *vec[2];
2879                         vec[0] = entry->namespace;
2880                         vec[1] = entry->name;
2881 -                       if (!aare_add_rule_vec(dfarules, 0, mode, 0, 2, vec))
2882 +                       if (!aare_add_rule_vec(dfarules, 0, mode, 0, 2, vec, dfaflags))
2883                             return FALSE;
2884                 } else {
2885 -                       if (!aare_add_rule(dfarules, entry->name, 0, mode, 0))
2886 +                 if (!aare_add_rule(dfarules, entry->name, 0, mode, 0, dfaflags))
2887                                 return FALSE;
2888                 }
2889         }
2890 @@ -643,18 +561,13 @@
2891  
2892  int post_process_entries(struct codomain *cod)
2893  {
2894 -       int ret = TRUE, rc;
2895 +       int ret = TRUE;
2896         struct cod_entry *entry;
2897         int count = 0;
2898  
2899         list_for_each(cod->entries, entry) {
2900 -               if (regex_type == AARE_DFA) {
2901 -                       rc = process_dfa_entry(cod->dfarules, entry);
2902 -               } else {
2903 -                       filter_slashes(entry->name);
2904 -                       rc = process_pcre_entry(entry);
2905 -               }
2906 -               if (!rc)
2907 +               if (regex_type == AARE_DFA &&
2908 +                   !process_dfa_entry(cod->dfarules, entry))
2909                         ret = FALSE;
2910                 count++;
2911         }
2912 @@ -770,7 +683,7 @@
2913  
2914         test_string = strdup("///foo//////f//oo////////////////");
2915         filter_slashes(test_string);
2916 -       MY_TEST(strcmp(test_string, "/foo/f/oo") == 0, "simple tests");
2917 +       MY_TEST(strcmp(test_string, "/foo/f/oo/") == 0, "simple tests");
2918  
2919         test_string = strdup("/foo/f/oo");
2920         filter_slashes(test_string);
2921 @@ -802,13 +715,11 @@
2922  
2923         test_string = strdup("/a/");
2924         filter_slashes(test_string);
2925 -       MY_TEST(strcmp(test_string, "/a") == 0, "simple test for /a/");
2926 +       MY_TEST(strcmp(test_string, "/a/") == 0, "simple test for /a/");
2927  
2928         return rc;
2929  }
2930  
2931 -int regex_type = AARE_PCRE;
2932 -
2933  int main(void)
2934  {
2935         int rc = 0;
2936
2937 === modified file 'parser/parser_symtab.c'
2938 --- parser/parser_symtab.c      2009-07-24 13:24:53 +0000
2939 +++ parser/parser_symtab.c      2010-08-03 17:27:13 +0000
2940 @@ -23,6 +23,7 @@
2941  #include <string.h>
2942  #include <errno.h>
2943  #include <libintl.h>
2944 +#include <linux/limits.h>
2945  #define _(s) gettext(s)
2946  
2947  #include "immunix.h"
2948 @@ -33,11 +34,6 @@
2949         sd_set,
2950  };
2951  
2952 -struct set_value {
2953 -       char *val;
2954 -       struct set_value *next;
2955 -};
2956 -
2957  struct symtab {
2958         char *var_name;
2959         enum var_type type;
2960 @@ -288,7 +284,7 @@
2961  
2962  /* returns a pointer to the value list, which should be used as the
2963   * argument to the get_next_set_value() function. */
2964 -void *get_set_var(const char *var)
2965 +struct set_value *get_set_var(const char *var)
2966  {
2967         struct symtab *result;
2968         struct set_value *valuelist = NULL;
2969 @@ -321,16 +317,17 @@
2970  }
2971  
2972  /* iterator to walk the list of set values */
2973 -char *get_next_set_value(void **list)
2974 +char *get_next_set_value(struct set_value **list)
2975  {
2976 -       struct set_value **valuelist = (struct set_value **) list;
2977 +       struct set_value *next;
2978         char *ret;
2979  
2980 -       if (!valuelist || !(*valuelist))
2981 +       if (!list || !(*list))
2982                 return NULL;
2983  
2984 -       ret = (*valuelist)->val;
2985 -       (*valuelist) = (*valuelist)->next;
2986 +       ret = (*list)->val;
2987 +       next = (*list)->next;
2988 +       (*list) = next;
2989  
2990         return ret;
2991  }
2992 @@ -429,10 +426,13 @@
2993  
2994                         for (ref_item = ref->expanded; ref_item; ref_item = ref_item->next) {
2995                                 char *expanded_string;
2996 -                               asprintf(&expanded_string, "%s%s%s",
2997 +                               if (!asprintf(&expanded_string, "%s%s%s",
2998                                          split->prefix ?  split->prefix : "",
2999                                          ref_item->val,
3000 -                                        split->suffix ?  split->suffix : "");
3001 +                                        split->suffix ?  split->suffix : "")) {
3002 +                                       PERROR("Out of memory\n");
3003 +                                       exit(1);
3004 +                               }
3005                                 add_to_set(&work_list, expanded_string);
3006                                 free(expanded_string);
3007                         }
3008 @@ -569,7 +569,7 @@
3009  {
3010         int rc = 0;
3011         int retval;
3012 -       void *retptr;
3013 +       struct set_value *retptr;
3014         struct symtab *a, *b;
3015  
3016         a = new_symtab_entry("blah");
3017
3018 === modified file 'parser/parser_variable.c'
3019 --- parser/parser_variable.c    2009-07-24 23:47:46 +0000
3020 +++ parser/parser_variable.c    2010-08-03 17:27:13 +0000
3021 @@ -17,10 +17,14 @@
3022   *   along with this program; if not, contact Novell, Inc.
3023   */
3024  
3025 +#include <ctype.h>
3026 +#include <stdlib.h>
3027  #include <stdio.h>
3028  #include <stdarg.h>
3029  #include <string.h>
3030  #include <libintl.h>
3031 +#include <linux/limits.h>
3032 +
3033  #define _(s) gettext(s)
3034  
3035  /* #define DEBUG */
3036 @@ -124,7 +128,7 @@
3037  
3038  static int expand_entry_variables(struct cod_entry *entry)
3039  {
3040 -       void *valuelist;
3041 +       struct set_value *valuelist;
3042         int ret = TRUE;
3043         char *value;
3044         struct var_string *split_var;
3045
3046 === modified file 'parser/parser_yacc.y'
3047 --- parser/parser_yacc.y        2010-02-17 20:21:52 +0000
3048 +++ parser/parser_yacc.y        2010-08-03 17:27:13 +0000
3049 @@ -1,9 +1,9 @@
3050  %{
3051 -/* $Id$ */
3052 -
3053  /*
3054   *   Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
3055   *   NOVELL (All rights reserved)
3056 + *   Copyright (c) 2010
3057 + *   Canonical, Ltd.
3058   *
3059   *   This program is free software; you can redistribute it and/or
3060   *   modify it under the terms of version 2 of the GNU General Public
3061 @@ -15,7 +15,7 @@
3062   *   GNU General Public License for more details.
3063   *
3064   *   You should have received a copy of the GNU General Public License
3065 - *   along with this program; if not, contact Novell, Inc.
3066 + *   along with this program; if not, contact Canonical, Ltd.
3067   */
3068  
3069  #define YYERROR_VERBOSE 1
3070 @@ -32,6 +32,7 @@
3071  /* #define DEBUG */
3072  
3073  #include "parser.h"
3074 +#include "parser_include.h"
3075  #include <unistd.h>
3076  #include <netinet/in.h>
3077  #include <arpa/inet.h>
3078 @@ -63,10 +64,6 @@
3079  
3080  #define CAP_TO_MASK(x) (1ull << (x))
3081  
3082 -/* from lex_config, for nice error messages */
3083 -/* extern char *current_file; */
3084 -extern int current_lineno;
3085 -
3086  struct value_list {
3087         char *value;
3088         struct value_list *next;
3089 @@ -415,7 +412,7 @@
3090  
3091  flagval:       TOK_FLAG_ID
3092         {
3093 -               struct flagval fv = {0, 0, 0};
3094 +               struct flagval fv = { 0, 0, 0, 0 };
3095                 if (strcmp($1, "debug") == 0) {
3096                         yyerror(_("Profile flag 'debug' is no longer valid."));
3097                 } else if (strcmp($1, "complain") == 0) {
3098 @@ -1109,10 +1106,15 @@
3099         va_end(arg);
3100  
3101         if (profilename) {
3102 -               PERROR(_("AppArmor parser error in %s at line %d: %s\n"),
3103 -                      profilename, current_lineno, buf);
3104 +               PERROR(_("AppArmor parser error for %s%s%s at line %d: %s\n"),
3105 +                      profilename,
3106 +                      current_filename ? " in " : "",
3107 +                      current_filename ? current_filename : "",
3108 +                      current_lineno, buf);
3109         } else {
3110 -               PERROR(_("AppArmor parser error, line %d: %s\n"),
3111 +               PERROR(_("AppArmor parser error,%s%s line %d: %s\n"),
3112 +                      current_filename ? " in " : "",
3113 +                      current_filename ? current_filename : "",
3114                        current_lineno, buf);
3115         }
3116  
3117
3118 === removed directory 'parser/pcre'
3119 === removed file 'parser/pcre/Makefile'
3120 --- parser/pcre/Makefile        2007-03-30 16:30:15 +0000
3121 +++ parser/pcre/Makefile        1970-01-01 00:00:00 +0000
3122 @@ -1,7 +0,0 @@
3123 -all: pcre.o
3124 -
3125 -pcre.o:  pcre.c
3126 -       $(CC) -c $(CFLAGS) $<
3127 -
3128 -clean:
3129 -       rm -f pcre.o
3130
3131 === removed file 'parser/pcre/chartables.c'
3132 --- parser/pcre/chartables.c    2006-04-11 21:52:54 +0000
3133 +++ parser/pcre/chartables.c    1970-01-01 00:00:00 +0000
3134 @@ -1,183 +0,0 @@
3135 -/*************************************************
3136 -*      Perl-Compatible Regular Expressions       *
3137 -*************************************************/
3138 -
3139 -/* This file is automatically written by the dftables auxiliary 
3140 -program. If you edit it by hand, you might like to edit the Makefile to 
3141 -prevent its ever being regenerated.
3142 -
3143 -This file is #included in the compilation of pcre.c to build the default
3144 -character tables which are used when no tables are passed to the compile
3145 -function. */
3146 -
3147 -static unsigned char pcre_default_tables[] = {
3148 -
3149 -/* This table is a lower casing table. */
3150 -
3151 -    0,  1,  2,  3,  4,  5,  6,  7,
3152 -    8,  9, 10, 11, 12, 13, 14, 15,
3153 -   16, 17, 18, 19, 20, 21, 22, 23,
3154 -   24, 25, 26, 27, 28, 29, 30, 31,
3155 -   32, 33, 34, 35, 36, 37, 38, 39,
3156 -   40, 41, 42, 43, 44, 45, 46, 47,
3157 -   48, 49, 50, 51, 52, 53, 54, 55,
3158 -   56, 57, 58, 59, 60, 61, 62, 63,
3159 -   64, 97, 98, 99,100,101,102,103,
3160 -  104,105,106,107,108,109,110,111,
3161 -  112,113,114,115,116,117,118,119,
3162 -  120,121,122, 91, 92, 93, 94, 95,
3163 -   96, 97, 98, 99,100,101,102,103,
3164 -  104,105,106,107,108,109,110,111,
3165 -  112,113,114,115,116,117,118,119,
3166 -  120,121,122,123,124,125,126,127,
3167 -  128,129,130,131,132,133,134,135,
3168 -  136,137,138,139,140,141,142,143,
3169 -  144,145,146,147,148,149,150,151,
3170 -  152,153,154,155,156,157,158,159,
3171 -  160,161,162,163,164,165,166,167,
3172 -  168,169,170,171,172,173,174,175,
3173 -  176,177,178,179,180,181,182,183,
3174 -  184,185,186,187,188,189,190,191,
3175 -  192,193,194,195,196,197,198,199,
3176 -  200,201,202,203,204,205,206,207,
3177 -  208,209,210,211,212,213,214,215,
3178 -  216,217,218,219,220,221,222,223,
3179 -  224,225,226,227,228,229,230,231,
3180 -  232,233,234,235,236,237,238,239,
3181 -  240,241,242,243,244,245,246,247,
3182 -  248,249,250,251,252,253,254,255,
3183 -
3184 -/* This table is a case flipping table. */
3185 -
3186 -    0,  1,  2,  3,  4,  5,  6,  7,
3187 -    8,  9, 10, 11, 12, 13, 14, 15,
3188 -   16, 17, 18, 19, 20, 21, 22, 23,
3189 -   24, 25, 26, 27, 28, 29, 30, 31,
3190 -   32, 33, 34, 35, 36, 37, 38, 39,
3191 -   40, 41, 42, 43, 44, 45, 46, 47,
3192 -   48, 49, 50, 51, 52, 53, 54, 55,
3193 -   56, 57, 58, 59, 60, 61, 62, 63,
3194 -   64, 97, 98, 99,100,101,102,103,
3195 -  104,105,106,107,108,109,110,111,
3196 -  112,113,114,115,116,117,118,119,
3197 -  120,121,122, 91, 92, 93, 94, 95,
3198 -   96, 65, 66, 67, 68, 69, 70, 71,
3199 -   72, 73, 74, 75, 76, 77, 78, 79,
3200 -   80, 81, 82, 83, 84, 85, 86, 87,
3201 -   88, 89, 90,123,124,125,126,127,
3202 -  128,129,130,131,132,133,134,135,
3203 -  136,137,138,139,140,141,142,143,
3204 -  144,145,146,147,148,149,150,151,
3205 -  152,153,154,155,156,157,158,159,
3206 -  160,161,162,163,164,165,166,167,
3207 -  168,169,170,171,172,173,174,175,
3208 -  176,177,178,179,180,181,182,183,
3209 -  184,185,186,187,188,189,190,191,
3210 -  192,193,194,195,196,197,198,199,
3211 -  200,201,202,203,204,205,206,207,
3212 -  208,209,210,211,212,213,214,215,
3213 -  216,217,218,219,220,221,222,223,
3214 -  224,225,226,227,228,229,230,231,
3215 -  232,233,234,235,236,237,238,239,
3216 -  240,241,242,243,244,245,246,247,
3217 -  248,249,250,251,252,253,254,255,
3218 -
3219 -/* This table contains bit maps for various character classes.
3220 -Each map is 32 bytes long and the bits run from the least
3221 -significant end of each byte. The classes that have their own
3222 -maps are: space, xdigit, digit, upper, lower, word, graph
3223 -print, punct, and cntrl. Other classes are built from combinations. */
3224 -
3225 -  0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00,
3226 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3227 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3228 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3229 -
3230 -  0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
3231 -  0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,
3232 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3233 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3234 -
3235 -  0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
3236 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3237 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3238 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3239 -
3240 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3241 -  0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
3242 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3243 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3244 -
3245 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3246 -  0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,
3247 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3248 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3249 -
3250 -  0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
3251 -  0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07,
3252 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3253 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3254 -
3255 -  0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
3256 -  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
3257 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3258 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3259 -
3260 -  0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
3261 -  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
3262 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3263 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3264 -
3265 -  0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc,
3266 -  0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78,
3267 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3268 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3269 -
3270 -  0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
3271 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
3272 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3273 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
3274 -
3275 -/* This table identifies various classes of character by individual bits:
3276 -  0x01   white space character
3277 -  0x02   letter
3278 -  0x04   decimal digit
3279 -  0x08   hexadecimal digit
3280 -  0x10   alphanumeric or '_'
3281 -  0x80   regular expression metacharacter or binary zero
3282 -*/
3283 -
3284 -  0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*   0-  7 */
3285 -  0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /*   8- 15 */
3286 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  16- 23 */
3287 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*  24- 31 */
3288 -  0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /*    - '  */
3289 -  0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /*  ( - /  */
3290 -  0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /*  0 - 7  */
3291 -  0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /*  8 - ?  */
3292 -  0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /*  @ - G  */
3293 -  0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /*  H - O  */
3294 -  0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /*  P - W  */
3295 -  0x12,0x12,0x12,0x80,0x00,0x00,0x80,0x10, /*  X - _  */
3296 -  0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /*  ` - g  */
3297 -  0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /*  h - o  */
3298 -  0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /*  p - w  */
3299 -  0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /*  x -127 */
3300 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */
3301 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */
3302 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */
3303 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */
3304 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */
3305 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */
3306 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */
3307 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
3308 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */
3309 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */
3310 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */
3311 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */
3312 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */
3313 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */
3314 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */
3315 -  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */
3316 -
3317 -/* End of chartables.c */
3318
3319 === removed file 'parser/pcre/config.h'
3320 --- parser/pcre/config.h        2006-04-11 21:52:54 +0000
3321 +++ parser/pcre/config.h        1970-01-01 00:00:00 +0000
3322 @@ -1,48 +0,0 @@
3323 -/* config.h.  Generated automatically by configure.  */
3324 -
3325 -/* On Unix systems config.in is converted by configure into config.h. PCRE is
3326 -written in Standard C, but there are a few non-standard things it can cope
3327 -with, allowing it to run on SunOS4 and other "close to standard" systems.
3328 -
3329 -On a non-Unix system you should just copy this file into config.h, and set up
3330 -the macros the way you need them. You should normally change the definitions of
3331 -HAVE_STRERROR and HAVE_MEMMOVE to 1. Unfortunately, because of the way autoconf
3332 -works, these cannot be made the defaults. If your system has bcopy() and not
3333 -memmove(), change the definition of HAVE_BCOPY instead of HAVE_MEMMOVE. If your
3334 -system has neither bcopy() nor memmove(), leave them both as 0; an emulation
3335 -function will be used. */
3336 -
3337 -/* Define to empty if the keyword does not work. */
3338 -
3339 -/* #undef const */
3340 -
3341 -/* Define to `unsigned' if <stddef.h> doesn't define size_t. */
3342 -
3343 -/* #undef size_t */
3344 -
3345 -/* The following two definitions are mainly for the benefit of SunOS4, which
3346 -doesn't have the strerror() or memmove() functions that should be present in
3347 -all Standard C libraries. The macros HAVE_STRERROR and HAVE_MEMMOVE should
3348 -normally be defined with the value 1 for other systems, but unfortunately we
3349 -can't make this the default because "configure" files generated by autoconf
3350 -will only change 0 to 1; they won't change 1 to 0 if the functions are not
3351 -found. */
3352 -
3353 -#define HAVE_STRERROR 1
3354 -#define HAVE_MEMMOVE 1
3355 -
3356 -/* There are some non-Unix systems that don't even have bcopy(). If this macro
3357 -is false, an emulation is used. If HAVE_MEMMOVE is set to 1, the value of
3358 -HAVE_BCOPY is not relevant. */
3359 -
3360 -#define HAVE_BCOPY 1
3361 -
3362 -/* The value of NEWLINE determines the newline character. The default is to
3363 -leave it up to the compiler, but some sites want to force a particular value.
3364 -On Unix systems, "configure" can be used to override this default. */
3365 -
3366 -#ifndef NEWLINE
3367 -#define NEWLINE '\n'
3368 -#endif
3369 -
3370 -/* End */
3371
3372 === removed file 'parser/pcre/internal.h'
3373 --- parser/pcre/internal.h      2006-04-11 21:52:54 +0000
3374 +++ parser/pcre/internal.h      1970-01-01 00:00:00 +0000
3375 @@ -1,412 +0,0 @@
3376 -/*************************************************
3377 -*      Perl-Compatible Regular Expressions       *
3378 -*************************************************/
3379 -
3380 -
3381 -/* This is a library of functions to support regular expressions whose syntax
3382 -and semantics are as close as possible to those of the Perl 5 language. See
3383 -the file Tech.Notes for some information on the internals.
3384 -
3385 -Written by: Philip Hazel <ph10@cam.ac.uk>
3386 -
3387 -           Copyright (c) 1997-2001 University of Cambridge
3388 -
3389 ------------------------------------------------------------------------------
3390 -Permission is granted to anyone to use this software for any purpose on any
3391 -computer system, and to redistribute it freely, subject to the following
3392 -restrictions:
3393 -
3394 -1. This software is distributed in the hope that it will be useful,
3395 -   but WITHOUT ANY WARRANTY; without even the implied warranty of
3396 -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
3397 -
3398 -2. The origin of this software must not be misrepresented, either by
3399 -   explicit claim or by omission.
3400 -
3401 -3. Altered versions must be plainly marked as such, and must not be
3402 -   misrepresented as being the original software.
3403 -
3404 -4. If PCRE is embedded in any software that is released under the GNU
3405 -   General Purpose Licence (GPL), then the terms of that licence shall
3406 -   supersede any condition above with which it is incompatible.
3407 ------------------------------------------------------------------------------
3408 -*/
3409 -
3410 -/* This header contains definitions that are shared between the different
3411 -modules, but which are not relevant to the outside. */
3412 -
3413 -/* Get the definitions provided by running "configure" */
3414 -
3415 -#include "config.h"
3416 -
3417 -/* To cope with SunOS4 and other systems that lack memmove() but have bcopy(),
3418 -define a macro for memmove() if HAVE_MEMMOVE is false, provided that HAVE_BCOPY
3419 -is set. Otherwise, include an emulating function for those systems that have
3420 -neither (there some non-Unix environments where this is the case). This assumes
3421 -that all calls to memmove are moving strings upwards in store, which is the
3422 -case in PCRE. */
3423 -
3424 -#if ! HAVE_MEMMOVE
3425 -#undef  memmove        /* some systems may have a macro */
3426 -#if HAVE_BCOPY
3427 -#define memmove(a, b, c) bcopy(b, a, c)
3428 -#else
3429 -void *
3430 -pcre_memmove(unsigned char *dest, const unsigned char *src, size_t n)
3431 -{
3432 -int i;
3433 -dest += n;
3434 -src += n;
3435 -for (i = 0; i < n; ++i) *(--dest) =  *(--src);
3436 -}
3437 -#define memmove(a, b, c) pcre_memmove(a, b, c)
3438 -#endif
3439 -#endif
3440 -
3441 -/* Standard C headers plus the external interface definition */
3442 -
3443 -#include <ctype.h>
3444 -#include <limits.h>
3445 -#include <stddef.h>
3446 -#include <stdio.h>
3447 -#include <stdlib.h>
3448 -#include <string.h>
3449 -#include "pcre.h"
3450 -
3451 -/* In case there is no definition of offsetof() provided - though any proper
3452 -Standard C system should have one. */
3453 -
3454 -#ifndef offsetof
3455 -#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field))
3456 -#endif
3457 -
3458 -/* These are the public options that can change during matching. */
3459 -
3460 -#define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL)
3461 -
3462 -/* Private options flags start at the most significant end of the four bytes,
3463 -but skip the top bit so we can use ints for convenience without getting tangled
3464 -with negative values. The public options defined in pcre.h start at the least
3465 -significant end. Make sure they don't overlap, though now that we have expanded
3466 -to four bytes there is plenty of space. */
3467 -
3468 -#define PCRE_FIRSTSET      0x40000000  /* first_char is set */
3469 -#define PCRE_REQCHSET      0x20000000  /* req_char is set */
3470 -#define PCRE_STARTLINE     0x10000000  /* start after \n for multiline */
3471 -#define PCRE_INGROUP       0x08000000  /* compiling inside a group */
3472 -#define PCRE_ICHANGED      0x04000000  /* i option changes within regex */
3473 -
3474 -/* Options for the "extra" block produced by pcre_study(). */
3475 -
3476 -#define PCRE_STUDY_MAPPED   0x01     /* a map of starting chars exists */
3477 -
3478 -/* Masks for identifying the public options which are permitted at compile
3479 -time, run time or study time, respectively. */
3480 -
3481 -#define PUBLIC_OPTIONS \
3482 -  (PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \
3483 -   PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8)
3484 -
3485 -#define PUBLIC_EXEC_OPTIONS \
3486 -  (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY)
3487 -
3488 -#define PUBLIC_STUDY_OPTIONS 0   /* None defined */
3489 -
3490 -/* Magic number to provide a small check against being handed junk. */
3491 -
3492 -#define MAGIC_NUMBER  0x50435245UL   /* 'PCRE' */
3493 -
3494 -/* Miscellaneous definitions */
3495 -
3496 -typedef int BOOL;
3497 -
3498 -#define FALSE   0
3499 -#define TRUE    1
3500 -
3501 -/* Escape items that are just an encoding of a particular data value. Note that
3502 -ESC_N is defined as yet another macro, which is set in config.h to either \n
3503 -(the default) or \r (which some people want). */
3504 -
3505 -#ifndef ESC_E
3506 -#define ESC_E 27
3507 -#endif
3508 -
3509 -#ifndef ESC_F
3510 -#define ESC_F '\f'
3511 -#endif
3512 -
3513 -#ifndef ESC_N
3514 -#define ESC_N NEWLINE
3515 -#endif
3516 -
3517 -#ifndef ESC_R
3518 -#define ESC_R '\r'
3519 -#endif
3520 -
3521 -#ifndef ESC_T
3522 -#define ESC_T '\t'
3523 -#endif
3524 -
3525 -/* These are escaped items that aren't just an encoding of a particular data
3526 -value such as \n. They must have non-zero values, as check_escape() returns
3527 -their negation. Also, they must appear in the same order as in the opcode
3528 -definitions below, up to ESC_z. The final one must be ESC_REF as subsequent
3529 -values are used for \1, \2, \3, etc. There is a test in the code for an escape
3530 -greater than ESC_b and less than ESC_Z to detect the types that may be
3531 -repeated. If any new escapes are put in-between that don't consume a character,
3532 -that code will have to change. */
3533 -
3534 -enum { ESC_A = 1, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, ESC_w,
3535 -       ESC_Z, ESC_z, ESC_REF };
3536 -
3537 -/* Opcode table: OP_BRA must be last, as all values >= it are used for brackets
3538 -that extract substrings. Starting from 1 (i.e. after OP_END), the values up to
3539 -OP_EOD must correspond in order to the list of escapes immediately above. */
3540 -
3541 -enum {
3542 -  OP_END,            /* End of pattern */
3543 -
3544 -  /* Values corresponding to backslashed metacharacters */
3545 -
3546 -  OP_SOD,            /* Start of data: \A */
3547 -  OP_NOT_WORD_BOUNDARY,  /* \B */
3548 -  OP_WORD_BOUNDARY,      /* \b */
3549 -  OP_NOT_DIGIT,          /* \D */
3550 -  OP_DIGIT,              /* \d */
3551 -  OP_NOT_WHITESPACE,     /* \S */
3552 -  OP_WHITESPACE,         /* \s */
3553 -  OP_NOT_WORDCHAR,       /* \W */
3554 -  OP_WORDCHAR,           /* \w */
3555 -  OP_EODN,           /* End of data or \n at end of data: \Z. */
3556 -  OP_EOD,            /* End of data: \z */
3557 -
3558 -  OP_OPT,            /* Set runtime options */
3559 -  OP_CIRC,           /* Start of line - varies with multiline switch */
3560 -  OP_DOLL,           /* End of line - varies with multiline switch */
3561 -  OP_ANY,            /* Match any character */
3562 -  OP_CHARS,          /* Match string of characters */
3563 -  OP_NOT,            /* Match anything but the following char */
3564 -
3565 -  OP_STAR,           /* The maximizing and minimizing versions of */
3566 -  OP_MINSTAR,        /* all these opcodes must come in pairs, with */
3567 -  OP_PLUS,           /* the minimizing one second. */
3568 -  OP_MINPLUS,        /* This first set applies to single characters */
3569 -  OP_QUERY,
3570 -  OP_MINQUERY,
3571 -  OP_UPTO,           /* From 0 to n matches */
3572 -  OP_MINUPTO,
3573 -  OP_EXACT,          /* Exactly n matches */
3574 -
3575 -  OP_NOTSTAR,        /* The maximizing and minimizing versions of */
3576 -  OP_NOTMINSTAR,     /* all these opcodes must come in pairs, with */
3577 -  OP_NOTPLUS,        /* the minimizing one second. */
3578 -  OP_NOTMINPLUS,     /* This first set applies to "not" single characters */
3579 -  OP_NOTQUERY,
3580 -  OP_NOTMINQUERY,
3581 -  OP_NOTUPTO,        /* From 0 to n matches */
3582 -  OP_NOTMINUPTO,
3583 -  OP_NOTEXACT,       /* Exactly n matches */
3584 -
3585 -  OP_TYPESTAR,       /* The maximizing and minimizing versions of */
3586 -  OP_TYPEMINSTAR,    /* all these opcodes must come in pairs, with */
3587 -  OP_TYPEPLUS,       /* the minimizing one second. These codes must */
3588 -  OP_TYPEMINPLUS,    /* be in exactly the same order as those above. */
3589 -  OP_TYPEQUERY,      /* This set applies to character types such as \d */
3590 -  OP_TYPEMINQUERY,
3591 -  OP_TYPEUPTO,       /* From 0 to n matches */
3592 -  OP_TYPEMINUPTO,
3593 -  OP_TYPEEXACT,      /* Exactly n matches */
3594 -
3595 -  OP_CRSTAR,         /* The maximizing and minimizing versions of */
3596 -  OP_CRMINSTAR,      /* all these opcodes must come in pairs, with */
3597 -  OP_CRPLUS,         /* the minimizing one second. These codes must */
3598 -  OP_CRMINPLUS,      /* be in exactly the same order as those above. */
3599 -  OP_CRQUERY,        /* These are for character classes and back refs */
3600 -  OP_CRMINQUERY,
3601 -  OP_CRRANGE,        /* These are different to the three seta above. */
3602 -  OP_CRMINRANGE,
3603 -
3604 -  OP_CLASS,          /* Match a character class */
3605 -  OP_REF,            /* Match a back reference */
3606 -  OP_RECURSE,        /* Match this pattern recursively */
3607 -
3608 -  OP_ALT,            /* Start of alternation */
3609 -  OP_KET,            /* End of group that doesn't have an unbounded repeat */
3610 -  OP_KETRMAX,        /* These two must remain together and in this */
3611 -  OP_KETRMIN,        /* order. They are for groups the repeat for ever. */
3612 -
3613 -  /* The assertions must come before ONCE and COND */
3614 -
3615 -  OP_ASSERT,         /* Positive lookahead */
3616 -  OP_ASSERT_NOT,     /* Negative lookahead */
3617 -  OP_ASSERTBACK,     /* Positive lookbehind */
3618 -  OP_ASSERTBACK_NOT, /* Negative lookbehind */
3619 -  OP_REVERSE,        /* Move pointer back - used in lookbehind assertions */
3620 -
3621 -  /* ONCE and COND must come after the assertions, with ONCE first, as there's
3622 -  a test for >= ONCE for a subpattern that isn't an assertion. */
3623 -
3624 -  OP_ONCE,           /* Once matched, don't back up into the subpattern */
3625 -  OP_COND,           /* Conditional group */
3626 -  OP_CREF,           /* Used to hold an extraction string number (cond ref) */
3627 -
3628 -  OP_BRAZERO,        /* These two must remain together and in this */
3629 -  OP_BRAMINZERO,     /* order. */
3630 -
3631 -  OP_BRANUMBER,      /* Used for extracting brackets whose number is greater
3632 -                        than can fit into an opcode. */
3633 -
3634 -  OP_BRA             /* This and greater values are used for brackets that
3635 -                        extract substrings up to a basic limit. After that,
3636 -                        use is made of OP_BRANUMBER. */
3637 -};
3638 -
3639 -/* The highest extraction number before we have to start using additional
3640 -bytes. (Originally PCRE didn't have support for extraction counts highter than
3641 -this number.) The value is limited by the number of opcodes left after OP_BRA,
3642 -i.e. 255 - OP_BRA. We actually set it a bit lower to leave room for additional
3643 -opcodes. */
3644 -
3645 -#define EXTRACT_BASIC_MAX  150
3646 -
3647 -/* The texts of compile-time error messages are defined as macros here so that
3648 -they can be accessed by the POSIX wrapper and converted into error codes.  Yes,
3649 -I could have used error codes in the first place, but didn't feel like changing
3650 -just to accommodate the POSIX wrapper. */
3651 -
3652 -#define ERR1  "\\ at end of pattern"
3653 -#define ERR2  "\\c at end of pattern"
3654 -#define ERR3  "unrecognized character follows \\"
3655 -#define ERR4  "numbers out of order in {} quantifier"
3656 -#define ERR5  "number too big in {} quantifier"
3657 -#define ERR6  "missing terminating ] for character class"
3658 -#define ERR7  "invalid escape sequence in character class"
3659 -#define ERR8  "range out of order in character class"
3660 -#define ERR9  "nothing to repeat"
3661 -#define ERR10 "operand of unlimited repeat could match the empty string"
3662 -#define ERR11 "internal error: unexpected repeat"
3663 -#define ERR12 "unrecognized character after (?"
3664 -#define ERR13 "unused error"
3665 -#define ERR14 "missing )"
3666 -#define ERR15 "back reference to non-existent subpattern"
3667 -#define ERR16 "erroffset passed as NULL"
3668 -#define ERR17 "unknown option bit(s) set"
3669 -#define ERR18 "missing ) after comment"
3670 -#define ERR19 "parentheses nested too deeply"
3671 -#define ERR20 "regular expression too large"
3672 -#define ERR21 "failed to get memory"
3673 -#define ERR22 "unmatched parentheses"
3674 -#define ERR23 "internal error: code overflow"
3675 -#define ERR24 "unrecognized character after (?<"
3676 -#define ERR25 "lookbehind assertion is not fixed length"
3677 -#define ERR26 "malformed number after (?("
3678 -#define ERR27 "conditional group contains more than two branches"
3679 -#define ERR28 "assertion expected after (?("
3680 -#define ERR29 "(?p must be followed by )"
3681 -#define ERR30 "unknown POSIX class name"
3682 -#define ERR31 "POSIX collating elements are not supported"
3683 -#define ERR32 "this version of PCRE is not compiled with PCRE_UTF8 support"
3684 -#define ERR33 "characters with values > 255 are not yet supported in classes"
3685 -#define ERR34 "character value in \\x{...} sequence is too large"
3686 -#define ERR35 "invalid condition (?(0)"
3687 -
3688 -/* All character handling must be done as unsigned characters. Otherwise there
3689 -are problems with top-bit-set characters and functions such as isspace().
3690 -However, we leave the interface to the outside world as char *, because that
3691 -should make things easier for callers. We define a short type for unsigned char
3692 -to save lots of typing. I tried "uchar", but it causes problems on Digital
3693 -Unix, where it is defined in sys/types, so use "uschar" instead. */
3694 -
3695 -typedef unsigned char uschar;
3696 -
3697 -/* The real format of the start of the pcre block; the actual code vector
3698 -runs on as long as necessary after the end. */
3699 -
3700 -typedef struct real_pcre {
3701 -  unsigned long int magic_number;
3702 -  size_t size;
3703 -  const unsigned char *tables;
3704 -  unsigned long int options;
3705 -  unsigned short int top_bracket;
3706 -  unsigned short int top_backref;
3707 -  uschar first_char;
3708 -  uschar req_char;
3709 -  uschar code[1];
3710 -} real_pcre;
3711 -
3712 -/* The real format of the extra block returned by pcre_study(). */
3713 -
3714 -typedef struct real_pcre_extra {
3715 -  uschar options;
3716 -  uschar start_bits[32];
3717 -} real_pcre_extra;
3718 -
3719 -
3720 -/* Structure for passing "static" information around between the functions
3721 -doing the compiling, so that they are thread-safe. */
3722 -
3723 -typedef struct compile_data {
3724 -  const uschar *lcc;            /* Points to lower casing table */
3725 -  const uschar *fcc;            /* Points to case-flipping table */
3726 -  const uschar *cbits;          /* Points to character type table */
3727 -  const uschar *ctypes;         /* Points to table of type maps */
3728 -} compile_data;
3729 -
3730 -/* Structure for passing "static" information around between the functions
3731 -doing the matching, so that they are thread-safe. */
3732 -
3733 -typedef struct match_data {
3734 -  int    errorcode;             /* As it says */
3735 -  int   *offset_vector;         /* Offset vector */
3736 -  int    offset_end;            /* One past the end */
3737 -  int    offset_max;            /* The maximum usable for return data */
3738 -  const uschar *lcc;            /* Points to lower casing table */
3739 -  const uschar *ctypes;         /* Points to table of type maps */
3740 -  BOOL   offset_overflow;       /* Set if too many extractions */
3741 -  BOOL   notbol;                /* NOTBOL flag */
3742 -  BOOL   noteol;                /* NOTEOL flag */
3743 -  BOOL   utf8;                  /* UTF8 flag */
3744 -  BOOL   endonly;               /* Dollar not before final \n */
3745 -  BOOL   notempty;              /* Empty string match not wanted */
3746 -  const uschar *start_pattern;  /* For use when recursing */
3747 -  const uschar *start_subject;  /* Start of the subject string */
3748 -  const uschar *end_subject;    /* End of the subject string */
3749 -  const uschar *start_match;    /* Start of this match attempt */
3750 -  const uschar *end_match_ptr;  /* Subject position at end match */
3751 -  int    end_offset_top;        /* Highwater mark at end of match */
3752 -} match_data;
3753 -
3754 -/* Bit definitions for entries in the pcre_ctypes table. */
3755 -
3756 -#define ctype_space   0x01
3757 -#define ctype_letter  0x02
3758 -#define ctype_digit   0x04
3759 -#define ctype_xdigit  0x08
3760 -#define ctype_word    0x10   /* alphameric or '_' */
3761 -#define ctype_meta    0x80   /* regexp meta char or zero (end pattern) */
3762 -
3763 -/* Offsets for the bitmap tables in pcre_cbits. Each table contains a set
3764 -of bits for a class map. Some classes are built by combining these tables. */
3765 -
3766 -#define cbit_space     0      /* [:space:] or \s */
3767 -#define cbit_xdigit   32      /* [:xdigit:] */
3768 -#define cbit_digit    64      /* [:digit:] or \d */
3769 -#define cbit_upper    96      /* [:upper:] */
3770 -#define cbit_lower   128      /* [:lower:] */
3771 -#define cbit_word    160      /* [:word:] or \w */
3772 -#define cbit_graph   192      /* [:graph:] */
3773 -#define cbit_print   224      /* [:print:] */
3774 -#define cbit_punct   256      /* [:punct:] */
3775 -#define cbit_cntrl   288      /* [:cntrl:] */
3776 -#define cbit_length  320      /* Length of the cbits table */
3777 -
3778 -/* Offsets of the various tables from the base tables pointer, and
3779 -total length. */
3780 -
3781 -#define lcc_offset      0
3782 -#define fcc_offset    256
3783 -#define cbits_offset  512
3784 -#define ctypes_offset (cbits_offset + cbit_length)
3785 -#define tables_length (ctypes_offset + 256)
3786 -
3787 -/* End of internal.h */
3788
3789 === removed file 'parser/pcre/pcre.c'
3790 --- parser/pcre/pcre.c  2006-04-11 21:52:54 +0000
3791 +++ parser/pcre/pcre.c  1970-01-01 00:00:00 +0000
3792 @@ -1,5187 +0,0 @@
3793 -/*************************************************
3794 -*      Perl-Compatible Regular Expressions       *
3795 -*************************************************/
3796 -
3797 -/*
3798 -This is a library of functions to support regular expressions whose syntax
3799 -and semantics are as close as possible to those of the Perl 5 language. See
3800 -the file Tech.Notes for some information on the internals.
3801 -
3802 -Written by: Philip Hazel <ph10@cam.ac.uk>
3803 -
3804 -           Copyright (c) 1997-2001 University of Cambridge
3805 -
3806 ------------------------------------------------------------------------------
3807 -Permission is granted to anyone to use this software for any purpose on any
3808 -computer system, and to redistribute it freely, subject to the following
3809 -restrictions:
3810 -
3811 -1. This software is distributed in the hope that it will be useful,
3812 -   but WITHOUT ANY WARRANTY; without even the implied warranty of
3813 -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
3814 -
3815 -2. The origin of this software must not be misrepresented, either by
3816 -   explicit claim or by omission.
3817 -
3818 -3. Altered versions must be plainly marked as such, and must not be
3819 -   misrepresented as being the original software.
3820 -
3821 -4. If PCRE is embedded in any software that is released under the GNU
3822 -   General Purpose Licence (GPL), then the terms of that licence shall
3823 -   supersede any condition above with which it is incompatible.
3824 ------------------------------------------------------------------------------
3825 -*/
3826 -
3827 -
3828 -/* Define DEBUG to get debugging output on stdout. */
3829 -
3830 -/* #define DEBUG */
3831 -
3832 -/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef
3833 -inline, and there are *still* stupid compilers about that don't like indented
3834 -pre-processor statements. I suppose it's only been 10 years... */
3835 -
3836 -#ifdef DEBUG
3837 -#define DPRINTF(p) printf p
3838 -#else
3839 -#define DPRINTF(p) /*nothing*/
3840 -#endif
3841 -
3842 -/* Include the internals header, which itself includes Standard C headers plus
3843 -the external pcre header. */
3844 -
3845 -#include "internal.h"
3846 -
3847 -
3848 -/* Allow compilation as C++ source code, should anybody want to do that. */
3849 -
3850 -#ifdef __cplusplus
3851 -#define class pcre_class
3852 -#endif
3853 -
3854 -
3855 -/* Maximum number of items on the nested bracket stacks at compile time. This
3856 -applies to the nesting of all kinds of parentheses. It does not limit
3857 -un-nested, non-capturing parentheses. This number can be made bigger if
3858 -necessary - it is used to dimension one int and one unsigned char vector at
3859 -compile time. */
3860 -
3861 -#define BRASTACK_SIZE 200
3862 -
3863 -
3864 -/* The number of bytes in a literal character string above which we can't add
3865 -any more is different when UTF-8 characters may be encountered. */
3866 -
3867 -#ifdef SUPPORT_UTF8
3868 -#define MAXLIT 250
3869 -#else
3870 -#define MAXLIT 255
3871 -#endif
3872 -
3873 -
3874 -/* Min and max values for the common repeats; for the maxima, 0 => infinity */
3875 -
3876 -static const char rep_min[] = { 0, 0, 1, 1, 0, 0 };
3877 -static const char rep_max[] = { 0, 0, 0, 0, 1, 1 };
3878 -
3879 -/* Text forms of OP_ values and things, for debugging (not all used) */
3880 -
3881 -#ifdef DEBUG
3882 -static const char *OP_names[] = {
3883 -  "End", "\\A", "\\B", "\\b", "\\D", "\\d",
3884 -  "\\S", "\\s", "\\W", "\\w", "\\Z", "\\z",
3885 -  "Opt", "^", "$", "Any", "chars", "not",
3886 -  "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
3887 -  "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
3888 -  "*", "*?", "+", "+?", "?", "??", "{", "{", "{",
3889 -  "*", "*?", "+", "+?", "?", "??", "{", "{",
3890 -  "class", "Ref", "Recurse",
3891 -  "Alt", "Ket", "KetRmax", "KetRmin", "Assert", "Assert not",
3892 -  "AssertB", "AssertB not", "Reverse", "Once", "Cond", "Cref",
3893 -  "Brazero", "Braminzero", "Branumber", "Bra"
3894 -};
3895 -#endif
3896 -
3897 -/* Table for handling escaped characters in the range '0'-'z'. Positive returns
3898 -are simple data values; negative values are for special things like \d and so
3899 -on. Zero means further processing is needed (for things like \x), or the escape
3900 -is invalid. */
3901 -
3902 -static const short int escapes[] = {
3903 -    0,      0,      0,      0,      0,      0,      0,      0,   /* 0 - 7 */
3904 -    0,      0,    ':',    ';',    '<',    '=',    '>',    '?',   /* 8 - ? */
3905 -  '@', -ESC_A, -ESC_B,      0, -ESC_D,      0,      0,      0,   /* @ - G */
3906 -    0,      0,      0,      0,      0,      0,      0,      0,   /* H - O */
3907 -    0,      0,      0, -ESC_S,      0,      0,      0, -ESC_W,   /* P - W */
3908 -    0,      0, -ESC_Z,    '[',   '\\',    ']',    '^',    '_',   /* X - _ */
3909 -  '`',      7, -ESC_b,      0, -ESC_d,  ESC_E,  ESC_F,      0,   /* ` - g */
3910 -    0,      0,      0,      0,      0,      0,  ESC_N,      0,   /* h - o */
3911 -    0,      0,  ESC_R, -ESC_s,  ESC_T,      0,      0, -ESC_w,   /* p - w */
3912 -    0,      0, -ESC_z                                            /* x - z */
3913 -};
3914 -
3915 -/* Tables of names of POSIX character classes and their lengths. The list is
3916 -terminated by a zero length entry. The first three must be alpha, upper, lower,
3917 -as this is assumed for handling case independence. */
3918 -
3919 -static const char *posix_names[] = {
3920 -  "alpha", "lower", "upper",
3921 -  "alnum", "ascii", "cntrl", "digit", "graph",
3922 -  "print", "punct", "space", "word",  "xdigit" };
3923 -
3924 -static const uschar posix_name_lengths[] = {
3925 -  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 };
3926 -
3927 -/* Table of class bit maps for each POSIX class; up to three may be combined
3928 -to form the class. */
3929 -
3930 -static const int posix_class_maps[] = {
3931 -  cbit_lower, cbit_upper, -1,             /* alpha */
3932 -  cbit_lower, -1,         -1,             /* lower */
3933 -  cbit_upper, -1,         -1,             /* upper */
3934 -  cbit_digit, cbit_lower, cbit_upper,     /* alnum */
3935 -  cbit_print, cbit_cntrl, -1,             /* ascii */
3936 -  cbit_cntrl, -1,         -1,             /* cntrl */
3937 -  cbit_digit, -1,         -1,             /* digit */
3938 -  cbit_graph, -1,         -1,             /* graph */
3939 -  cbit_print, -1,         -1,             /* print */
3940 -  cbit_punct, -1,         -1,             /* punct */
3941 -  cbit_space, -1,         -1,             /* space */
3942 -  cbit_word,  -1,         -1,             /* word */
3943 -  cbit_xdigit,-1,         -1              /* xdigit */
3944 -};
3945 -
3946 -
3947 -/* Definition to allow mutual recursion */
3948 -
3949 -static BOOL
3950 -  compile_regex(int, int, int *, uschar **, const uschar **, const char **,
3951 -    BOOL, int, int *, int *, compile_data *);
3952 -
3953 -/* Structure for building a chain of data that actually lives on the
3954 -stack, for holding the values of the subject pointer at the start of each
3955 -subpattern, so as to detect when an empty string has been matched by a
3956 -subpattern - to break infinite loops. */
3957 -
3958 -typedef struct eptrblock {
3959 -  struct eptrblock *prev;
3960 -  const uschar *saved_eptr;
3961 -} eptrblock;
3962 -
3963 -/* Flag bits for the match() function */
3964 -
3965 -#define match_condassert   0x01    /* Called to check a condition assertion */
3966 -#define match_isgroup      0x02    /* Set if start of bracketed group */
3967 -
3968 -
3969 -
3970 -/*************************************************
3971 -*               Global variables                 *
3972 -*************************************************/
3973 -
3974 -/* PCRE is thread-clean and doesn't use any global variables in the normal
3975 -sense. However, it calls memory allocation and free functions via the two
3976 -indirections below, which are can be changed by the caller, but are shared
3977 -between all threads. */
3978 -
3979 -void *(*pcre_malloc)(size_t) = malloc;
3980 -void  (*pcre_free)(void *) = free;
3981 -
3982 -
3983 -
3984 -/*************************************************
3985 -*    Macros and tables for character handling    *
3986 -*************************************************/
3987 -
3988 -/* When UTF-8 encoding is being used, a character is no longer just a single
3989 -byte. The macros for character handling generate simple sequences when used in
3990 -byte-mode, and more complicated ones for UTF-8 characters. */
3991 -
3992 -#ifndef SUPPORT_UTF8
3993 -#define GETCHARINC(c, eptr) c = *eptr++;
3994 -#define GETCHARLEN(c, eptr, len) c = *eptr;
3995 -#define BACKCHAR(eptr)
3996 -
3997 -#else   /* SUPPORT_UTF8 */
3998 -
3999 -/* Get the next UTF-8 character, advancing the pointer */
4000 -
4001 -#define GETCHARINC(c, eptr) \
4002 -  c = *eptr++; \
4003 -  if (md->utf8 && (c & 0xc0) == 0xc0) \
4004 -    { \
4005 -    int a = utf8_table4[c & 0x3f];  /* Number of additional bytes */ \
4006 -    int s = 6*a; \
4007 -    c = (c & utf8_table3[a]) << s; \
4008 -    while (a-- > 0) \
4009 -      { \
4010 -      s -= 6; \
4011 -      c |= (*eptr++ & 0x3f) << s; \
4012 -      } \
4013 -    }
4014 -
4015 -/* Get the next UTF-8 character, not advancing the pointer, setting length */
4016 -
4017 -#define GETCHARLEN(c, eptr, len) \
4018 -  c = *eptr; \
4019 -  len = 1; \
4020 -  if (md->utf8 && (c & 0xc0) == 0xc0) \
4021 -    { \
4022 -    int i; \
4023 -    int a = utf8_table4[c & 0x3f];  /* Number of additional bytes */ \
4024 -    int s = 6*a; \
4025 -    c = (c & utf8_table3[a]) << s; \
4026 -    for (i = 1; i <= a; i++) \
4027 -      { \
4028 -      s -= 6; \
4029 -      c |= (eptr[i] & 0x3f) << s; \
4030 -      } \
4031 -    len += a; \
4032 -    }
4033 -
4034 -/* If the pointer is not at the start of a character, move it back until
4035 -it is. */
4036 -
4037 -#define BACKCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr--;
4038 -
4039 -#endif
4040 -
4041 -
4042 -
4043 -/*************************************************
4044 -*             Default character tables           *
4045 -*************************************************/
4046 -
4047 -/* A default set of character tables is included in the PCRE binary. Its source
4048 -is built by the maketables auxiliary program, which uses the default C ctypes
4049 -functions, and put in the file chartables.c. These tables are used by PCRE
4050 -whenever the caller of pcre_compile() does not provide an alternate set of
4051 -tables. */
4052 -
4053 -#include "chartables.c"
4054 -
4055 -
4056 -
4057 -#ifdef SUPPORT_UTF8
4058 -/*************************************************
4059 -*           Tables for UTF-8 support             *
4060 -*************************************************/
4061 -
4062 -/* These are the breakpoints for different numbers of bytes in a UTF-8
4063 -character. */
4064 -
4065 -static int utf8_table1[] = { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
4066 -
4067 -/* These are the indicator bits and the mask for the data bits to set in the
4068 -first byte of a character, indexed by the number of additional bytes. */
4069 -
4070 -static int utf8_table2[] = { 0,    0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
4071 -static int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
4072 -
4073 -/* Table of the number of extra characters, indexed by the first character
4074 -masked with 0x3f. The highest number for a valid UTF-8 character is in fact
4075 -0x3d. */
4076 -
4077 -static uschar utf8_table4[] = {
4078 -  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
4079 -  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
4080 -  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
4081 -  3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
4082 -
4083 -
4084 -/*************************************************
4085 -*       Convert character value to UTF-8         *
4086 -*************************************************/
4087 -
4088 -/* This function takes an integer value in the range 0 - 0x7fffffff
4089 -and encodes it as a UTF-8 character in 0 to 6 bytes.
4090 -
4091 -Arguments:
4092 -  cvalue     the character value
4093 -  buffer     pointer to buffer for result - at least 6 bytes long
4094 -
4095 -Returns:     number of characters placed in the buffer
4096 -*/
4097 -
4098 -static int
4099 -ord2utf8(int cvalue, uschar *buffer)
4100 -{
4101 -register int i, j;
4102 -for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++)
4103 -  if (cvalue <= utf8_table1[i]) break;
4104 -buffer += i;
4105 -for (j = i; j > 0; j--)
4106 - {
4107 - *buffer-- = 0x80 | (cvalue & 0x3f);
4108 - cvalue >>= 6;
4109 - }
4110 -*buffer = utf8_table2[i] | cvalue;
4111 -return i + 1;
4112 -}
4113 -#endif
4114 -
4115 -
4116 -
4117 -/*************************************************
4118 -*          Return version string                 *
4119 -*************************************************/
4120 -
4121 -#define STRING(a)  # a
4122 -#define XSTRING(s) STRING(s)
4123 -
4124 -const char *
4125 -pcre_version(void)
4126 -{
4127 -return XSTRING(PCRE_MAJOR) "." XSTRING(PCRE_MINOR) " " XSTRING(PCRE_DATE);
4128 -}
4129 -
4130 -
4131 -
4132 -
4133 -/*************************************************
4134 -* (Obsolete) Return info about compiled pattern  *
4135 -*************************************************/
4136 -
4137 -/* This is the original "info" function. It picks potentially useful data out
4138 -of the private structure, but its interface was too rigid. It remains for
4139 -backwards compatibility. The public options are passed back in an int - though
4140 -the re->options field has been expanded to a long int, all the public options
4141 -at the low end of it, and so even on 16-bit systems this will still be OK.
4142 -Therefore, I haven't changed the API for pcre_info().
4143 -
4144 -Arguments:
4145 -  external_re   points to compiled code
4146 -  optptr        where to pass back the options
4147 -  first_char    where to pass back the first character,
4148 -                or -1 if multiline and all branches start ^,
4149 -                or -2 otherwise
4150 -
4151 -Returns:        number of capturing subpatterns
4152 -                or negative values on error
4153 -*/
4154 -
4155 -int
4156 -pcre_info(const pcre *external_re, int *optptr, int *first_char)
4157 -{
4158 -const real_pcre *re = (const real_pcre *)external_re;
4159 -if (re == NULL) return PCRE_ERROR_NULL;
4160 -if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
4161 -if (optptr != NULL) *optptr = (int)(re->options & PUBLIC_OPTIONS);
4162 -if (first_char != NULL)
4163 -  *first_char = ((re->options & PCRE_FIRSTSET) != 0)? re->first_char :
4164 -     ((re->options & PCRE_STARTLINE) != 0)? -1 : -2;
4165 -return re->top_bracket;
4166 -}
4167 -
4168 -
4169 -
4170 -/*************************************************
4171 -*        Return info about compiled pattern      *
4172 -*************************************************/
4173 -
4174 -/* This is a newer "info" function which has an extensible interface so
4175 -that additional items can be added compatibly.
4176 -
4177 -Arguments:
4178 -  external_re      points to compiled code
4179 -  external_study   points to study data, or NULL
4180 -  what             what information is required
4181 -  where            where to put the information
4182 -
4183 -Returns:           0 if data returned, negative on error
4184 -*/
4185 -
4186 -int
4187 -pcre_fullinfo(const pcre *external_re, const pcre_extra *study_data, int what,
4188 -  void *where)
4189 -{
4190 -const real_pcre *re = (const real_pcre *)external_re;
4191 -const real_pcre_extra *study = (const real_pcre_extra *)study_data;
4192 -
4193 -if (re == NULL || where == NULL) return PCRE_ERROR_NULL;
4194 -if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
4195 -
4196 -switch (what)
4197 -  {
4198 -  case PCRE_INFO_OPTIONS:
4199 -  *((unsigned long int *)where) = re->options & PUBLIC_OPTIONS;
4200 -  break;
4201 -
4202 -  case PCRE_INFO_SIZE:
4203 -  *((size_t *)where) = re->size;
4204 -  break;
4205 -
4206 -  case PCRE_INFO_CAPTURECOUNT:
4207 -  *((int *)where) = re->top_bracket;
4208 -  break;
4209 -
4210 -  case PCRE_INFO_BACKREFMAX:
4211 -  *((int *)where) = re->top_backref;
4212 -  break;
4213 -
4214 -  case PCRE_INFO_FIRSTCHAR:
4215 -  *((int *)where) =
4216 -    ((re->options & PCRE_FIRSTSET) != 0)? re->first_char :
4217 -    ((re->options & PCRE_STARTLINE) != 0)? -1 : -2;
4218 -  break;
4219 -
4220 -  case PCRE_INFO_FIRSTTABLE:
4221 -  *((const uschar **)where) =
4222 -    (study != NULL && (study->options & PCRE_STUDY_MAPPED) != 0)?
4223 -      study->start_bits : NULL;
4224 -  break;
4225 -
4226 -  case PCRE_INFO_LASTLITERAL:
4227 -  *((int *)where) =
4228 -    ((re->options & PCRE_REQCHSET) != 0)? re->req_char : -1;
4229 -  break;
4230 -
4231 -  default: return PCRE_ERROR_BADOPTION;
4232 -  }
4233 -
4234 -return 0;
4235 -}
4236 -
4237 -
4238 -
4239 -#ifdef DEBUG
4240 -/*************************************************
4241 -*        Debugging function to print chars       *
4242 -*************************************************/
4243 -
4244 -/* Print a sequence of chars in printable format, stopping at the end of the
4245 -subject if the requested.
4246 -
4247 -Arguments:
4248 -  p           points to characters
4249 -  length      number to print
4250 -  is_subject  TRUE if printing from within md->start_subject
4251 -  md          pointer to matching data block, if is_subject is TRUE
4252 -
4253 -Returns:     nothing
4254 -*/
4255 -
4256 -static void
4257 -pchars(const uschar *p, int length, BOOL is_subject, match_data *md)
4258 -{
4259 -int c;
4260 -if (is_subject && length > md->end_subject - p) length = md->end_subject - p;
4261 -while (length-- > 0)
4262 -  if (isprint(c = *(p++))) printf("%c", c); else printf("\\x%02x", c);
4263 -}
4264 -#endif
4265 -
4266 -
4267 -
4268 -
4269 -/*************************************************
4270 -*            Handle escapes                      *
4271 -*************************************************/
4272 -
4273 -/* This function is called when a \ has been encountered. It either returns a
4274 -positive value for a simple escape such as \n, or a negative value which
4275 -encodes one of the more complicated things such as \d. When UTF-8 is enabled,
4276 -a positive value greater than 255 may be returned. On entry, ptr is pointing at
4277 -the \. On exit, it is on the final character of the escape sequence.
4278 -
4279 -Arguments:
4280 -  ptrptr     points to the pattern position pointer
4281 -  errorptr   points to the pointer to the error message
4282 -  bracount   number of previous extracting brackets
4283 -  options    the options bits
4284 -  isclass    TRUE if inside a character class
4285 -  cd         pointer to char tables block
4286 -
4287 -Returns:     zero or positive => a data character
4288 -             negative => a special escape sequence
4289 -             on error, errorptr is set
4290 -*/
4291 -
4292 -static int
4293 -check_escape(const uschar **ptrptr, const char **errorptr, int bracount,
4294 -  int options, BOOL isclass, compile_data *cd)
4295 -{
4296 -const uschar *ptr = *ptrptr;
4297 -int c, i;
4298 -
4299 -/* If backslash is at the end of the pattern, it's an error. */
4300 -
4301 -c = *(++ptr);
4302 -if (c == 0) *errorptr = ERR1;
4303 -
4304 -/* Digits or letters may have special meaning; all others are literals. */
4305 -
4306 -else if (c < '0' || c > 'z') {}
4307 -
4308 -/* Do an initial lookup in a table. A non-zero result is something that can be
4309 -returned immediately. Otherwise further processing may be required. */
4310 -
4311 -else if ((i = escapes[c - '0']) != 0) c = i;
4312 -
4313 -/* Escapes that need further processing, or are illegal. */
4314 -
4315 -else
4316 -  {
4317 -  const uschar *oldptr;
4318 -  switch (c)
4319 -    {
4320 -    /* The handling of escape sequences consisting of a string of digits
4321 -    starting with one that is not zero is not straightforward. By experiment,
4322 -    the way Perl works seems to be as follows:
4323 -
4324 -    Outside a character class, the digits are read as a decimal number. If the
4325 -    number is less than 10, or if there are that many previous extracting
4326 -    left brackets, then it is a back reference. Otherwise, up to three octal
4327 -    digits are read to form an escaped byte. Thus \123 is likely to be octal
4328 -    123 (cf \0123, which is octal 012 followed by the literal 3). If the octal
4329 -    value is greater than 377, the least significant 8 bits are taken. Inside a
4330 -    character class, \ followed by a digit is always an octal number. */
4331 -
4332 -    case '1': case '2': case '3': case '4': case '5':
4333 -    case '6': case '7': case '8': case '9':
4334 -
4335 -    if (!isclass)
4336 -      {
4337 -      oldptr = ptr;
4338 -      c -= '0';
4339 -      while ((cd->ctypes[ptr[1]] & ctype_digit) != 0)
4340 -        c = c * 10 + *(++ptr) - '0';
4341 -      if (c < 10 || c <= bracount)
4342 -        {
4343 -        c = -(ESC_REF + c);
4344 -        break;
4345 -        }
4346 -      ptr = oldptr;      /* Put the pointer back and fall through */
4347 -      }
4348 -
4349 -    /* Handle an octal number following \. If the first digit is 8 or 9, Perl
4350 -    generates a binary zero byte and treats the digit as a following literal.
4351 -    Thus we have to pull back the pointer by one. */
4352 -
4353 -    if ((c = *ptr) >= '8')
4354 -      {
4355 -      ptr--;
4356 -      c = 0;
4357 -      break;
4358 -      }
4359 -
4360 -    /* \0 always starts an octal number, but we may drop through to here with a
4361 -    larger first octal digit. */
4362 -
4363 -    case '0':
4364 -    c -= '0';
4365 -    while(i++ < 2 && (cd->ctypes[ptr[1]] & ctype_digit) != 0 &&
4366 -      ptr[1] != '8' && ptr[1] != '9')
4367 -        c = c * 8 + *(++ptr) - '0';
4368 -    c &= 255;     /* Take least significant 8 bits */
4369 -    break;
4370 -
4371 -    /* \x is complicated when UTF-8 is enabled. \x{ddd} is a character number
4372 -    which can be greater than 0xff, but only if the ddd are hex digits. */
4373 -
4374 -    case 'x':
4375 -#ifdef SUPPORT_UTF8
4376 -    if (ptr[1] == '{' && (options & PCRE_UTF8) != 0)
4377 -      {
4378 -      const uschar *pt = ptr + 2;
4379 -      register int count = 0;
4380 -      c = 0;
4381 -      while ((cd->ctypes[*pt] & ctype_xdigit) != 0)
4382 -        {
4383 -        count++;
4384 -        c = c * 16 + cd->lcc[*pt] -
4385 -          (((cd->ctypes[*pt] & ctype_digit) != 0)? '0' : 'W');
4386 -        pt++;
4387 -        }
4388 -      if (*pt == '}')
4389 -        {
4390 -        if (c < 0 || count > 8) *errorptr = ERR34;
4391 -        ptr = pt;
4392 -        break;
4393 -        }
4394 -      /* If the sequence of hex digits does not end with '}', then we don't
4395 -      recognize this construct; fall through to the normal \x handling. */
4396 -      }
4397 -#endif
4398 -
4399 -    /* Read just a single hex char */
4400 -
4401 -    c = 0;
4402 -    while (i++ < 2 && (cd->ctypes[ptr[1]] & ctype_xdigit) != 0)
4403 -      {
4404 -      ptr++;
4405 -      c = c * 16 + cd->lcc[*ptr] -
4406 -        (((cd->ctypes[*ptr] & ctype_digit) != 0)? '0' : 'W');
4407 -      }
4408 -    break;
4409 -
4410 -    /* Other special escapes not starting with a digit are straightforward */
4411 -
4412 -    case 'c':
4413 -    c = *(++ptr);
4414 -    if (c == 0)
4415 -      {
4416 -      *errorptr = ERR2;
4417 -      return 0;
4418 -      }
4419 -
4420 -    /* A letter is upper-cased; then the 0x40 bit is flipped */
4421 -
4422 -    if (c >= 'a' && c <= 'z') c = cd->fcc[c];
4423 -    c ^= 0x40;
4424 -    break;
4425 -
4426 -    /* PCRE_EXTRA enables extensions to Perl in the matter of escapes. Any
4427 -    other alphameric following \ is an error if PCRE_EXTRA was set; otherwise,
4428 -    for Perl compatibility, it is a literal. This code looks a bit odd, but
4429 -    there used to be some cases other than the default, and there may be again
4430 -    in future, so I haven't "optimized" it. */
4431 -
4432 -    default:
4433 -    if ((options & PCRE_EXTRA) != 0) switch(c)
4434 -      {
4435 -      default:
4436 -      *errorptr = ERR3;
4437 -      break;
4438 -      }
4439 -    break;
4440 -    }
4441 -  }
4442 -
4443 -*ptrptr = ptr;
4444 -return c;
4445 -}
4446 -
4447 -
4448 -
4449 -/*************************************************
4450 -*            Check for counted repeat            *
4451 -*************************************************/
4452 -
4453 -/* This function is called when a '{' is encountered in a place where it might
4454 -start a quantifier. It looks ahead to see if it really is a quantifier or not.
4455 -It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd}
4456 -where the ddds are digits.
4457 -
4458 -Arguments:
4459 -  p         pointer to the first char after '{'
4460 -  cd        pointer to char tables block
4461 -
4462 -Returns:    TRUE or FALSE
4463 -*/
4464 -
4465 -static BOOL
4466 -is_counted_repeat(const uschar *p, compile_data *cd)
4467 -{
4468 -if ((cd->ctypes[*p++] & ctype_digit) == 0) return FALSE;
4469 -while ((cd->ctypes[*p] & ctype_digit) != 0) p++;
4470 -if (*p == '}') return TRUE;
4471 -
4472 -if (*p++ != ',') return FALSE;
4473 -if (*p == '}') return TRUE;
4474 -
4475 -if ((cd->ctypes[*p++] & ctype_digit) == 0) return FALSE;
4476 -while ((cd->ctypes[*p] & ctype_digit) != 0) p++;
4477 -return (*p == '}');
4478 -}
4479 -
4480 -
4481 -
4482 -/*************************************************
4483 -*         Read repeat counts                     *
4484 -*************************************************/
4485 -
4486 -/* Read an item of the form {n,m} and return the values. This is called only
4487 -after is_counted_repeat() has confirmed that a repeat-count quantifier exists,
4488 -so the syntax is guaranteed to be correct, but we need to check the values.
4489 -
4490 -Arguments:
4491 -  p          pointer to first char after '{'
4492 -  minp       pointer to int for min
4493 -  maxp       pointer to int for max
4494 -             returned as -1 if no max
4495 -  errorptr   points to pointer to error message
4496 -  cd         pointer to character tables clock
4497 -
4498 -Returns:     pointer to '}' on success;
4499 -             current ptr on error, with errorptr set
4500 -*/
4501 -
4502 -static const uschar *
4503 -read_repeat_counts(const uschar *p, int *minp, int *maxp,
4504 -  const char **errorptr, compile_data *cd)
4505 -{
4506 -int min = 0;
4507 -int max = -1;
4508 -
4509 -/* Read the minimum value and do a paranoid check: a negative value indicates
4510 -an integer overflow. */
4511 -
4512 -while ((cd->ctypes[*p] & ctype_digit) != 0) min = min * 10 + *p++ - '0';
4513 -
4514 -if (min < 0 || min > 65535) {
4515 -  *errorptr = ERR5;
4516 -  return p;
4517 -}
4518 -/* Read the maximum value if there is one, and again do a paranoid on its size.
4519 -Also, max must not be less than min. */
4520 -
4521 -if (*p == '}') max = min; else
4522 -  {
4523 -  if (*(++p) != '}')
4524 -    {
4525 -    max = 0;
4526 -    while((cd->ctypes[*p] & ctype_digit) != 0) max = max * 10 + *p++ - '0';
4527 -    if (max < 0 || max > 65535)
4528 -      {
4529 -      *errorptr = ERR5;
4530 -      return p;
4531 -      }
4532 -    if (max < min)
4533 -      {
4534 -      *errorptr = ERR4;
4535 -      return p;
4536 -      }
4537 -    }
4538 -  }
4539 -
4540 -/* Fill in the required variables, and pass back the pointer to the terminating
4541 -'}'. */
4542 -
4543 -*minp = min;
4544 -*maxp = max;
4545 -return p;
4546 -}
4547 -
4548 -
4549 -
4550 -/*************************************************
4551 -*        Find the fixed length of a pattern      *
4552 -*************************************************/
4553 -
4554 -/* Scan a pattern and compute the fixed length of subject that will match it,
4555 -if the length is fixed. This is needed for dealing with backward assertions.
4556 -
4557 -Arguments:
4558 -  code     points to the start of the pattern (the bracket)
4559 -  options  the compiling options
4560 -
4561 -Returns:   the fixed length, or -1 if there is no fixed length
4562 -*/
4563 -
4564 -static int
4565 -find_fixedlength(uschar *code, int options)
4566 -{
4567 -int length = -1;
4568 -
4569 -register int branchlength = 0;
4570 -register uschar *cc = code + 3;
4571 -
4572 -/* Scan along the opcodes for this branch. If we get to the end of the
4573 -branch, check the length against that of the other branches. */
4574 -
4575 -for (;;)
4576 -  {
4577 -  int d;
4578 -  register int op = *cc;
4579 -  if (op >= OP_BRA) op = OP_BRA;
4580 -
4581 -  switch (op)
4582 -    {
4583 -    case OP_BRA:
4584 -    case OP_ONCE:
4585 -    case OP_COND:
4586 -    d = find_fixedlength(cc, options);
4587 -    if (d < 0) return -1;
4588 -    branchlength += d;
4589 -    do cc += (cc[1] << 8) + cc[2]; while (*cc == OP_ALT);
4590 -    cc += 3;
4591 -    break;
4592 -
4593 -    /* Reached end of a branch; if it's a ket it is the end of a nested
4594 -    call. If it's ALT it is an alternation in a nested call. If it is
4595 -    END it's the end of the outer call. All can be handled by the same code. */
4596 -
4597 -    case OP_ALT:
4598 -    case OP_KET:
4599 -    case OP_KETRMAX:
4600 -    case OP_KETRMIN:
4601 -    case OP_END:
4602 -    if (length < 0) length = branchlength;
4603 -      else if (length != branchlength) return -1;
4604 -    if (*cc != OP_ALT) return length;
4605 -    cc += 3;
4606 -    branchlength = 0;
4607 -    break;
4608 -
4609 -    /* Skip over assertive subpatterns */
4610 -
4611 -    case OP_ASSERT:
4612 -    case OP_ASSERT_NOT:
4613 -    case OP_ASSERTBACK:
4614 -    case OP_ASSERTBACK_NOT:
4615 -    do cc += (cc[1] << 8) + cc[2]; while (*cc == OP_ALT);
4616 -    cc += 3;
4617 -    break;
4618 -
4619 -    /* Skip over things that don't match chars */
4620 -
4621 -    case OP_REVERSE:
4622 -    case OP_BRANUMBER:
4623 -    case OP_CREF:
4624 -    cc++;
4625 -    /* Fall through */
4626 -
4627 -    case OP_OPT:
4628 -    cc++;
4629 -    /* Fall through */
4630 -
4631 -    case OP_SOD:
4632 -    case OP_EOD:
4633 -    case OP_EODN:
4634 -    case OP_CIRC:
4635 -    case OP_DOLL:
4636 -    case OP_NOT_WORD_BOUNDARY:
4637 -    case OP_WORD_BOUNDARY:
4638 -    cc++;
4639 -    break;
4640 -
4641 -    /* Handle char strings. In UTF-8 mode we must count characters, not bytes.
4642 -    This requires a scan of the string, unfortunately. We assume valid UTF-8
4643 -    strings, so all we do is reduce the length by one for byte whose bits are
4644 -    10xxxxxx. */
4645 -
4646 -    case OP_CHARS:
4647 -    branchlength += *(++cc);
4648 -#ifdef SUPPORT_UTF8
4649 -    for (d = 1; d <= *cc; d++)
4650 -      if ((cc[d] & 0xc0) == 0x80) branchlength--;
4651 -#endif
4652 -    cc += *cc + 1;
4653 -    break;
4654 -
4655 -    /* Handle exact repetitions */
4656 -
4657 -    case OP_EXACT:
4658 -    case OP_TYPEEXACT:
4659 -    branchlength += (cc[1] << 8) + cc[2];
4660 -    cc += 4;
4661 -    break;
4662 -
4663 -    /* Handle single-char matchers */
4664 -
4665 -    case OP_NOT_DIGIT:
4666 -    case OP_DIGIT:
4667 -    case OP_NOT_WHITESPACE:
4668 -    case OP_WHITESPACE:
4669 -    case OP_NOT_WORDCHAR:
4670 -    case OP_WORDCHAR:
4671 -    case OP_ANY:
4672 -    branchlength++;
4673 -    cc++;
4674 -    break;
4675 -
4676 -
4677 -    /* Check a class for variable quantification */
4678 -
4679 -    case OP_CLASS:
4680 -    cc += 33;
4681 -
4682 -    switch (*cc)
4683 -      {
4684 -      case OP_CRSTAR:
4685 -      case OP_CRMINSTAR:
4686 -      case OP_CRQUERY:
4687 -      case OP_CRMINQUERY:
4688 -      return -1;
4689 -
4690 -      case OP_CRRANGE:
4691 -      case OP_CRMINRANGE:
4692 -      if ((cc[1] << 8) + cc[2] != (cc[3] << 8) + cc[4]) return -1;
4693 -      branchlength += (cc[1] << 8) + cc[2];
4694 -      cc += 5;
4695 -      break;
4696 -
4697 -      default:
4698 -      branchlength++;
4699 -      }
4700 -    break;
4701 -
4702 -    /* Anything else is variable length */
4703 -
4704 -    default:
4705 -    return -1;
4706 -    }
4707 -  }
4708 -/* Control never gets here */
4709 -}
4710 -
4711 -
4712 -
4713 -
4714 -/*************************************************
4715 -*           Check for POSIX class syntax         *
4716 -*************************************************/
4717 -
4718 -/* This function is called when the sequence "[:" or "[." or "[=" is
4719 -encountered in a character class. It checks whether this is followed by an
4720 -optional ^ and then a sequence of letters, terminated by a matching ":]" or
4721 -".]" or "=]".
4722 -
4723 -Argument:
4724 -  ptr      pointer to the initial [
4725 -  endptr   where to return the end pointer
4726 -  cd       pointer to compile data
4727 -
4728 -Returns:   TRUE or FALSE
4729 -*/
4730 -
4731 -static BOOL
4732 -check_posix_syntax(const uschar *ptr, const uschar **endptr, compile_data *cd)
4733 -{
4734 -int terminator;          /* Don't combine these lines; the Solaris cc */
4735 -terminator = *(++ptr);   /* compiler warns about "non-constant" initializer. */
4736 -if (*(++ptr) == '^') ptr++;
4737 -while ((cd->ctypes[*ptr] & ctype_letter) != 0) ptr++;
4738 -if (*ptr == terminator && ptr[1] == ']')
4739 -  {
4740 -  *endptr = ptr;
4741 -  return TRUE;
4742 -  }
4743 -return FALSE;
4744 -}
4745 -
4746 -
4747 -
4748 -
4749 -/*************************************************
4750 -*          Check POSIX class name                *
4751 -*************************************************/
4752 -
4753 -/* This function is called to check the name given in a POSIX-style class entry
4754 -such as [:alnum:].
4755 -
4756 -Arguments:
4757 -  ptr        points to the first letter
4758 -  len        the length of the name
4759 -
4760 -Returns:     a value representing the name, or -1 if unknown
4761 -*/
4762 -
4763 -static int
4764 -check_posix_name(const uschar *ptr, int len)
4765 -{
4766 -register int yield = 0;
4767 -while (posix_name_lengths[yield] != 0)
4768 -  {
4769 -  if (len == posix_name_lengths[yield] &&
4770 -    strncmp((const char *)ptr, posix_names[yield], len) == 0) return yield;
4771 -  yield++;
4772 -  }
4773 -return -1;
4774 -}
4775 -
4776 -
4777 -
4778 -
4779 -/*************************************************
4780 -*           Compile one branch                   *
4781 -*************************************************/
4782 -
4783 -/* Scan the pattern, compiling it into the code vector.
4784 -
4785 -Arguments:
4786 -  options      the option bits
4787 -  brackets     points to number of extracting brackets used
4788 -  code         points to the pointer to the current code point
4789 -  ptrptr       points to the current pattern pointer
4790 -  errorptr     points to pointer to error message
4791 -  optchanged   set to the value of the last OP_OPT item compiled
4792 -  reqchar      set to the last literal character required, else -1
4793 -  countlits    set to count of mandatory literal characters
4794 -  cd           contains pointers to tables
4795 -
4796 -Returns:       TRUE on success
4797 -               FALSE, with *errorptr set on error
4798 -*/
4799 -
4800 -static BOOL
4801 -compile_branch(int options, int *brackets, uschar **codeptr,
4802 -  const uschar **ptrptr, const char **errorptr, int *optchanged,
4803 -  int *reqchar, int *countlits, compile_data *cd)
4804 -{
4805 -int repeat_type, op_type;
4806 -int repeat_min, repeat_max;
4807 -int bravalue, length;
4808 -int greedy_default, greedy_non_default;
4809 -int prevreqchar;
4810 -int condcount = 0;
4811 -int subcountlits = 0;
4812 -register int c;
4813 -register uschar *code = *codeptr;
4814 -uschar *tempcode;
4815 -const uschar *ptr = *ptrptr;
4816 -const uschar *tempptr;
4817 -uschar *previous = NULL;
4818 -uschar class[32];
4819 -
4820 -/* Set up the default and non-default settings for greediness */
4821 -
4822 -greedy_default = ((options & PCRE_UNGREEDY) != 0);
4823 -greedy_non_default = greedy_default ^ 1;
4824 -
4825 -/* Initialize no required char, and count of literals */
4826 -
4827 -*reqchar = prevreqchar = -1;
4828 -*countlits = 0;
4829 -
4830 -/* Switch on next character until the end of the branch */
4831 -
4832 -for (;; ptr++)
4833 -  {
4834 -  BOOL negate_class;
4835 -  int class_charcount;
4836 -  int class_lastchar;
4837 -  int newoptions;
4838 -  int skipbytes;
4839 -  int subreqchar;
4840 -
4841 -  c = *ptr;
4842 -  if ((options & PCRE_EXTENDED) != 0)
4843 -    {
4844 -    if ((cd->ctypes[c] & ctype_space) != 0) continue;
4845 -    if (c == '#')
4846 -      {
4847 -      /* The space before the ; is to avoid a warning on a silly compiler
4848 -      on the Macintosh. */
4849 -      while ((c = *(++ptr)) != 0 && c != NEWLINE) ;
4850 -      continue;
4851 -      }
4852 -    }
4853 -
4854 -  switch(c)
4855 -    {
4856 -    /* The branch terminates at end of string, |, or ). */
4857 -
4858 -    case 0:
4859 -    case '|':
4860 -    case ')':
4861 -    *codeptr = code;
4862 -    *ptrptr = ptr;
4863 -    return TRUE;
4864 -
4865 -    /* Handle single-character metacharacters */
4866 -
4867 -    case '^':
4868 -    previous = NULL;
4869 -    *code++ = OP_CIRC;
4870 -    break;
4871 -
4872 -    case '$':
4873 -    previous = NULL;
4874 -    *code++ = OP_DOLL;
4875 -    break;
4876 -
4877 -    case '.':
4878 -    previous = code;
4879 -    *code++ = OP_ANY;
4880 -    break;
4881 -
4882 -    /* Character classes. These always build a 32-byte bitmap of the permitted
4883 -    characters, except in the special case where there is only one character.
4884 -    For negated classes, we build the map as usual, then invert it at the end.
4885 -    */
4886 -
4887 -    case '[':
4888 -    previous = code;
4889 -    *code++ = OP_CLASS;
4890 -
4891 -    /* If the first character is '^', set the negation flag and skip it. */
4892 -
4893 -    if ((c = *(++ptr)) == '^')
4894 -      {
4895 -      negate_class = TRUE;
4896 -      c = *(++ptr);
4897 -      }
4898 -    else negate_class = FALSE;
4899 -
4900 -    /* Keep a count of chars so that we can optimize the case of just a single
4901 -    character. */
4902 -
4903 -    class_charcount = 0;
4904 -    class_lastchar = -1;
4905 -
4906 -    /* Initialize the 32-char bit map to all zeros. We have to build the
4907 -    map in a temporary bit of store, in case the class contains only 1
4908 -    character, because in that case the compiled code doesn't use the
4909 -    bit map. */
4910 -
4911 -    memset(class, 0, 32 * sizeof(uschar));
4912 -
4913 -    /* Process characters until ] is reached. By writing this as a "do" it
4914 -    means that an initial ] is taken as a data character. */
4915 -
4916 -    do
4917 -      {
4918 -      if (c == 0)
4919 -        {
4920 -        *errorptr = ERR6;
4921 -        goto FAILED;
4922 -        }
4923 -
4924 -      /* Handle POSIX class names. Perl allows a negation extension of the
4925 -      form [:^name]. A square bracket that doesn't match the syntax is
4926 -      treated as a literal. We also recognize the POSIX constructions
4927 -      [.ch.] and [=ch=] ("collating elements") and fault them, as Perl
4928 -      5.6 does. */
4929 -
4930 -      if (c == '[' &&
4931 -          (ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') &&
4932 -          check_posix_syntax(ptr, &tempptr, cd))
4933 -        {
4934 -        BOOL local_negate = FALSE;
4935 -        int posix_class, i;
4936 -        register const uschar *cbits = cd->cbits;
4937 -
4938 -        if (ptr[1] != ':')
4939 -          {
4940 -          *errorptr = ERR31;
4941 -          goto FAILED;
4942 -          }
4943 -
4944 -        ptr += 2;
4945 -        if (*ptr == '^')
4946 -          {
4947 -          local_negate = TRUE;
4948 -          ptr++;
4949 -          }
4950 -
4951 -        posix_class = check_posix_name(ptr, tempptr - ptr);
4952 -        if (posix_class < 0)
4953 -          {
4954 -          *errorptr = ERR30;
4955 -          goto FAILED;
4956 -          }
4957 -
4958 -        /* If matching is caseless, upper and lower are converted to
4959 -        alpha. This relies on the fact that the class table starts with
4960 -        alpha, lower, upper as the first 3 entries. */
4961 -
4962 -        if ((options & PCRE_CASELESS) != 0 && posix_class <= 2)
4963 -          posix_class = 0;
4964 -
4965 -        /* Or into the map we are building up to 3 of the static class
4966 -        tables, or their negations. */
4967 -
4968 -        posix_class *= 3;
4969 -        for (i = 0; i < 3; i++)
4970 -          {
4971 -          int taboffset = posix_class_maps[posix_class + i];
4972 -          if (taboffset < 0) break;
4973 -          if (local_negate)
4974 -            for (c = 0; c < 32; c++) class[c] |= ~cbits[c+taboffset];
4975 -          else
4976 -            for (c = 0; c < 32; c++) class[c] |= cbits[c+taboffset];
4977 -          }
4978 -
4979 -        ptr = tempptr + 1;
4980 -        class_charcount = 10;  /* Set > 1; assumes more than 1 per class */
4981 -        continue;
4982 -        }
4983 -
4984 -      /* Backslash may introduce a single character, or it may introduce one
4985 -      of the specials, which just set a flag. Escaped items are checked for
4986 -      validity in the pre-compiling pass. The sequence \b is a special case.
4987 -      Inside a class (and only there) it is treated as backspace. Elsewhere
4988 -      it marks a word boundary. Other escapes have preset maps ready to
4989 -      or into the one we are building. We assume they have more than one
4990 -      character in them, so set class_count bigger than one. */
4991 -
4992 -      if (c == '\\')
4993 -        {
4994 -        c = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd);
4995 -        if (-c == ESC_b) c = '\b';
4996 -        else if (c < 0)
4997 -          {
4998 -          register const uschar *cbits = cd->cbits;
4999 -          class_charcount = 10;
5000 -          switch (-c)
5001 -            {
5002 -            case ESC_d:
5003 -            for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_digit];
5004 -            continue;
5005 -
5006 -            case ESC_D:
5007 -            for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_digit];
5008 -            continue;
5009 -
5010 -            case ESC_w:
5011 -            for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_word];
5012 -            continue;
5013 -
5014 -            case ESC_W:
5015 -            for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_word];
5016 -            continue;
5017 -
5018 -            case ESC_s:
5019 -            for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_space];
5020 -            continue;
5021 -
5022 -            case ESC_S:
5023 -            for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_space];
5024 -            continue;
5025 -
5026 -            default:
5027 -            *errorptr = ERR7;
5028 -            goto FAILED;
5029 -            }
5030 -          }
5031 -
5032 -        /* Fall through if single character, but don't at present allow
5033 -        chars > 255 in UTF-8 mode. */
5034 -
5035 -#ifdef SUPPORT_UTF8
5036 -        if (c > 255)
5037 -          {
5038 -          *errorptr = ERR33;
5039 -          goto FAILED;
5040 -          }
5041 -#endif
5042 -        }
5043 -
5044 -      /* A single character may be followed by '-' to form a range. However,
5045 -      Perl does not permit ']' to be the end of the range. A '-' character
5046 -      here is treated as a literal. */
5047 -
5048 -      if (ptr[1] == '-' && ptr[2] != ']')
5049 -        {
5050 -        int d;
5051 -        ptr += 2;
5052 -        d = *ptr;
5053 -
5054 -        if (d == 0)
5055 -          {
5056 -          *errorptr = ERR6;
5057 -          goto FAILED;
5058 -          }
5059 -
5060 -        /* The second part of a range can be a single-character escape, but
5061 -        not any of the other escapes. Perl 5.6 treats a hyphen as a literal
5062 -        in such circumstances. */
5063 -
5064 -        if (d == '\\')
5065 -          {
5066 -          const uschar *oldptr = ptr;
5067 -          d = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd);
5068 -
5069 -#ifdef SUPPORT_UTF8
5070 -          if (d > 255)
5071 -            {
5072 -            *errorptr = ERR33;
5073 -            goto FAILED;
5074 -            }
5075 -#endif
5076 -          /* \b is backslash; any other special means the '-' was literal */
5077 -
5078 -          if (d < 0)
5079 -            {
5080 -            if (d == -ESC_b) d = '\b'; else
5081 -              {
5082 -              ptr = oldptr - 2;
5083 -              goto SINGLE_CHARACTER;  /* A few lines below */
5084 -              }
5085 -            }
5086 -          }
5087 -
5088 -        if (d < c)
5089 -          {
5090 -          *errorptr = ERR8;
5091 -          goto FAILED;
5092 -          }
5093 -
5094 -        for (; c <= d; c++)
5095 -          {
5096 -          class[c/8] |= (1 << (c&7));
5097 -          if ((options & PCRE_CASELESS) != 0)
5098 -            {
5099 -            int uc = cd->fcc[c];           /* flip case */
5100 -            class[uc/8] |= (1 << (uc&7));
5101 -            }
5102 -          class_charcount++;                /* in case a one-char range */
5103 -          class_lastchar = c;
5104 -          }
5105 -        continue;   /* Go get the next char in the class */
5106 -        }
5107 -
5108 -      /* Handle a lone single character - we can get here for a normal
5109 -      non-escape char, or after \ that introduces a single character. */
5110 -
5111 -      SINGLE_CHARACTER:
5112 -
5113 -      class [c/8] |= (1 << (c&7));
5114 -      if ((options & PCRE_CASELESS) != 0)
5115 -        {
5116 -        c = cd->fcc[c];   /* flip case */
5117 -        class[c/8] |= (1 << (c&7));
5118 -        }
5119 -      class_charcount++;
5120 -      class_lastchar = c;
5121 -      }
5122 -
5123 -    /* Loop until ']' reached; the check for end of string happens inside the
5124 -    loop. This "while" is the end of the "do" above. */
5125 -
5126 -    while ((c = *(++ptr)) != ']');
5127 -
5128 -    /* If class_charcount is 1 and class_lastchar is not negative, we saw
5129 -    precisely one character. This doesn't need the whole 32-byte bit map.
5130 -    We turn it into a 1-character OP_CHAR if it's positive, or OP_NOT if
5131 -    it's negative. */
5132 -
5133 -    if (class_charcount == 1 && class_lastchar >= 0)
5134 -      {
5135 -      if (negate_class)
5136 -        {
5137 -        code[-1] = OP_NOT;
5138 -        }
5139 -      else
5140 -        {
5141 -        code[-1] = OP_CHARS;
5142 -        *code++ = 1;
5143 -        }
5144 -      *code++ = class_lastchar;
5145 -      }
5146 -
5147 -    /* Otherwise, negate the 32-byte map if necessary, and copy it into
5148 -    the code vector. */
5149 -
5150 -    else
5151 -      {
5152 -      if (negate_class)
5153 -        for (c = 0; c < 32; c++) code[c] = ~class[c];
5154 -      else
5155 -        memcpy(code, class, 32);
5156 -      code += 32;
5157 -      }
5158 -    break;
5159 -
5160 -    /* Various kinds of repeat */
5161 -
5162 -    case '{':
5163 -    if (!is_counted_repeat(ptr+1, cd)) goto NORMAL_CHAR;
5164 -    ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorptr, cd);
5165 -    if (*errorptr != NULL) goto FAILED;
5166 -    goto REPEAT;
5167 -
5168 -    case '*':
5169 -    repeat_min = 0;
5170 -    repeat_max = -1;
5171 -    goto REPEAT;
5172 -
5173 -    case '+':
5174 -    repeat_min = 1;
5175 -    repeat_max = -1;
5176 -    goto REPEAT;
5177 -
5178 -    case '?':
5179 -    repeat_min = 0;
5180 -    repeat_max = 1;
5181 -
5182 -    REPEAT:
5183 -    if (previous == NULL)
5184 -      {
5185 -      *errorptr = ERR9;
5186 -      goto FAILED;
5187 -      }
5188 -
5189 -    /* If the next character is '?' this is a minimizing repeat, by default,
5190 -    but if PCRE_UNGREEDY is set, it works the other way round. Advance to the
5191 -    next character. */
5192 -
5193 -    if (ptr[1] == '?')
5194 -      { repeat_type = greedy_non_default; ptr++; }
5195 -    else repeat_type = greedy_default;
5196 -
5197 -    /* If previous was a string of characters, chop off the last one and use it
5198 -    as the subject of the repeat. If there was only one character, we can
5199 -    abolish the previous item altogether. A repeat with a zero minimum wipes
5200 -    out any reqchar setting, backing up to the previous value. We must also
5201 -    adjust the countlits value. */
5202 -
5203 -    if (*previous == OP_CHARS)
5204 -      {
5205 -      int len = previous[1];
5206 -
5207 -      if (repeat_min == 0) *reqchar = prevreqchar;
5208 -      *countlits += repeat_min - 1;
5209 -
5210 -      if (len == 1)
5211 -        {
5212 -        c = previous[2];
5213 -        code = previous;
5214 -        }
5215 -      else
5216 -        {
5217 -        c = previous[len+1];
5218 -        previous[1]--;
5219 -        code--;
5220 -        }
5221 -      op_type = 0;                 /* Use single-char op codes */
5222 -      goto OUTPUT_SINGLE_REPEAT;   /* Code shared with single character types */
5223 -      }
5224 -
5225 -    /* If previous was a single negated character ([^a] or similar), we use
5226 -    one of the special opcodes, replacing it. The code is shared with single-
5227 -    character repeats by adding a suitable offset into repeat_type. */
5228 -
5229 -    else if ((int)*previous == OP_NOT)
5230 -      {
5231 -      op_type = OP_NOTSTAR - OP_STAR;  /* Use "not" opcodes */
5232 -      c = previous[1];
5233 -      code = previous;
5234 -      goto OUTPUT_SINGLE_REPEAT;
5235 -      }
5236 -
5237 -    /* If previous was a character type match (\d or similar), abolish it and
5238 -    create a suitable repeat item. The code is shared with single-character
5239 -    repeats by adding a suitable offset into repeat_type. */
5240 -
5241 -    else if ((int)*previous < OP_EODN || *previous == OP_ANY)
5242 -      {
5243 -      op_type = OP_TYPESTAR - OP_STAR;  /* Use type opcodes */
5244 -      c = *previous;
5245 -      code = previous;
5246 -
5247 -      OUTPUT_SINGLE_REPEAT:
5248 -
5249 -      /* If the maximum is zero then the minimum must also be zero; Perl allows
5250 -      this case, so we do too - by simply omitting the item altogether. */
5251 -
5252 -      if (repeat_max == 0) goto END_REPEAT;
5253 -
5254 -      /* Combine the op_type with the repeat_type */
5255 -
5256 -      repeat_type += op_type;
5257 -
5258 -      /* A minimum of zero is handled either as the special case * or ?, or as
5259 -      an UPTO, with the maximum given. */
5260 -
5261 -      if (repeat_min == 0)
5262 -        {
5263 -        if (repeat_max == -1) *code++ = OP_STAR + repeat_type;
5264 -          else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type;
5265 -        else
5266 -          {
5267 -          *code++ = OP_UPTO + repeat_type;
5268 -          *code++ = repeat_max >> 8;
5269 -          *code++ = (repeat_max & 255);
5270 -          }
5271 -        }
5272 -
5273 -      /* The case {1,} is handled as the special case + */
5274 -
5275 -      else if (repeat_min == 1 && repeat_max == -1)
5276 -        *code++ = OP_PLUS + repeat_type;
5277 -
5278 -      /* The case {n,n} is just an EXACT, while the general case {n,m} is
5279 -      handled as an EXACT followed by an UPTO. An EXACT of 1 is optimized. */
5280 -
5281 -      else
5282 -        {
5283 -        if (repeat_min != 1)
5284 -          {
5285 -          *code++ = OP_EXACT + op_type;  /* NB EXACT doesn't have repeat_type */
5286 -          *code++ = repeat_min >> 8;
5287 -          *code++ = (repeat_min & 255);
5288 -          }
5289 -
5290 -        /* If the mininum is 1 and the previous item was a character string,
5291 -        we either have to put back the item that got cancelled if the string
5292 -        length was 1, or add the character back onto the end of a longer
5293 -        string. For a character type nothing need be done; it will just get
5294 -        put back naturally. Note that the final character is always going to
5295 -        get added below. */
5296 -
5297 -        else if (*previous == OP_CHARS)
5298 -          {
5299 -          if (code == previous) code += 2; else previous[1]++;
5300 -          }
5301 -
5302 -        /*  For a single negated character we also have to put back the
5303 -        item that got cancelled. */
5304 -
5305 -        else if (*previous == OP_NOT) code++;
5306 -
5307 -        /* If the maximum is unlimited, insert an OP_STAR. */
5308 -
5309 -        if (repeat_max < 0)
5310 -          {
5311 -          *code++ = c;
5312 -          *code++ = OP_STAR + repeat_type;
5313 -          }
5314 -
5315 -        /* Else insert an UPTO if the max is greater than the min. */
5316 -
5317 -        else if (repeat_max != repeat_min)
5318 -          {
5319 -          *code++ = c;
5320 -          repeat_max -= repeat_min;
5321 -          *code++ = OP_UPTO + repeat_type;
5322 -          *code++ = repeat_max >> 8;
5323 -          *code++ = (repeat_max & 255);
5324 -          }
5325 -        }
5326 -
5327 -      /* The character or character type itself comes last in all cases. */
5328 -
5329 -      *code++ = c;
5330 -      }
5331 -
5332 -    /* If previous was a character class or a back reference, we put the repeat
5333 -    stuff after it, but just skip the item if the repeat was {0,0}. */
5334 -
5335 -    else if (*previous == OP_CLASS || *previous == OP_REF)
5336 -      {
5337 -      if (repeat_max == 0)
5338 -        {
5339 -        code = previous;
5340 -        goto END_REPEAT;
5341 -        }
5342 -      if (repeat_min == 0 && repeat_max == -1)
5343 -        *code++ = OP_CRSTAR + repeat_type;
5344 -      else if (repeat_min == 1 && repeat_max == -1)
5345 -        *code++ = OP_CRPLUS + repeat_type;
5346 -      else if (repeat_min == 0 && repeat_max == 1)
5347 -        *code++ = OP_CRQUERY + repeat_type;
5348 -      else
5349 -        {
5350 -        *code++ = OP_CRRANGE + repeat_type;
5351 -        *code++ = repeat_min >> 8;
5352 -        *code++ = repeat_min & 255;
5353 -        if (repeat_max == -1) repeat_max = 0;  /* 2-byte encoding for max */
5354 -        *code++ = repeat_max >> 8;
5355 -        *code++ = repeat_max & 255;
5356 -        }
5357 -      }
5358 -
5359 -    /* If previous was a bracket group, we may have to replicate it in certain
5360 -    cases. */
5361 -
5362 -    else if ((int)*previous >= OP_BRA || (int)*previous == OP_ONCE ||
5363 -             (int)*previous == OP_COND)
5364 -      {
5365 -      register int i;
5366 -      int ketoffset = 0;
5367 -      int len = code - previous;
5368 -      uschar *bralink = NULL;
5369 -
5370 -      /* If the maximum repeat count is unlimited, find the end of the bracket
5371 -      by scanning through from the start, and compute the offset back to it
5372 -      from the current code pointer. There may be an OP_OPT setting following
5373 -      the final KET, so we can't find the end just by going back from the code
5374 -      pointer. */
5375 -
5376 -      if (repeat_max == -1)
5377 -        {
5378 -        register uschar *ket = previous;
5379 -        do ket += (ket[1] << 8) + ket[2]; while (*ket != OP_KET);
5380 -        ketoffset = code - ket;
5381 -        }
5382 -
5383 -      /* The case of a zero minimum is special because of the need to stick
5384 -      OP_BRAZERO in front of it, and because the group appears once in the
5385 -      data, whereas in other cases it appears the minimum number of times. For
5386 -      this reason, it is simplest to treat this case separately, as otherwise
5387 -      the code gets far too messy. There are several special subcases when the
5388 -      minimum is zero. */
5389 -
5390 -      if (repeat_min == 0)
5391 -        {
5392 -        /* If we set up a required char from the bracket, we must back off
5393 -        to the previous value and reset the countlits value too. */
5394 -
5395 -        if (subcountlits > 0)
5396 -          {
5397 -          *reqchar = prevreqchar;
5398 -          *countlits -= subcountlits;
5399 -          }
5400 -
5401 -        /* If the maximum is also zero, we just omit the group from the output
5402 -        altogether. */
5403 -
5404 -        if (repeat_max == 0)
5405 -          {
5406 -          code = previous;
5407 -          goto END_REPEAT;
5408 -          }
5409 -
5410 -        /* If the maximum is 1 or unlimited, we just have to stick in the
5411 -        BRAZERO and do no more at this point. */
5412 -
5413 -        if (repeat_max <= 1)
5414 -          {
5415 -          memmove(previous+1, previous, len);
5416 -          code++;
5417 -          *previous++ = OP_BRAZERO + repeat_type;
5418 -          }
5419 -
5420 -        /* If the maximum is greater than 1 and limited, we have to replicate
5421 -        in a nested fashion, sticking OP_BRAZERO before each set of brackets.
5422 -        The first one has to be handled carefully because it's the original
5423 -        copy, which has to be moved up. The remainder can be handled by code
5424 -        that is common with the non-zero minimum case below. We just have to
5425 -        adjust the value or repeat_max, since one less copy is required. */
5426 -
5427 -        else
5428 -          {
5429 -          int offset;
5430 -          memmove(previous+4, previous, len);
5431 -          code += 4;
5432 -          *previous++ = OP_BRAZERO + repeat_type;
5433 -          *previous++ = OP_BRA;
5434 -
5435 -          /* We chain together the bracket offset fields that have to be
5436 -          filled in later when the ends of the brackets are reached. */
5437 -
5438 -          offset = (bralink == NULL)? 0 : previous - bralink;
5439 -          bralink = previous;
5440 -          *previous++ = offset >> 8;
5441 -          *previous++ = offset & 255;
5442 -          }
5443 -
5444 -        repeat_max--;
5445 -        }
5446 -
5447 -      /* If the minimum is greater than zero, replicate the group as many
5448 -      times as necessary, and adjust the maximum to the number of subsequent
5449 -      copies that we need. */
5450 -
5451 -      else
5452 -        {
5453 -        for (i = 1; i < repeat_min; i++)
5454 -          {
5455 -          memcpy(code, previous, len);
5456 -          code += len;
5457 -          }
5458 -        if (repeat_max > 0) repeat_max -= repeat_min;
5459 -        }
5460 -
5461 -      /* This code is common to both the zero and non-zero minimum cases. If
5462 -      the maximum is limited, it replicates the group in a nested fashion,
5463 -      remembering the bracket starts on a stack. In the case of a zero minimum,
5464 -      the first one was set up above. In all cases the repeat_max now specifies
5465 -      the number of additional copies needed. */
5466 -
5467 -      if (repeat_max >= 0)
5468 -        {
5469 -        for (i = repeat_max - 1; i >= 0; i--)
5470 -          {
5471 -          *code++ = OP_BRAZERO + repeat_type;
5472 -
5473 -          /* All but the final copy start a new nesting, maintaining the
5474 -          chain of brackets outstanding. */
5475 -
5476 -          if (i != 0)
5477 -            {
5478 -            int offset;
5479 -            *code++ = OP_BRA;
5480 -            offset = (bralink == NULL)? 0 : code - bralink;
5481 -            bralink = code;
5482 -            *code++ = offset >> 8;
5483 -            *code++ = offset & 255;
5484 -            }
5485 -
5486 -          memcpy(code, previous, len);
5487 -          code += len;
5488 -          }
5489 -
5490 -        /* Now chain through the pending brackets, and fill in their length
5491 -        fields (which are holding the chain links pro tem). */
5492 -
5493 -        while (bralink != NULL)
5494 -          {
5495 -          int oldlinkoffset;
5496 -          int offset = code - bralink + 1;
5497 -          uschar *bra = code - offset;
5498 -          oldlinkoffset = (bra[1] << 8) + bra[2];
5499 -          bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset;
5500 -          *code++ = OP_KET;
5501 -          *code++ = bra[1] = offset >> 8;
5502 -          *code++ = bra[2] = (offset & 255);
5503 -          }
5504 -        }
5505 -
5506 -      /* If the maximum is unlimited, set a repeater in the final copy. We
5507 -      can't just offset backwards from the current code point, because we
5508 -      don't know if there's been an options resetting after the ket. The
5509 -      correct offset was computed above. */
5510 -
5511 -      else code[-ketoffset] = OP_KETRMAX + repeat_type;
5512 -      }
5513 -
5514 -    /* Else there's some kind of shambles */
5515 -
5516 -    else
5517 -      {
5518 -      *errorptr = ERR11;
5519 -      goto FAILED;
5520 -      }
5521 -
5522 -    /* In all case we no longer have a previous item. */
5523 -
5524 -    END_REPEAT:
5525 -    previous = NULL;
5526 -    break;
5527 -
5528 -
5529 -    /* Start of nested bracket sub-expression, or comment or lookahead or
5530 -    lookbehind or option setting or condition. First deal with special things
5531 -    that can come after a bracket; all are introduced by ?, and the appearance
5532 -    of any of them means that this is not a referencing group. They were
5533 -    checked for validity in the first pass over the string, so we don't have to
5534 -    check for syntax errors here.  */
5535 -
5536 -    case '(':
5537 -    newoptions = options;
5538 -    skipbytes = 0;
5539 -
5540 -    if (*(++ptr) == '?')
5541 -      {
5542 -      int set, unset;
5543 -      int *optset;
5544 -
5545 -      switch (*(++ptr))
5546 -        {
5547 -        case '#':                 /* Comment; skip to ket */
5548 -        ptr++;
5549 -        while (*ptr != ')') ptr++;
5550 -        continue;
5551 -
5552 -        case ':':                 /* Non-extracting bracket */
5553 -        bravalue = OP_BRA;
5554 -        ptr++;
5555 -        break;
5556 -
5557 -        case '(':
5558 -        bravalue = OP_COND;       /* Conditional group */
5559 -        if ((cd->ctypes[*(++ptr)] & ctype_digit) != 0)
5560 -          {
5561 -          int condref = *ptr - '0';
5562 -          while (*(++ptr) != ')') condref = condref*10 + *ptr - '0';
5563 -          if (condref == 0)
5564 -            {
5565 -            *errorptr = ERR35;
5566 -            goto FAILED;
5567 -            }
5568 -          ptr++;
5569 -          code[3] = OP_CREF;
5570 -          code[4] = condref >> 8;
5571 -          code[5] = condref & 255;
5572 -          skipbytes = 3;
5573 -          }
5574 -        else ptr--;
5575 -        break;
5576 -
5577 -        case '=':                 /* Positive lookahead */
5578 -        bravalue = OP_ASSERT;
5579 -        ptr++;
5580 -        break;
5581 -
5582 -        case '!':                 /* Negative lookahead */
5583 -        bravalue = OP_ASSERT_NOT;
5584 -        ptr++;
5585 -        break;
5586 -
5587 -        case '<':                 /* Lookbehinds */
5588 -        switch (*(++ptr))
5589 -          {
5590 -          case '=':               /* Positive lookbehind */
5591 -          bravalue = OP_ASSERTBACK;
5592 -          ptr++;
5593 -          break;
5594 -
5595 -          case '!':               /* Negative lookbehind */
5596 -          bravalue = OP_ASSERTBACK_NOT;
5597 -          ptr++;
5598 -          break;
5599 -
5600 -          default:                /* Syntax error */
5601 -          *errorptr = ERR24;
5602 -          goto FAILED;
5603 -          }
5604 -        break;
5605 -
5606 -        case '>':                 /* One-time brackets */
5607 -        bravalue = OP_ONCE;
5608 -        ptr++;
5609 -        break;
5610 -
5611 -        case 'R':                 /* Pattern recursion */
5612 -        *code++ = OP_RECURSE;
5613 -        ptr++;
5614 -        continue;
5615 -
5616 -        default:                  /* Option setting */
5617 -        set = unset = 0;
5618 -        optset = &set;
5619 -
5620 -        while (*ptr != ')' && *ptr != ':')
5621 -          {
5622 -          switch (*ptr++)
5623 -            {
5624 -            case '-': optset = &unset; break;
5625 -
5626 -            case 'i': *optset |= PCRE_CASELESS; break;
5627 -            case 'm': *optset |= PCRE_MULTILINE; break;
5628 -            case 's': *optset |= PCRE_DOTALL; break;
5629 -            case 'x': *optset |= PCRE_EXTENDED; break;
5630 -            case 'U': *optset |= PCRE_UNGREEDY; break;
5631 -            case 'X': *optset |= PCRE_EXTRA; break;
5632 -
5633 -            default:
5634 -            *errorptr = ERR12;
5635 -            goto FAILED;
5636 -            }
5637 -          }
5638 -
5639 -        /* Set up the changed option bits, but don't change anything yet. */
5640 -
5641 -        newoptions = (options | set) & (~unset);
5642 -
5643 -        /* If the options ended with ')' this is not the start of a nested
5644 -        group with option changes, so the options change at this level. At top
5645 -        level there is nothing else to be done (the options will in fact have
5646 -        been set from the start of compiling as a result of the first pass) but
5647 -        at an inner level we must compile code to change the ims options if
5648 -        necessary, and pass the new setting back so that it can be put at the
5649 -        start of any following branches, and when this group ends, a resetting
5650 -        item can be compiled. */
5651 -
5652 -        if (*ptr == ')')
5653 -          {
5654 -          if ((options & PCRE_INGROUP) != 0 &&
5655 -              (options & PCRE_IMS) != (newoptions & PCRE_IMS))
5656 -            {
5657 -            *code++ = OP_OPT;
5658 -            *code++ = *optchanged = newoptions & PCRE_IMS;
5659 -            }
5660 -          options = newoptions;  /* Change options at this level */
5661 -          previous = NULL;       /* This item can't be repeated */
5662 -          continue;              /* It is complete */
5663 -          }
5664 -
5665 -        /* If the options ended with ':' we are heading into a nested group
5666 -        with possible change of options. Such groups are non-capturing and are
5667 -        not assertions of any kind. All we need to do is skip over the ':';
5668 -        the newoptions value is handled below. */
5669 -
5670 -        bravalue = OP_BRA;
5671 -        ptr++;
5672 -        }
5673 -      }
5674 -
5675 -    /* Else we have a referencing group; adjust the opcode. If the bracket
5676 -    number is greater than EXTRACT_BASIC_MAX, we set the opcode one higher, and
5677 -    arrange for the true number to follow later, in an OP_BRANUMBER item. */
5678 -
5679 -    else
5680 -      {
5681 -      if (++(*brackets) > EXTRACT_BASIC_MAX)
5682 -        {
5683 -        bravalue = OP_BRA + EXTRACT_BASIC_MAX + 1;
5684 -        code[3] = OP_BRANUMBER;
5685 -        code[4] = *brackets >> 8;
5686 -        code[5] = *brackets & 255;
5687 -        skipbytes = 3;
5688 -        }
5689 -      else bravalue = OP_BRA + *brackets;
5690 -      }
5691 -
5692 -    /* Process nested bracketed re. Assertions may not be repeated, but other
5693 -    kinds can be. We copy code into a non-register variable in order to be able
5694 -    to pass its address because some compilers complain otherwise. Pass in a
5695 -    new setting for the ims options if they have changed. */
5696 -
5697 -    previous = (bravalue >= OP_ONCE)? code : NULL;
5698 -    *code = bravalue;
5699 -    tempcode = code;
5700 -
5701 -    if (!compile_regex(
5702 -         options | PCRE_INGROUP,       /* Set for all nested groups */
5703 -         ((options & PCRE_IMS) != (newoptions & PCRE_IMS))?
5704 -           newoptions & PCRE_IMS : -1, /* Pass ims options if changed */
5705 -         brackets,                     /* Extracting bracket count */
5706 -         &tempcode,                    /* Where to put code (updated) */
5707 -         &ptr,                         /* Input pointer (updated) */
5708 -         errorptr,                     /* Where to put an error message */
5709 -         (bravalue == OP_ASSERTBACK ||
5710 -          bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */
5711 -         skipbytes,                    /* Skip over OP_COND/OP_BRANUMBER */
5712 -         &subreqchar,                  /* For possible last char */
5713 -         &subcountlits,                /* For literal count */
5714 -         cd))                          /* Tables block */
5715 -      goto FAILED;
5716 -
5717 -    /* At the end of compiling, code is still pointing to the start of the
5718 -    group, while tempcode has been updated to point past the end of the group
5719 -    and any option resetting that may follow it. The pattern pointer (ptr)
5720 -    is on the bracket. */
5721 -
5722 -    /* If this is a conditional bracket, check that there are no more than
5723 -    two branches in the group. */
5724 -
5725 -    else if (bravalue == OP_COND)
5726 -      {
5727 -      uschar *tc = code;
5728 -      condcount = 0;
5729 -
5730 -      do {
5731 -         condcount++;
5732 -         tc += (tc[1] << 8) | tc[2];
5733 -         }
5734 -      while (*tc != OP_KET);
5735 -
5736 -      if (condcount > 2)
5737 -        {
5738 -        *errorptr = ERR27;
5739 -        goto FAILED;
5740 -        }
5741 -      }
5742 -
5743 -    /* Handle updating of the required character. If the subpattern didn't
5744 -    set one, leave it as it was. Otherwise, update it for normal brackets of
5745 -    all kinds, forward assertions, and conditions with two branches. Don't
5746 -    update the literal count for forward assertions, however. If the bracket
5747 -    is followed by a quantifier with zero repeat, we have to back off. Hence
5748 -    the definition of prevreqchar and subcountlits outside the main loop so
5749 -    that they can be accessed for the back off. */
5750 -
5751 -    if (subreqchar > 0 &&
5752 -         (bravalue >= OP_BRA || bravalue == OP_ONCE || bravalue == OP_ASSERT ||
5753 -         (bravalue == OP_COND && condcount == 2)))
5754 -      {
5755 -      prevreqchar = *reqchar;
5756 -      *reqchar = subreqchar;
5757 -      if (bravalue != OP_ASSERT) *countlits += subcountlits;
5758 -      }
5759 -
5760 -    /* Now update the main code pointer to the end of the group. */
5761 -
5762 -    code = tempcode;
5763 -
5764 -    /* Error if hit end of pattern */
5765 -
5766 -    if (*ptr != ')')
5767 -      {
5768 -      *errorptr = ERR14;
5769 -      goto FAILED;
5770 -      }
5771 -    break;
5772 -
5773 -    /* Check \ for being a real metacharacter; if not, fall through and handle
5774 -    it as a data character at the start of a string. Escape items are checked
5775 -    for validity in the pre-compiling pass. */
5776 -
5777 -    case '\\':
5778 -    tempptr = ptr;
5779 -    c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd);
5780 -
5781 -    /* Handle metacharacters introduced by \. For ones like \d, the ESC_ values
5782 -    are arranged to be the negation of the corresponding OP_values. For the
5783 -    back references, the values are ESC_REF plus the reference number. Only
5784 -    back references and those types that consume a character may be repeated.
5785 -    We can test for values between ESC_b and ESC_Z for the latter; this may
5786 -    have to change if any new ones are ever created. */
5787 -
5788 -    if (c < 0)
5789 -      {
5790 -      if (-c >= ESC_REF)
5791 -        {
5792 -        int number = -c - ESC_REF;
5793 -        previous = code;
5794 -        *code++ = OP_REF;
5795 -        *code++ = number >> 8;
5796 -        *code++ = number & 255;
5797 -        }
5798 -      else
5799 -        {
5800 -        previous = (-c > ESC_b && -c < ESC_Z)? code : NULL;
5801 -        *code++ = -c;
5802 -        }
5803 -      continue;
5804 -      }
5805 -
5806 -    /* Data character: reset and fall through */
5807 -
5808 -    ptr = tempptr;
5809 -    c = '\\';
5810 -
5811 -    /* Handle a run of data characters until a metacharacter is encountered.
5812 -    The first character is guaranteed not to be whitespace or # when the
5813 -    extended flag is set. */
5814 -
5815 -    NORMAL_CHAR:
5816 -    default:
5817 -    previous = code;
5818 -    *code = OP_CHARS;
5819 -    code += 2;
5820 -    length = 0;
5821 -
5822 -    do
5823 -      {
5824 -      if ((options & PCRE_EXTENDED) != 0)
5825 -        {
5826 -        if ((cd->ctypes[c] & ctype_space) != 0) continue;
5827 -        if (c == '#')
5828 -          {
5829 -          /* The space before the ; is to avoid a warning on a silly compiler
5830 -          on the Macintosh. */
5831 -          while ((c = *(++ptr)) != 0 && c != NEWLINE) ;
5832 -          if (c == 0) break;
5833 -          continue;
5834 -          }
5835 -        }
5836 -
5837 -      /* Backslash may introduce a data char or a metacharacter. Escaped items
5838 -      are checked for validity in the pre-compiling pass. Stop the string
5839 -      before a metaitem. */
5840 -
5841 -      if (c == '\\')
5842 -        {
5843 -        tempptr = ptr;
5844 -        c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd);
5845 -        if (c < 0) { ptr = tempptr; break; }
5846 -
5847 -        /* If a character is > 127 in UTF-8 mode, we have to turn it into
5848 -        two or more characters in the UTF-8 encoding. */
5849 -
5850 -#ifdef SUPPORT_UTF8
5851 -        if (c > 127 && (options & PCRE_UTF8) != 0)
5852 -          {
5853 -          uschar buffer[8];
5854 -          int len = ord2utf8(c, buffer);
5855 -          for (c = 0; c < len; c++) *code++ = buffer[c];
5856 -          length += len;
5857 -          continue;
5858 -          }
5859 -#endif
5860 -        }
5861 -
5862 -      /* Ordinary character or single-char escape */
5863 -
5864 -      *code++ = c;
5865 -      length++;
5866 -      }
5867 -
5868 -    /* This "while" is the end of the "do" above. */
5869 -
5870 -    while (length < MAXLIT && (cd->ctypes[c = *(++ptr)] & ctype_meta) == 0);
5871 -
5872 -    /* Update the last character and the count of literals */
5873 -
5874 -    prevreqchar = (length > 1)? code[-2] : *reqchar;
5875 -    *reqchar = code[-1];
5876 -    *countlits += length;
5877 -
5878 -    /* Compute the length and set it in the data vector, and advance to
5879 -    the next state. */
5880 -
5881 -    previous[1] = length;
5882 -    if (length < MAXLIT) ptr--;
5883 -    break;
5884 -    }
5885 -  }                   /* end of big loop */
5886 -
5887 -/* Control never reaches here by falling through, only by a goto for all the
5888 -error states. Pass back the position in the pattern so that it can be displayed
5889 -to the user for diagnosing the error. */
5890 -
5891 -FAILED:
5892 -*ptrptr = ptr;
5893 -return FALSE;
5894 -}
5895 -
5896 -
5897 -
5898 -
5899 -/*************************************************
5900 -*     Compile sequence of alternatives           *
5901 -*************************************************/
5902 -
5903 -/* On entry, ptr is pointing past the bracket character, but on return
5904 -it points to the closing bracket, or vertical bar, or end of string.
5905 -The code variable is pointing at the byte into which the BRA operator has been
5906 -stored. If the ims options are changed at the start (for a (?ims: group) or
5907 -during any branch, we need to insert an OP_OPT item at the start of every
5908 -following branch to ensure they get set correctly at run time, and also pass
5909 -the new options into every subsequent branch compile.
5910 -
5911 -Argument:
5912 -  options     the option bits
5913 -  optchanged  new ims options to set as if (?ims) were at the start, or -1
5914 -               for no change
5915 -  brackets    -> int containing the number of extracting brackets used
5916 -  codeptr     -> the address of the current code pointer
5917 -  ptrptr      -> the address of the current pattern pointer
5918 -  errorptr    -> pointer to error message
5919 -  lookbehind  TRUE if this is a lookbehind assertion
5920 -  skipbytes   skip this many bytes at start (for OP_COND, OP_BRANUMBER)
5921 -  reqchar     -> place to put the last required character, or a negative number
5922 -  countlits   -> place to put the shortest literal count of any branch
5923 -  cd          points to the data block with tables pointers
5924 -
5925 -Returns:      TRUE on success
5926 -*/
5927 -
5928 -static BOOL
5929 -compile_regex(int options, int optchanged, int *brackets, uschar **codeptr,
5930 -  const uschar **ptrptr, const char **errorptr, BOOL lookbehind, int skipbytes,
5931 -  int *reqchar, int *countlits, compile_data *cd)
5932 -{
5933 -const uschar *ptr = *ptrptr;
5934 -uschar *code = *codeptr;
5935 -uschar *last_branch = code;
5936 -uschar *start_bracket = code;
5937 -uschar *reverse_count = NULL;
5938 -int oldoptions = options & PCRE_IMS;
5939 -int branchreqchar, branchcountlits;
5940 -
5941 -*reqchar = -1;
5942 -*countlits = INT_MAX;
5943 -code += 3 + skipbytes;
5944 -
5945 -/* Loop for each alternative branch */
5946 -
5947 -for (;;)
5948 -  {
5949 -  int length;
5950 -
5951 -  /* Handle change of options */
5952 -
5953 -  if (optchanged >= 0)
5954 -    {
5955 -    *code++ = OP_OPT;
5956 -    *code++ = optchanged;
5957 -    options = (options & ~PCRE_IMS) | optchanged;
5958 -    }
5959 -
5960 -  /* Set up dummy OP_REVERSE if lookbehind assertion */
5961 -
5962 -  if (lookbehind)
5963 -    {
5964 -    *code++ = OP_REVERSE;
5965 -    reverse_count = code;
5966 -    *code++ = 0;
5967 -    *code++ = 0;
5968 -    }
5969 -
5970 -  /* Now compile the branch */
5971 -
5972 -  if (!compile_branch(options, brackets, &code, &ptr, errorptr, &optchanged,
5973 -      &branchreqchar, &branchcountlits, cd))
5974 -    {
5975 -    *ptrptr = ptr;
5976 -    return FALSE;
5977 -    }
5978 -
5979 -  /* Fill in the length of the last branch */
5980 -
5981 -  length = code - last_branch;
5982 -  last_branch[1] = length >> 8;
5983 -  last_branch[2] = length & 255;
5984 -
5985 -  /* Save the last required character if all branches have the same; a current
5986 -  value of -1 means unset, while -2 means "previous branch had no last required
5987 -  char".  */
5988 -
5989 -  if (*reqchar != -2)
5990 -    {
5991 -    if (branchreqchar >= 0)
5992 -      {
5993 -      if (*reqchar == -1) *reqchar = branchreqchar;
5994 -      else if (*reqchar != branchreqchar) *reqchar = -2;
5995 -      }
5996 -    else *reqchar = -2;
5997 -    }
5998 -
5999 -  /* Keep the shortest literal count */
6000 -
6001 -  if (branchcountlits < *countlits) *countlits = branchcountlits;
6002 -  DPRINTF(("literal count = %d min=%d\n", branchcountlits, *countlits));
6003 -
6004 -  /* If lookbehind, check that this branch matches a fixed-length string,
6005 -  and put the length into the OP_REVERSE item. Temporarily mark the end of
6006 -  the branch with OP_END. */
6007 -
6008 -  if (lookbehind)
6009 -    {
6010 -    *code = OP_END;
6011 -    length = find_fixedlength(last_branch, options);
6012 -    DPRINTF(("fixed length = %d\n", length));
6013 -    if (length < 0)
6014 -      {
6015 -      *errorptr = ERR25;
6016 -      *ptrptr = ptr;
6017 -      return FALSE;
6018 -      }
6019 -    reverse_count[0] = (length >> 8);
6020 -    reverse_count[1] = length & 255;
6021 -    }
6022 -
6023 -  /* Reached end of expression, either ')' or end of pattern. Insert a
6024 -  terminating ket and the length of the whole bracketed item, and return,
6025 -  leaving the pointer at the terminating char. If any of the ims options
6026 -  were changed inside the group, compile a resetting op-code following. */
6027 -
6028 -  if (*ptr != '|')
6029 -    {
6030 -    length = code - start_bracket;
6031 -    *code++ = OP_KET;
6032 -    *code++ = length >> 8;
6033 -    *code++ = length & 255;
6034 -    if (optchanged >= 0)
6035 -      {
6036 -      *code++ = OP_OPT;
6037 -      *code++ = oldoptions;
6038 -      }
6039 -    *codeptr = code;
6040 -    *ptrptr = ptr;
6041 -    return TRUE;
6042 -    }
6043 -
6044 -  /* Another branch follows; insert an "or" node and advance the pointer. */
6045 -
6046 -  *code = OP_ALT;
6047 -  last_branch = code;
6048 -  code += 3;
6049 -  ptr++;
6050 -  }
6051 -/* Control never reaches here */
6052 -}
6053 -
6054 -
6055 -
6056 -
6057 -/*************************************************
6058 -*      Find first significant op code            *
6059 -*************************************************/
6060 -
6061 -/* This is called by several functions that scan a compiled expression looking
6062 -for a fixed first character, or an anchoring op code etc. It skips over things
6063 -that do not influence this. For one application, a change of caseless option is
6064 -important.
6065 -
6066 -Arguments:
6067 -  code       pointer to the start of the group
6068 -  options    pointer to external options
6069 -  optbit     the option bit whose changing is significant, or
6070 -             zero if none are
6071 -  optstop    TRUE to return on option change, otherwise change the options
6072 -               value and continue
6073 -
6074 -Returns:     pointer to the first significant opcode
6075 -*/
6076 -
6077 -static const uschar*
6078 -first_significant_code(const uschar *code, int *options, int optbit,
6079 -  BOOL optstop)
6080 -{
6081 -for (;;)
6082 -  {
6083 -  switch ((int)*code)
6084 -    {
6085 -    case OP_OPT:
6086 -    if (optbit > 0 && ((int)code[1] & optbit) != (*options & optbit))
6087 -      {
6088 -      if (optstop) return code;
6089 -      *options = (int)code[1];
6090 -      }
6091 -    code += 2;
6092 -    break;
6093 -
6094 -    case OP_CREF:
6095 -    case OP_BRANUMBER:
6096 -    code += 3;
6097 -    break;
6098 -
6099 -    case OP_WORD_BOUNDARY:
6100 -    case OP_NOT_WORD_BOUNDARY:
6101 -    code++;
6102 -    break;
6103 -
6104 -    case OP_ASSERT_NOT:
6105 -    case OP_ASSERTBACK:
6106 -    case OP_ASSERTBACK_NOT:
6107 -    do code += (code[1] << 8) + code[2]; while (*code == OP_ALT);
6108 -    code += 3;
6109 -    break;
6110 -
6111 -    default:
6112 -    return code;
6113 -    }
6114 -  }
6115 -/* Control never reaches here */
6116 -}
6117 -
6118 -
6119 -
6120 -
6121 -/*************************************************
6122 -*          Check for anchored expression         *
6123 -*************************************************/
6124 -
6125 -/* Try to find out if this is an anchored regular expression. Consider each
6126 -alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket
6127 -all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then
6128 -it's anchored. However, if this is a multiline pattern, then only OP_SOD
6129 -counts, since OP_CIRC can match in the middle.
6130 -
6131 -A branch is also implicitly anchored if it starts with .* and DOTALL is set,
6132 -because that will try the rest of the pattern at all possible matching points,
6133 -so there is no point trying them again.
6134 -
6135 -Arguments:
6136 -  code       points to start of expression (the bracket)
6137 -  options    points to the options setting
6138 -
6139 -Returns:     TRUE or FALSE
6140 -*/
6141 -
6142 -static BOOL
6143 -is_anchored(register const uschar *code, int *options)
6144 -{
6145 -do {
6146 -   const uschar *scode = first_significant_code(code + 3, options,
6147 -     PCRE_MULTILINE, FALSE);
6148 -   register int op = *scode;
6149 -   if (op >= OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND)
6150 -     { if (!is_anchored(scode, options)) return FALSE; }
6151 -   else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR) &&
6152 -            (*options & PCRE_DOTALL) != 0)
6153 -     { if (scode[1] != OP_ANY) return FALSE; }
6154 -   else if (op != OP_SOD &&
6155 -           ((*options & PCRE_MULTILINE) != 0 || op != OP_CIRC))
6156 -     return FALSE;
6157 -   code += (code[1] << 8) + code[2];
6158 -   }
6159 -while (*code == OP_ALT);
6160 -return TRUE;
6161 -}
6162 -
6163 -
6164 -
6165 -/*************************************************
6166 -*         Check for starting with ^ or .*        *
6167 -*************************************************/
6168 -
6169 -/* This is called to find out if every branch starts with ^ or .* so that
6170 -"first char" processing can be done to speed things up in multiline
6171 -matching and for non-DOTALL patterns that start with .* (which must start at
6172 -the beginning or after \n).
6173 -
6174 -Argument:  points to start of expression (the bracket)
6175 -Returns:   TRUE or FALSE
6176 -*/
6177 -
6178 -static BOOL
6179 -is_startline(const uschar *code)
6180 -{
6181 -do {
6182 -   const uschar *scode = first_significant_code(code + 3, NULL, 0, FALSE);
6183 -   register int op = *scode;
6184 -   if (op >= OP_BRA || op == OP_ASSERT || op == OP_ONCE || op == OP_COND)
6185 -     { if (!is_startline(scode)) return FALSE; }
6186 -   else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR)
6187 -     { if (scode[1] != OP_ANY) return FALSE; }
6188 -   else if (op != OP_CIRC) return FALSE;
6189 -   code += (code[1] << 8) + code[2];
6190 -   }
6191 -while (*code == OP_ALT);
6192 -return TRUE;
6193 -}
6194 -
6195 -
6196 -
6197 -/*************************************************
6198 -*          Check for fixed first char            *
6199 -*************************************************/
6200 -
6201 -/* Try to find out if there is a fixed first character. This is called for
6202 -unanchored expressions, as it speeds up their processing quite considerably.
6203 -Consider each alternative branch. If they all start with the same char, or with
6204 -a bracket all of whose alternatives start with the same char (recurse ad lib),
6205 -then we return that char, otherwise -1.
6206 -
6207 -Arguments:
6208 -  code       points to start of expression (the bracket)
6209 -  options    pointer to the options (used to check casing changes)
6210 -
6211 -Returns:     -1 or the fixed first char
6212 -*/
6213 -
6214 -static int
6215 -find_firstchar(const uschar *code, int *options)
6216 -{
6217 -register int c = -1;
6218 -do {
6219 -   int d;
6220 -   const uschar *scode = first_significant_code(code + 3, options,
6221 -     PCRE_CASELESS, TRUE);
6222 -   register int op = *scode;
6223 -
6224 -   if (op >= OP_BRA) op = OP_BRA;
6225 -
6226 -   switch(op)
6227 -     {
6228 -     default:
6229 -     return -1;
6230 -
6231 -     case OP_BRA:
6232 -     case OP_ASSERT:
6233 -     case OP_ONCE:
6234 -     case OP_COND:
6235 -     if ((d = find_firstchar(scode, options)) < 0) return -1;
6236 -     if (c < 0) c = d; else if (c != d) return -1;
6237 -     break;
6238 -
6239 -     case OP_EXACT:       /* Fall through */
6240 -     scode++;
6241 -
6242 -     case OP_CHARS:       /* Fall through */
6243 -     scode++;
6244 -
6245 -     case OP_PLUS:
6246 -     case OP_MINPLUS:
6247 -     if (c < 0) c = scode[1]; else if (c != scode[1]) return -1;
6248 -     break;
6249 -     }
6250 -
6251 -   code += (code[1] << 8) + code[2];
6252 -   }
6253 -while (*code == OP_ALT);
6254 -return c;
6255 -}
6256 -
6257 -
6258 -
6259 -
6260 -
6261 -/*************************************************
6262 -*        Compile a Regular Expression            *
6263 -*************************************************/
6264 -
6265 -/* This function takes a string and returns a pointer to a block of store
6266 -holding a compiled version of the expression.
6267 -
6268 -Arguments:
6269 -  pattern      the regular expression
6270 -  options      various option bits
6271 -  errorptr     pointer to pointer to error text
6272 -  erroroffset  ptr offset in pattern where error was detected
6273 -  tables       pointer to character tables or NULL
6274 -
6275 -Returns:       pointer to compiled data block, or NULL on error,
6276 -               with errorptr and erroroffset set
6277 -*/
6278 -
6279 -pcre *
6280 -pcre_compile(const char *pattern, int options, const char **errorptr,
6281 -  int *erroroffset, const unsigned char *tables)
6282 -{
6283 -real_pcre *re;
6284 -int length = 3;      /* For initial BRA plus length */
6285 -int runlength;
6286 -int c, reqchar, countlits;
6287 -int bracount = 0;
6288 -int top_backref = 0;
6289 -int branch_extra = 0;
6290 -int branch_newextra;
6291 -unsigned int brastackptr = 0;
6292 -size_t size;
6293 -uschar *code;
6294 -const uschar *ptr;
6295 -compile_data compile_block;
6296 -int brastack[BRASTACK_SIZE];
6297 -uschar bralenstack[BRASTACK_SIZE];
6298 -
6299 -#ifdef DEBUG
6300 -uschar *code_base, *code_end;
6301 -#endif
6302 -
6303 -/* Can't support UTF8 unless PCRE has been compiled to include the code. */
6304 -
6305 -#ifndef SUPPORT_UTF8
6306 -if ((options & PCRE_UTF8) != 0)
6307 -  {
6308 -  *errorptr = ERR32;
6309 -  return NULL;
6310 -  }
6311 -#endif
6312 -
6313 -/* We can't pass back an error message if errorptr is NULL; I guess the best we
6314 -can do is just return NULL. */
6315 -
6316 -if (errorptr == NULL) return NULL;
6317 -*errorptr = NULL;
6318 -
6319 -/* However, we can give a message for this error */
6320 -
6321 -if (erroroffset == NULL)
6322 -  {
6323 -  *errorptr = ERR16;
6324 -  return NULL;
6325 -  }
6326 -*erroroffset = 0;
6327 -
6328 -if ((options & ~PUBLIC_OPTIONS) != 0)
6329 -  {
6330 -  *errorptr = ERR17;
6331 -  return NULL;
6332 -  }
6333 -
6334 -/* Set up pointers to the individual character tables */
6335 -
6336 -if (tables == NULL) tables = pcre_default_tables;
6337 -compile_block.lcc = tables + lcc_offset;
6338 -compile_block.fcc = tables + fcc_offset;
6339 -compile_block.cbits = tables + cbits_offset;
6340 -compile_block.ctypes = tables + ctypes_offset;
6341 -
6342 -/* Reflect pattern for debugging output */
6343 -
6344 -DPRINTF(("------------------------------------------------------------------\n"));
6345 -DPRINTF(("%s\n", pattern));
6346 -
6347 -/* The first thing to do is to make a pass over the pattern to compute the
6348 -amount of store required to hold the compiled code. This does not have to be
6349 -perfect as long as errors are overestimates. At the same time we can detect any
6350 -internal flag settings. Make an attempt to correct for any counted white space
6351 -if an "extended" flag setting appears late in the pattern. We can't be so
6352 -clever for #-comments. */
6353 -
6354 -ptr = (const uschar *)(pattern - 1);
6355 -while ((c = *(++ptr)) != 0)
6356 -  {
6357 -  int min, max;
6358 -  int class_charcount;
6359 -  int bracket_length;
6360 -
6361 -  if ((options & PCRE_EXTENDED) != 0)
6362 -    {
6363 -    if ((compile_block.ctypes[c] & ctype_space) != 0) continue;
6364 -    if (c == '#')
6365 -      {
6366 -      /* The space before the ; is to avoid a warning on a silly compiler
6367 -      on the Macintosh. */
6368 -      while ((c = *(++ptr)) != 0 && c != NEWLINE) ;
6369 -      continue;
6370 -      }
6371 -    }
6372 -
6373 -  switch(c)
6374 -    {
6375 -    /* A backslashed item may be an escaped "normal" character or a
6376 -    character type. For a "normal" character, put the pointers and
6377 -    character back so that tests for whitespace etc. in the input
6378 -    are done correctly. */
6379 -
6380 -    case '\\':
6381 -      {
6382 -      const uschar *save_ptr = ptr;
6383 -      c = check_escape(&ptr, errorptr, bracount, options, FALSE, &compile_block);
6384 -      if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
6385 -      if (c >= 0)
6386 -        {
6387 -        ptr = save_ptr;
6388 -        c = '\\';
6389 -        goto NORMAL_CHAR;
6390 -        }
6391 -      }
6392 -    length++;
6393 -
6394 -    /* A back reference needs an additional 2 bytes, plus either one or 5
6395 -    bytes for a repeat. We also need to keep the value of the highest
6396 -    back reference. */
6397 -
6398 -    if (c <= -ESC_REF)
6399 -      {
6400 -      int refnum = -c - ESC_REF;
6401 -      if (refnum > top_backref) top_backref = refnum;
6402 -      length += 2;   /* For single back reference */
6403 -      if (ptr[1] == '{' && is_counted_repeat(ptr+2, &compile_block))
6404 -        {
6405 -        ptr = read_repeat_counts(ptr+2, &min, &max, errorptr, &compile_block);
6406 -        if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
6407 -        if ((min == 0 && (max == 1 || max == -1)) ||
6408 -          (min == 1 && max == -1))
6409 -            length++;
6410 -        else length += 5;
6411 -        if (ptr[1] == '?') ptr++;
6412 -        }
6413 -      }
6414 -    continue;
6415 -
6416 -    case '^':
6417 -    case '.':
6418 -    case '$':
6419 -    case '*':     /* These repeats won't be after brackets; */
6420 -    case '+':     /* those are handled separately */
6421 -    case '?':
6422 -    length++;
6423 -    continue;
6424 -
6425 -    /* This covers the cases of repeats after a single char, metachar, class,
6426 -    or back reference. */
6427 -
6428 -    case '{':
6429 -    if (!is_counted_repeat(ptr+1, &compile_block)) goto NORMAL_CHAR;
6430 -    ptr = read_repeat_counts(ptr+1, &min, &max, errorptr, &compile_block);
6431 -    if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
6432 -    if ((min == 0 && (max == 1 || max == -1)) ||
6433 -      (min == 1 && max == -1))
6434 -        length++;
6435 -    else
6436 -      {
6437 -      length--;   /* Uncount the original char or metachar */
6438 -      if (min == 1) length++; else if (min > 0) length += 4;
6439 -      if (max > 0) length += 4; else length += 2;
6440 -      }
6441 -    if (ptr[1] == '?') ptr++;
6442 -    continue;
6443 -
6444 -    /* An alternation contains an offset to the next branch or ket. If any ims
6445 -    options changed in the previous branch(es), and/or if we are in a
6446 -    lookbehind assertion, extra space will be needed at the start of the
6447 -    branch. This is handled by branch_extra. */
6448 -
6449 -    case '|':
6450 -    length += 3 + branch_extra;
6451 -    continue;
6452 -
6453 -    /* A character class uses 33 characters. Don't worry about character types
6454 -    that aren't allowed in classes - they'll get picked up during the compile.
6455 -    A character class that contains only one character uses 2 or 3 bytes,
6456 -    depending on whether it is negated or not. Notice this where we can. */
6457 -
6458 -    case '[':
6459 -    class_charcount = 0;
6460 -    if (*(++ptr) == '^') ptr++;
6461 -    do
6462 -      {
6463 -      if (*ptr == '\\')
6464 -        {
6465 -        int ch = check_escape(&ptr, errorptr, bracount, options, TRUE,
6466 -          &compile_block);
6467 -        if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
6468 -        if (-ch == ESC_b) class_charcount++; else class_charcount = 10;
6469 -        }
6470 -      else class_charcount++;
6471 -      ptr++;
6472 -      }
6473 -    while (*ptr != 0 && *ptr != ']');
6474 -
6475 -    /* Repeats for negated single chars are handled by the general code */
6476 -
6477 -    if (class_charcount == 1) length += 3; else
6478 -      {
6479 -      length += 33;
6480 -
6481 -      /* A repeat needs either 1 or 5 bytes. */
6482 -
6483 -      if (*ptr != 0 && ptr[1] == '{' && is_counted_repeat(ptr+2, &compile_block))
6484 -        {
6485 -        ptr = read_repeat_counts(ptr+2, &min, &max, errorptr, &compile_block);
6486 -        if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
6487 -        if ((min == 0 && (max == 1 || max == -1)) ||
6488 -          (min == 1 && max == -1))
6489 -            length++;
6490 -        else length += 5;
6491 -        if (ptr[1] == '?') ptr++;
6492 -        }
6493 -      }
6494 -    continue;
6495 -
6496 -    /* Brackets may be genuine groups or special things */
6497 -
6498 -    case '(':
6499 -    branch_newextra = 0;
6500 -    bracket_length = 3;
6501 -
6502 -    /* Handle special forms of bracket, which all start (? */
6503 -
6504 -    if (ptr[1] == '?')
6505 -      {
6506 -      int set, unset;
6507 -      int *optset;
6508 -
6509 -      switch (c = ptr[2])
6510 -        {
6511 -        /* Skip over comments entirely */
6512 -        case '#':
6513 -        ptr += 3;
6514 -        while (*ptr != 0 && *ptr != ')') ptr++;
6515 -        if (*ptr == 0)
6516 -          {
6517 -          *errorptr = ERR18;
6518 -          goto PCRE_ERROR_RETURN;
6519 -          }
6520 -        continue;
6521 -
6522 -        /* Non-referencing groups and lookaheads just move the pointer on, and
6523 -        then behave like a non-special bracket, except that they don't increment
6524 -        the count of extracting brackets. Ditto for the "once only" bracket,
6525 -        which is in Perl from version 5.005. */
6526 -
6527 -        case ':':
6528 -        case '=':
6529 -        case '!':
6530 -        case '>':
6531 -        ptr += 2;
6532 -        break;
6533 -
6534 -        /* A recursive call to the regex is an extension, to provide the
6535 -        facility which can be obtained by $(?p{perl-code}) in Perl 5.6. */
6536 -
6537 -        case 'R':
6538 -        if (ptr[3] != ')')
6539 -          {
6540 -          *errorptr = ERR29;
6541 -          goto PCRE_ERROR_RETURN;
6542 -          }
6543 -        ptr += 3;
6544 -        length += 1;
6545 -        break;
6546 -
6547 -        /* Lookbehinds are in Perl from version 5.005 */
6548 -
6549 -        case '<':
6550 -        if (ptr[3] == '=' || ptr[3] == '!')
6551 -          {
6552 -          ptr += 3;
6553 -          branch_newextra = 3;
6554 -          length += 3;         /* For the first branch */
6555 -          break;
6556 -          }
6557 -        *errorptr = ERR24;
6558 -        goto PCRE_ERROR_RETURN;
6559 -
6560 -        /* Conditionals are in Perl from version 5.005. The bracket must either
6561 -        be followed by a number (for bracket reference) or by an assertion
6562 -        group. */
6563 -
6564 -        case '(':
6565 -        if ((compile_block.ctypes[ptr[3]] & ctype_digit) != 0)
6566 -          {
6567 -          ptr += 4;
6568 -          length += 3;
6569 -          while ((compile_block.ctypes[*ptr] & ctype_digit) != 0) ptr++;
6570 -          if (*ptr != ')')
6571 -            {
6572 -            *errorptr = ERR26;
6573 -            goto PCRE_ERROR_RETURN;
6574 -            }
6575 -          }
6576 -        else   /* An assertion must follow */
6577 -          {
6578 -          ptr++;   /* Can treat like ':' as far as spacing is concerned */
6579 -          if (ptr[2] != '?' ||
6580 -             (ptr[3] != '=' && ptr[3] != '!' && ptr[3] != '<') )
6581 -            {
6582 -            ptr += 2;    /* To get right offset in message */
6583 -            *errorptr = ERR28;
6584 -            goto PCRE_ERROR_RETURN;
6585 -            }
6586 -          }
6587 -        break;
6588 -
6589 -        /* Else loop checking valid options until ) is met. Anything else is an
6590 -        error. If we are without any brackets, i.e. at top level, the settings
6591 -        act as if specified in the options, so massage the options immediately.
6592 -        This is for backward compatibility with Perl 5.004. */
6593 -
6594 -        default:
6595 -        set = unset = 0;
6596 -        optset = &set;
6597 -        ptr += 2;
6598 -
6599 -        for (;; ptr++)
6600 -          {
6601 -          c = *ptr;
6602 -          switch (c)
6603 -            {
6604 -            case 'i':
6605 -            *optset |= PCRE_CASELESS;
6606 -            continue;
6607 -
6608 -            case 'm':
6609 -            *optset |= PCRE_MULTILINE;
6610 -            continue;
6611 -
6612 -            case 's':
6613 -            *optset |= PCRE_DOTALL;
6614 -            continue;
6615 -
6616 -            case 'x':
6617 -            *optset |= PCRE_EXTENDED;
6618 -            continue;
6619 -
6620 -            case 'X':
6621 -            *optset |= PCRE_EXTRA;
6622 -            continue;
6623 -
6624 -            case 'U':
6625 -            *optset |= PCRE_UNGREEDY;
6626 -            continue;
6627 -
6628 -            case '-':
6629 -            optset = &unset;
6630 -            continue;
6631 -
6632 -            /* A termination by ')' indicates an options-setting-only item;
6633 -            this is global at top level; otherwise nothing is done here and
6634 -            it is handled during the compiling process on a per-bracket-group
6635 -            basis. */
6636 -
6637 -            case ')':
6638 -            if (brastackptr == 0)
6639 -              {
6640 -              options = (options | set) & (~unset);
6641 -              set = unset = 0;     /* To save length */
6642 -              }
6643 -            /* Fall through */
6644 -
6645 -            /* A termination by ':' indicates the start of a nested group with
6646 -            the given options set. This is again handled at compile time, but
6647 -            we must allow for compiled space if any of the ims options are
6648 -            set. We also have to allow for resetting space at the end of
6649 -            the group, which is why 4 is added to the length and not just 2.
6650 -            If there are several changes of options within the same group, this
6651 -            will lead to an over-estimate on the length, but this shouldn't
6652 -            matter very much. We also have to allow for resetting options at
6653 -            the start of any alternations, which we do by setting
6654 -            branch_newextra to 2. Finally, we record whether the case-dependent
6655 -            flag ever changes within the regex. This is used by the "required
6656 -            character" code. */
6657 -
6658 -            case ':':
6659 -            if (((set|unset) & PCRE_IMS) != 0)
6660 -              {
6661 -              length += 4;
6662 -              branch_newextra = 2;
6663 -              if (((set|unset) & PCRE_CASELESS) != 0) options |= PCRE_ICHANGED;
6664 -              }
6665 -            goto END_OPTIONS;
6666 -
6667 -            /* Unrecognized option character */
6668 -
6669 -            default:
6670 -            *errorptr = ERR12;
6671 -            goto PCRE_ERROR_RETURN;
6672 -            }
6673 -          }
6674 -
6675 -        /* If we hit a closing bracket, that's it - this is a freestanding
6676 -        option-setting. We need to ensure that branch_extra is updated if
6677 -        necessary. The only values branch_newextra can have here are 0 or 2.
6678 -        If the value is 2, then branch_extra must either be 2 or 5, depending
6679 -        on whether this is a lookbehind group or not. */
6680 -
6681 -        END_OPTIONS:
6682 -        if (c == ')')
6683 -          {
6684 -          if (branch_newextra == 2 && (branch_extra == 0 || branch_extra == 3))
6685 -            branch_extra += branch_newextra;
6686 -          continue;
6687 -          }
6688 -
6689 -        /* If options were terminated by ':' control comes here. Fall through
6690 -        to handle the group below. */
6691 -        }
6692 -      }
6693 -
6694 -    /* Extracting brackets must be counted so we can process escapes in a
6695 -    Perlish way. If the number exceeds EXTRACT_BASIC_MAX we are going to
6696 -    need an additional 3 bytes of store per extracting bracket. */
6697 -
6698 -    else
6699 -      {
6700 -      bracount++;
6701 -      if (bracount > EXTRACT_BASIC_MAX) bracket_length += 3;
6702 -      }
6703 -
6704 -    /* Save length for computing whole length at end if there's a repeat that
6705 -    requires duplication of the group. Also save the current value of
6706 -    branch_extra, and start the new group with the new value. If non-zero, this
6707 -    will either be 2 for a (?imsx: group, or 3 for a lookbehind assertion. */
6708 -
6709 -    if (brastackptr >= sizeof(brastack)/sizeof(int))
6710 -      {
6711 -      *errorptr = ERR19;
6712 -      goto PCRE_ERROR_RETURN;
6713 -      }
6714 -
6715 -    bralenstack[brastackptr] = branch_extra;
6716 -    branch_extra = branch_newextra;
6717 -
6718 -    brastack[brastackptr++] = length;
6719 -    length += bracket_length;
6720 -    continue;
6721 -
6722 -    /* Handle ket. Look for subsequent max/min; for certain sets of values we
6723 -    have to replicate this bracket up to that many times. If brastackptr is
6724 -    0 this is an unmatched bracket which will generate an error, but take care
6725 -    not to try to access brastack[-1] when computing the length and restoring
6726 -    the branch_extra value. */
6727 -
6728 -    case ')':
6729 -    length += 3;
6730 -      {
6731 -      int minval = 1;
6732 -      int maxval = 1;
6733 -      int duplength;
6734 -
6735 -      if (brastackptr > 0)
6736 -        {
6737 -        duplength = length - brastack[--brastackptr];
6738 -        branch_extra = bralenstack[brastackptr];
6739 -        }
6740 -      else duplength = 0;
6741 -
6742 -      /* Leave ptr at the final char; for read_repeat_counts this happens
6743 -      automatically; for the others we need an increment. */
6744 -
6745 -      if ((c = ptr[1]) == '{' && is_counted_repeat(ptr+2, &compile_block))
6746 -        {
6747 -        ptr = read_repeat_counts(ptr+2, &minval, &maxval, errorptr,
6748 -          &compile_block);
6749 -        if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
6750 -        }
6751 -      else if (c == '*') { minval = 0; maxval = -1; ptr++; }
6752 -      else if (c == '+') { maxval = -1; ptr++; }
6753 -      else if (c == '?') { minval = 0; ptr++; }
6754 -
6755 -      /* If the minimum is zero, we have to allow for an OP_BRAZERO before the
6756 -      group, and if the maximum is greater than zero, we have to replicate
6757 -      maxval-1 times; each replication acquires an OP_BRAZERO plus a nesting
6758 -      bracket set - hence the 7. */
6759 -
6760 -      if (minval == 0)
6761 -        {
6762 -        length++;
6763 -        if (maxval > 0) length += (maxval - 1) * (duplength + 7);
6764 -        }
6765 -
6766 -      /* When the minimum is greater than zero, 1 we have to replicate up to
6767 -      minval-1 times, with no additions required in the copies. Then, if
6768 -      there is a limited maximum we have to replicate up to maxval-1 times
6769 -      allowing for a BRAZERO item before each optional copy and nesting
6770 -      brackets for all but one of the optional copies. */
6771 -
6772 -      else
6773 -        {
6774 -        length += (minval - 1) * duplength;
6775 -        if (maxval > minval)   /* Need this test as maxval=-1 means no limit */
6776 -          length += (maxval - minval) * (duplength + 7) - 6;
6777 -        }
6778 -      }
6779 -    continue;
6780 -
6781 -    /* Non-special character. For a run of such characters the length required
6782 -    is the number of characters + 2, except that the maximum run length is 255.
6783 -    We won't get a skipped space or a non-data escape or the start of a #
6784 -    comment as the first character, so the length can't be zero. */
6785 -
6786 -    NORMAL_CHAR:
6787 -    default:
6788 -    length += 2;
6789 -    runlength = 0;
6790 -    do
6791 -      {
6792 -      if ((options & PCRE_EXTENDED) != 0)
6793 -        {
6794 -        if ((compile_block.ctypes[c] & ctype_space) != 0) continue;
6795 -        if (c == '#')
6796 -          {
6797 -          /* The space before the ; is to avoid a warning on a silly compiler
6798 -          on the Macintosh. */
6799 -          while ((c = *(++ptr)) != 0 && c != NEWLINE) ;
6800 -          continue;
6801 -          }
6802 -        }
6803 -
6804 -      /* Backslash may introduce a data char or a metacharacter; stop the
6805 -      string before the latter. */
6806 -
6807 -      if (c == '\\')
6808 -        {
6809 -        const uschar *saveptr = ptr;
6810 -        c = check_escape(&ptr, errorptr, bracount, options, FALSE,
6811 -          &compile_block);
6812 -        if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
6813 -        if (c < 0) { ptr = saveptr; break; }
6814 -
6815 -#ifdef SUPPORT_UTF8
6816 -        if (c > 127 && (options & PCRE_UTF8) != 0)
6817 -          {
6818 -          int i;
6819 -          for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++)
6820 -            if (c <= utf8_table1[i]) break;
6821 -          runlength += i;
6822 -          }
6823 -#endif
6824 -        }
6825 -
6826 -      /* Ordinary character or single-char escape */
6827 -
6828 -      runlength++;
6829 -      }
6830 -
6831 -    /* This "while" is the end of the "do" above. */
6832 -
6833 -    while (runlength < MAXLIT &&
6834 -      (compile_block.ctypes[c = *(++ptr)] & ctype_meta) == 0);
6835 -
6836 -    ptr--;
6837 -    length += runlength;
6838 -    continue;
6839 -    }
6840 -  }
6841 -
6842 -length += 4;    /* For final KET and END */
6843 -
6844 -if (length > 65539)
6845 -  {
6846 -  *errorptr = ERR20;
6847 -  return NULL;
6848 -  }
6849 -
6850 -/* Compute the size of data block needed and get it, either from malloc or
6851 -externally provided function. We specify "code[0]" in the offsetof() expression
6852 -rather than just "code", because it has been reported that one broken compiler
6853 -fails on "code" because it is also an independent variable. It should make no
6854 -difference to the value of the offsetof(). */
6855 -
6856 -size = length + offsetof(real_pcre, code[0]);
6857 -re = (real_pcre *)(pcre_malloc)(size);
6858 -
6859 -if (re == NULL)
6860 -  {
6861 -  *errorptr = ERR21;
6862 -  return NULL;
6863 -  }
6864 -
6865 -/* size of re is sloppily computed, memset to get consistent output */
6866 -memset(re, 0, size);
6867 -
6868 -/* Put in the magic number, and save the size, options, and table pointer */
6869 -
6870 -re->magic_number = MAGIC_NUMBER;
6871 -re->size = size;
6872 -re->options = options;
6873 -re->tables = tables;
6874 -
6875 -/* Set up a starting, non-extracting bracket, then compile the expression. On
6876 -error, *errorptr will be set non-NULL, so we don't need to look at the result
6877 -of the function here. */
6878 -
6879 -ptr = (const uschar *)pattern;
6880 -code = re->code;
6881 -*code = OP_BRA;
6882 -bracount = 0;
6883 -(void)compile_regex(options, -1, &bracount, &code, &ptr, errorptr, FALSE, 0,
6884 -  &reqchar, &countlits, &compile_block);
6885 -re->top_bracket = bracount;
6886 -re->top_backref = top_backref;
6887 -
6888 -/* If not reached end of pattern on success, there's an excess bracket. */
6889 -
6890 -if (*errorptr == NULL && *ptr != 0) *errorptr = ERR22;
6891 -
6892 -/* Fill in the terminating state and check for disastrous overflow, but
6893 -if debugging, leave the test till after things are printed out. */
6894 -
6895 -*code++ = OP_END;
6896 -
6897 -#ifndef DEBUG
6898 -if (code - re->code > length) *errorptr = ERR23;
6899 -#endif
6900 -
6901 -/* Give an error if there's back reference to a non-existent capturing
6902 -subpattern. */
6903 -
6904 -if (top_backref > re->top_bracket) *errorptr = ERR15;
6905 -
6906 -/* Failed to compile */
6907 -
6908 -if (*errorptr != NULL)
6909 -  {
6910 -  (pcre_free)(re);
6911 -  PCRE_ERROR_RETURN:
6912 -  *erroroffset = ptr - (const uschar *)pattern;
6913 -  return NULL;
6914 -  }
6915 -
6916 -/* If the anchored option was not passed, set flag if we can determine that the
6917 -pattern is anchored by virtue of ^ characters or \A or anything else (such as
6918 -starting with .* when DOTALL is set).
6919 -
6920 -Otherwise, see if we can determine what the first character has to be, because
6921 -that speeds up unanchored matches no end. If not, see if we can set the
6922 -PCRE_STARTLINE flag. This is helpful for multiline matches when all branches
6923 -start with ^. and also when all branches start with .* for non-DOTALL matches.
6924 -*/
6925 -
6926 -if ((options & PCRE_ANCHORED) == 0)
6927 -  {
6928 -  int temp_options = options;
6929 -  if (is_anchored(re->code, &temp_options))
6930 -    re->options |= PCRE_ANCHORED;
6931 -  else
6932 -    {
6933 -    int ch = find_firstchar(re->code, &temp_options);
6934 -    if (ch >= 0)
6935 -      {
6936 -      re->first_char = ch;
6937 -      re->options |= PCRE_FIRSTSET;
6938 -      }
6939 -    else if (is_startline(re->code))
6940 -      re->options |= PCRE_STARTLINE;
6941 -    }
6942 -  }
6943 -
6944 -/* Save the last required character if there are at least two literal
6945 -characters on all paths, or if there is no first character setting. */
6946 -
6947 -if (reqchar >= 0 && (countlits > 1 || (re->options & PCRE_FIRSTSET) == 0))
6948 -  {
6949 -  re->req_char = reqchar;
6950 -  re->options |= PCRE_REQCHSET;
6951 -  }
6952 -
6953 -/* Print out the compiled data for debugging */
6954 -
6955 -#ifdef DEBUG
6956 -
6957 -printf("Length = %d top_bracket = %d top_backref = %d\n",
6958 -  length, re->top_bracket, re->top_backref);
6959 -
6960 -if (re->options != 0)
6961 -  {
6962 -  printf("%s%s%s%s%s%s%s%s%s\n",
6963 -    ((re->options & PCRE_ANCHORED) != 0)? "anchored " : "",
6964 -    ((re->options & PCRE_CASELESS) != 0)? "caseless " : "",
6965 -    ((re->options & PCRE_ICHANGED) != 0)? "case state changed " : "",
6966 -    ((re->options & PCRE_EXTENDED) != 0)? "extended " : "",
6967 -    ((re->options & PCRE_MULTILINE) != 0)? "multiline " : "",
6968 -    ((re->options & PCRE_DOTALL) != 0)? "dotall " : "",
6969 -    ((re->options & PCRE_DOLLAR_ENDONLY) != 0)? "endonly " : "",
6970 -    ((re->options & PCRE_EXTRA) != 0)? "extra " : "",
6971 -    ((re->options & PCRE_UNGREEDY) != 0)? "ungreedy " : "");
6972 -  }
6973 -
6974 -if ((re->options & PCRE_FIRSTSET) != 0)
6975 -  {
6976 -  if (isprint(re->first_char)) printf("First char = %c\n", re->first_char);
6977 -    else printf("First char = \\x%02x\n", re->first_char);
6978 -  }
6979 -
6980 -if ((re->options & PCRE_REQCHSET) != 0)
6981 -  {
6982 -  if (isprint(re->req_char)) printf("Req char = %c\n", re->req_char);
6983 -    else printf("Req char = \\x%02x\n", re->req_char);
6984 -  }
6985 -
6986 -code_end = code;
6987 -code_base = code = re->code;
6988 -
6989 -while (code < code_end)
6990 -  {
6991 -  int charlength;
6992 -
6993 -  printf("%3d ", code - code_base);
6994 -
6995 -  if (*code >= OP_BRA)
6996 -    {
6997 -    if (*code - OP_BRA > EXTRACT_BASIC_MAX)
6998 -      printf("%3d Bra extra", (code[1] << 8) + code[2]);
6999 -    else
7000 -      printf("%3d Bra %d", (code[1] << 8) + code[2], *code - OP_BRA);
7001 -    code += 2;
7002 -    }
7003 -
7004 -  else switch(*code)
7005 -    {
7006 -    case OP_OPT:
7007 -    printf(" %.2x %s", code[1], OP_names[*code]);
7008 -    code++;
7009 -    break;
7010 -
7011 -    case OP_CHARS:
7012 -    charlength = *(++code);
7013 -    printf("%3d ", charlength);
7014 -    while (charlength-- > 0)
7015 -      if (isprint(c = *(++code))) printf("%c", c); else printf("\\x%02x", c);
7016 -    break;
7017 -
7018 -    case OP_KETRMAX:
7019 -    case OP_KETRMIN:
7020 -    case OP_ALT:
7021 -    case OP_KET:
7022 -    case OP_ASSERT:
7023 -    case OP_ASSERT_NOT:
7024 -    case OP_ASSERTBACK:
7025 -    case OP_ASSERTBACK_NOT:
7026 -    case OP_ONCE:
7027 -    case OP_REVERSE:
7028 -    case OP_BRANUMBER:
7029 -    case OP_COND:
7030 -    case OP_CREF:
7031 -    printf("%3d %s", (code[1] << 8) + code[2], OP_names[*code]);
7032 -    code += 2;
7033 -    break;
7034 -
7035 -    case OP_STAR:
7036 -    case OP_MINSTAR:
7037 -    case OP_PLUS:
7038 -    case OP_MINPLUS:
7039 -    case OP_QUERY:
7040 -    case OP_MINQUERY:
7041 -    case OP_TYPESTAR:
7042 -    case OP_TYPEMINSTAR:
7043 -    case OP_TYPEPLUS:
7044 -    case OP_TYPEMINPLUS:
7045 -    case OP_TYPEQUERY:
7046 -    case OP_TYPEMINQUERY:
7047 -    if (*code >= OP_TYPESTAR)
7048 -      printf("    %s", OP_names[code[1]]);
7049 -    else if (isprint(c = code[1])) printf("    %c", c);
7050 -      else printf("    \\x%02x", c);
7051 -    printf("%s", OP_names[*code++]);
7052 -    break;
7053 -
7054 -    case OP_EXACT:
7055 -    case OP_UPTO:
7056 -    case OP_MINUPTO:
7057 -    if (isprint(c = code[3])) printf("    %c{", c);
7058 -      else printf("    \\x%02x{", c);
7059 -    if (*code != OP_EXACT) printf("0,");
7060 -    printf("%d}", (code[1] << 8) + code[2]);
7061 -    if (*code == OP_MINUPTO) printf("?");
7062 -    code += 3;
7063 -    break;
7064 -
7065 -    case OP_TYPEEXACT:
7066 -    case OP_TYPEUPTO:
7067 -    case OP_TYPEMINUPTO:
7068 -    printf("    %s{", OP_names[code[3]]);
7069 -    if (*code != OP_TYPEEXACT) printf(",");
7070 -    printf("%d}", (code[1] << 8) + code[2]);
7071 -    if (*code == OP_TYPEMINUPTO) printf("?");
7072 -    code += 3;
7073 -    break;
7074 -
7075 -    case OP_NOT:
7076 -    if (isprint(c = *(++code))) printf("    [^%c]", c);
7077 -      else printf("    [^\\x%02x]", c);
7078 -    break;
7079 -
7080 -    case OP_NOTSTAR:
7081 -    case OP_NOTMINSTAR:
7082 -    case OP_NOTPLUS:
7083 -    case OP_NOTMINPLUS:
7084 -    case OP_NOTQUERY:
7085 -    case OP_NOTMINQUERY:
7086 -    if (isprint(c = code[1])) printf("    [^%c]", c);
7087 -      else printf("    [^\\x%02x]", c);
7088 -    printf("%s", OP_names[*code++]);
7089 -    break;
7090 -
7091 -    case OP_NOTEXACT:
7092 -    case OP_NOTUPTO:
7093 -    case OP_NOTMINUPTO:
7094 -    if (isprint(c = code[3])) printf("    [^%c]{", c);
7095 -      else printf("    [^\\x%02x]{", c);
7096 -    if (*code != OP_NOTEXACT) printf(",");
7097 -    printf("%d}", (code[1] << 8) + code[2]);
7098 -    if (*code == OP_NOTMINUPTO) printf("?");
7099 -    code += 3;
7100 -    break;
7101 -
7102 -    case OP_REF:
7103 -    printf("    \\%d", (code[1] << 8) | code[2]);
7104 -    code += 3;
7105 -    goto CLASS_REF_REPEAT;
7106 -
7107 -    case OP_CLASS:
7108 -      {
7109 -      int i, min, max;
7110 -      code++;
7111 -      printf("    [");
7112 -
7113 -      for (i = 0; i < 256; i++)
7114 -        {
7115 -        if ((code[i/8] & (1 << (i&7))) != 0)
7116 -          {
7117 -          int j;
7118 -          for (j = i+1; j < 256; j++)
7119 -            if ((code[j/8] & (1 << (j&7))) == 0) break;
7120 -          if (i == '-' || i == ']') printf("\\");
7121 -          if (isprint(i)) printf("%c", i); else printf("\\x%02x", i);
7122 -          if (--j > i)
7123 -            {
7124 -            printf("-");
7125 -            if (j == '-' || j == ']') printf("\\");
7126 -            if (isprint(j)) printf("%c", j); else printf("\\x%02x", j);
7127 -            }
7128 -          i = j;
7129 -          }
7130 -        }
7131 -      printf("]");
7132 -      code += 32;
7133 -
7134 -      CLASS_REF_REPEAT:
7135 -
7136 -      switch(*code)
7137 -        {
7138 -        case OP_CRSTAR:
7139 -        case OP_CRMINSTAR:
7140 -        case OP_CRPLUS:
7141 -        case OP_CRMINPLUS:
7142 -        case OP_CRQUERY:
7143 -        case OP_CRMINQUERY:
7144 -        printf("%s", OP_names[*code]);
7145 -        break;
7146 -
7147 -        case OP_CRRANGE:
7148 -        case OP_CRMINRANGE:
7149 -        min = (code[1] << 8) + code[2];
7150 -        max = (code[3] << 8) + code[4];
7151 -        if (max == 0) printf("{%d,}", min);
7152 -        else printf("{%d,%d}", min, max);
7153 -        if (*code == OP_CRMINRANGE) printf("?");
7154 -        code += 4;
7155 -        break;
7156 -
7157 -        default:
7158 -        code--;
7159 -        }
7160 -      }
7161 -    break;
7162 -
7163 -    /* Anything else is just a one-node item */
7164 -
7165 -    default:
7166 -    printf("    %s", OP_names[*code]);
7167 -    break;
7168 -    }
7169 -
7170 -  code++;
7171 -  printf("\n");
7172 -  }
7173 -printf("------------------------------------------------------------------\n");
7174 -
7175 -/* This check is done here in the debugging case so that the code that
7176 -was compiled can be seen. */
7177 -
7178 -if (code - re->code > length)
7179 -  {
7180 -  *errorptr = ERR23;
7181 -  (pcre_free)(re);
7182 -  *erroroffset = ptr - (uschar *)pattern;
7183 -  return NULL;
7184 -  }
7185 -#endif
7186 -
7187 -return (pcre *)re;
7188 -}
7189 -
7190 -
7191 -
7192 -/*************************************************
7193 -*          Match a back-reference                *
7194 -*************************************************/
7195 -
7196 -/* If a back reference hasn't been set, the length that is passed is greater
7197 -than the number of characters left in the string, so the match fails.
7198 -
7199 -Arguments:
7200 -  offset      index into the offset vector
7201 -  eptr        points into the subject
7202 -  length      length to be matched
7203 -  md          points to match data block
7204 -  ims         the ims flags
7205 -
7206 -Returns:      TRUE if matched
7207 -*/
7208 -
7209 -static BOOL
7210 -match_ref(int offset, register const uschar *eptr, int length, match_data *md,
7211 -  unsigned long int ims)
7212 -{
7213 -const uschar *p = md->start_subject + md->offset_vector[offset];
7214 -
7215 -#ifdef DEBUG
7216 -if (eptr >= md->end_subject)
7217 -  printf("matching subject <null>");
7218 -else
7219 -  {
7220 -  printf("matching subject ");
7221 -  pchars(eptr, length, TRUE, md);
7222 -  }
7223 -printf(" against backref ");
7224 -pchars(p, length, FALSE, md);
7225 -printf("\n");
7226 -#endif
7227 -
7228 -/* Always fail if not enough characters left */
7229 -
7230 -if (length > md->end_subject - eptr) return FALSE;
7231 -
7232 -/* Separate the caselesss case for speed */
7233 -
7234 -if ((ims & PCRE_CASELESS) != 0)
7235 -  {
7236 -  while (length-- > 0)
7237 -    if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE;
7238 -  }
7239 -else
7240 -  { while (length-- > 0) if (*p++ != *eptr++) return FALSE; }
7241 -
7242 -return TRUE;
7243 -}
7244 -
7245 -
7246 -
7247 -/*************************************************
7248 -*         Match from current position            *
7249 -*************************************************/
7250 -
7251 -/* On entry ecode points to the first opcode, and eptr to the first character
7252 -in the subject string, while eptrb holds the value of eptr at the start of the
7253 -last bracketed group - used for breaking infinite loops matching zero-length
7254 -strings.
7255 -
7256 -Arguments:
7257 -   eptr        pointer in subject
7258 -   ecode       position in code
7259 -   offset_top  current top pointer
7260 -   md          pointer to "static" info for the match
7261 -   ims         current /i, /m, and /s options
7262 -   eptrb       pointer to chain of blocks containing eptr at start of
7263 -                 brackets - for testing for empty matches
7264 -   flags       can contain
7265 -                 match_condassert - this is an assertion condition
7266 -                 match_isgroup - this is the start of a bracketed group
7267 -
7268 -Returns:       TRUE if matched
7269 -*/
7270 -
7271 -static BOOL
7272 -match(register const uschar *eptr, register const uschar *ecode,
7273 -  int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb,
7274 -  int flags)
7275 -{
7276 -unsigned long int original_ims = ims;   /* Save for resetting on ')' */
7277 -eptrblock newptrb;
7278 -
7279 -/* At the start of a bracketed group, add the current subject pointer to the
7280 -stack of such pointers, to be re-instated at the end of the group when we hit
7281 -the closing ket. When match() is called in other circumstances, we don't add to
7282 -the stack. */
7283 -
7284 -if ((flags & match_isgroup) != 0)
7285 -  {
7286 -  newptrb.prev = eptrb;
7287 -  newptrb.saved_eptr = eptr;
7288 -  eptrb = &newptrb;
7289 -  }
7290 -
7291 -/* Now start processing the operations. */
7292 -
7293 -for (;;)
7294 -  {
7295 -  int op = (int)*ecode;
7296 -  int min, max, ctype;
7297 -  register int i;
7298 -  register int c;
7299 -  BOOL minimize = FALSE;
7300 -
7301 -  /* Opening capturing bracket. If there is space in the offset vector, save
7302 -  the current subject position in the working slot at the top of the vector. We
7303 -  mustn't change the current values of the data slot, because they may be set
7304 -  from a previous iteration of this group, and be referred to by a reference
7305 -  inside the group.
7306 -
7307 -  If the bracket fails to match, we need to restore this value and also the
7308 -  values of the final offsets, in case they were set by a previous iteration of
7309 -  the same bracket.
7310 -
7311 -  If there isn't enough space in the offset vector, treat this as if it were a
7312 -  non-capturing bracket. Don't worry about setting the flag for the error case
7313 -  here; that is handled in the code for KET. */
7314 -
7315 -  if (op > OP_BRA)
7316 -    {
7317 -    int offset;
7318 -    int number = op - OP_BRA;
7319 -
7320 -    /* For extended extraction brackets (large number), we have to fish out the
7321 -    number from a dummy opcode at the start. */
7322 -
7323 -    if (number > EXTRACT_BASIC_MAX) number = (ecode[4] << 8) | ecode[5];
7324 -    offset = number << 1;
7325 -
7326 -#ifdef DEBUG
7327 -    printf("start bracket %d subject=", number);
7328 -    pchars(eptr, 16, TRUE, md);
7329 -    printf("\n");
7330 -#endif
7331 -
7332 -    if (offset < md->offset_max)
7333 -      {
7334 -      int save_offset1 = md->offset_vector[offset];
7335 -      int save_offset2 = md->offset_vector[offset+1];
7336 -      int save_offset3 = md->offset_vector[md->offset_end - number];
7337 -
7338 -      DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3));
7339 -      md->offset_vector[md->offset_end - number] = eptr - md->start_subject;
7340 -
7341 -      do
7342 -        {
7343 -        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
7344 -          return TRUE;
7345 -        ecode += (ecode[1] << 8) + ecode[2];
7346 -        }
7347 -      while (*ecode == OP_ALT);
7348 -
7349 -      DPRINTF(("bracket %d failed\n", number));
7350 -
7351 -      md->offset_vector[offset] = save_offset1;
7352 -      md->offset_vector[offset+1] = save_offset2;
7353 -      md->offset_vector[md->offset_end - number] = save_offset3;
7354 -
7355 -      return FALSE;
7356 -      }
7357 -
7358 -    /* Insufficient room for saving captured contents */
7359 -
7360 -    else op = OP_BRA;
7361 -    }
7362 -
7363 -  /* Other types of node can be handled by a switch */
7364 -
7365 -  switch(op)
7366 -    {
7367 -    case OP_BRA:     /* Non-capturing bracket: optimized */
7368 -    DPRINTF(("start bracket 0\n"));
7369 -    do
7370 -      {
7371 -      if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
7372 -        return TRUE;
7373 -      ecode += (ecode[1] << 8) + ecode[2];
7374 -      }
7375 -    while (*ecode == OP_ALT);
7376 -    DPRINTF(("bracket 0 failed\n"));
7377 -    return FALSE;
7378 -
7379 -    /* Conditional group: compilation checked that there are no more than
7380 -    two branches. If the condition is false, skipping the first branch takes us
7381 -    past the end if there is only one branch, but that's OK because that is
7382 -    exactly what going to the ket would do. */
7383 -
7384 -    case OP_COND:
7385 -    if (ecode[3] == OP_CREF)         /* Condition is extraction test */
7386 -      {
7387 -      int offset = (ecode[4] << 9) | (ecode[5] << 1); /* Doubled ref number */
7388 -      return match(eptr,
7389 -        ecode + ((offset < offset_top && md->offset_vector[offset] >= 0)?
7390 -          6 : 3 + (ecode[1] << 8) + ecode[2]),
7391 -        offset_top, md, ims, eptrb, match_isgroup);
7392 -      }
7393 -
7394 -    /* The condition is an assertion. Call match() to evaluate it - setting
7395 -    the final argument TRUE causes it to stop at the end of an assertion. */
7396 -
7397 -    else
7398 -      {
7399 -      if (match(eptr, ecode+3, offset_top, md, ims, NULL,
7400 -          match_condassert | match_isgroup))
7401 -        {
7402 -        ecode += 3 + (ecode[4] << 8) + ecode[5];
7403 -        while (*ecode == OP_ALT) ecode += (ecode[1] << 8) + ecode[2];
7404 -        }
7405 -      else ecode += (ecode[1] << 8) + ecode[2];
7406 -      return match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup);
7407 -      }
7408 -    /* Control never reaches here */
7409 -
7410 -    /* Skip over conditional reference or large extraction number data if
7411 -    encountered. */
7412 -
7413 -    case OP_CREF:
7414 -    case OP_BRANUMBER:
7415 -    ecode += 3;
7416 -    break;
7417 -
7418 -    /* End of the pattern. If PCRE_NOTEMPTY is set, fail if we have matched
7419 -    an empty string - recursion will then try other alternatives, if any. */
7420 -
7421 -    case OP_END:
7422 -    if (md->notempty && eptr == md->start_match) return FALSE;
7423 -    md->end_match_ptr = eptr;          /* Record where we ended */
7424 -    md->end_offset_top = offset_top;   /* and how many extracts were taken */
7425 -    return TRUE;
7426 -
7427 -    /* Change option settings */
7428 -
7429 -    case OP_OPT:
7430 -    ims = ecode[1];
7431 -    ecode += 2;
7432 -    DPRINTF(("ims set to %02lx\n", ims));
7433 -    break;
7434 -
7435 -    /* Assertion brackets. Check the alternative branches in turn - the
7436 -    matching won't pass the KET for an assertion. If any one branch matches,
7437 -    the assertion is true. Lookbehind assertions have an OP_REVERSE item at the
7438 -    start of each branch to move the current point backwards, so the code at
7439 -    this level is identical to the lookahead case. */
7440 -
7441 -    case OP_ASSERT:
7442 -    case OP_ASSERTBACK:
7443 -    do
7444 -      {
7445 -      if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup)) break;
7446 -      ecode += (ecode[1] << 8) + ecode[2];
7447 -      }
7448 -    while (*ecode == OP_ALT);
7449 -    if (*ecode == OP_KET) return FALSE;
7450 -
7451 -    /* If checking an assertion for a condition, return TRUE. */
7452 -
7453 -    if ((flags & match_condassert) != 0) return TRUE;
7454 -
7455 -    /* Continue from after the assertion, updating the offsets high water
7456 -    mark, since extracts may have been taken during the assertion. */
7457 -
7458 -    do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
7459 -    ecode += 3;
7460 -    offset_top = md->end_offset_top;
7461 -    continue;
7462 -
7463 -    /* Negative assertion: all branches must fail to match */
7464 -
7465 -    case OP_ASSERT_NOT:
7466 -    case OP_ASSERTBACK_NOT:
7467 -    do
7468 -      {
7469 -      if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup))
7470 -        return FALSE;
7471 -      ecode += (ecode[1] << 8) + ecode[2];
7472 -      }
7473 -    while (*ecode == OP_ALT);
7474 -
7475 -    if ((flags & match_condassert) != 0) return TRUE;
7476 -
7477 -    ecode += 3;
7478 -    continue;
7479 -
7480 -    /* Move the subject pointer back. This occurs only at the start of
7481 -    each branch of a lookbehind assertion. If we are too close to the start to
7482 -    move back, this match function fails. When working with UTF-8 we move
7483 -    back a number of characters, not bytes. */
7484 -
7485 -    case OP_REVERSE:
7486 -#ifdef SUPPORT_UTF8
7487 -    c = (ecode[1] << 8) + ecode[2];
7488 -    for (i = 0; i < c; i++)
7489 -      {
7490 -      eptr--;
7491 -      BACKCHAR(eptr)
7492 -      }
7493 -#else
7494 -    eptr -= (ecode[1] << 8) + ecode[2];
7495 -#endif
7496 -
7497 -    if (eptr < md->start_subject) return FALSE;
7498 -    ecode += 3;
7499 -    break;
7500 -
7501 -    /* Recursion matches the current regex, nested. If there are any capturing
7502 -    brackets started but not finished, we have to save their starting points
7503 -    and reinstate them after the recursion. However, we don't know how many
7504 -    such there are (offset_top records the completed total) so we just have
7505 -    to save all the potential data. There may be up to 99 such values, which
7506 -    is a bit large to put on the stack, but using malloc for small numbers
7507 -    seems expensive. As a compromise, the stack is used when there are fewer
7508 -    than 16 values to store; otherwise malloc is used. A problem is what to do
7509 -    if the malloc fails ... there is no way of returning to the top level with
7510 -    an error. Save the top 15 values on the stack, and accept that the rest
7511 -    may be wrong. */
7512 -
7513 -    case OP_RECURSE:
7514 -      {
7515 -      BOOL rc;
7516 -      int *save;
7517 -      int stacksave[15];
7518 -
7519 -      c = md->offset_max;
7520 -
7521 -      if (c < 16) save = stacksave; else
7522 -        {
7523 -        save = (int *)(pcre_malloc)((c+1) * sizeof(int));
7524 -        if (save == NULL)
7525 -          {
7526 -          save = stacksave;
7527 -          c = 15;
7528 -          }
7529 -        }
7530 -
7531 -      for (i = 1; i <= c; i++)
7532 -        save[i] = md->offset_vector[md->offset_end - i];
7533 -      rc = match(eptr, md->start_pattern, offset_top, md, ims, eptrb,
7534 -        match_isgroup);
7535 -      for (i = 1; i <= c; i++)
7536 -        md->offset_vector[md->offset_end - i] = save[i];
7537 -      if (save != stacksave) (pcre_free)(save);
7538 -      if (!rc) return FALSE;
7539 -
7540 -      /* In case the recursion has set more capturing values, save the final
7541 -      number, then move along the subject till after the recursive match,
7542 -      and advance one byte in the pattern code. */
7543 -
7544 -      offset_top = md->end_offset_top;
7545 -      eptr = md->end_match_ptr;
7546 -      ecode++;
7547 -      }
7548 -    break;
7549 -
7550 -    /* "Once" brackets are like assertion brackets except that after a match,
7551 -    the point in the subject string is not moved back. Thus there can never be
7552 -    a move back into the brackets. Check the alternative branches in turn - the
7553 -    matching won't pass the KET for this kind of subpattern. If any one branch
7554 -    matches, we carry on as at the end of a normal bracket, leaving the subject
7555 -    pointer. */
7556 -
7557 -    case OP_ONCE:
7558 -      {
7559 -      const uschar *prev = ecode;
7560 -      const uschar *saved_eptr = eptr;
7561 -
7562 -      do
7563 -        {
7564 -        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
7565 -          break;
7566 -        ecode += (ecode[1] << 8) + ecode[2];
7567 -        }
7568 -      while (*ecode == OP_ALT);
7569 -
7570 -      /* If hit the end of the group (which could be repeated), fail */
7571 -
7572 -      if (*ecode != OP_ONCE && *ecode != OP_ALT) return FALSE;
7573 -
7574 -      /* Continue as from after the assertion, updating the offsets high water
7575 -      mark, since extracts may have been taken. */
7576 -
7577 -      do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
7578 -
7579 -      offset_top = md->end_offset_top;
7580 -      eptr = md->end_match_ptr;
7581 -
7582 -      /* For a non-repeating ket, just continue at this level. This also
7583 -      happens for a repeating ket if no characters were matched in the group.
7584 -      This is the forcible breaking of infinite loops as implemented in Perl
7585 -      5.005. If there is an options reset, it will get obeyed in the normal
7586 -      course of events. */
7587 -
7588 -      if (*ecode == OP_KET || eptr == saved_eptr)
7589 -        {
7590 -        ecode += 3;
7591 -        break;
7592 -        }
7593 -
7594 -      /* The repeating kets try the rest of the pattern or restart from the
7595 -      preceding bracket, in the appropriate order. We need to reset any options
7596 -      that changed within the bracket before re-running it, so check the next
7597 -      opcode. */
7598 -
7599 -      if (ecode[3] == OP_OPT)
7600 -        {
7601 -        ims = (ims & ~PCRE_IMS) | ecode[4];
7602 -        DPRINTF(("ims set to %02lx at group repeat\n", ims));
7603 -        }
7604 -
7605 -      if (*ecode == OP_KETRMIN)
7606 -        {
7607 -        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
7608 -            match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
7609 -              return TRUE;
7610 -        }
7611 -      else  /* OP_KETRMAX */
7612 -        {
7613 -        if (match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup) ||
7614 -            match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) return TRUE;
7615 -        }
7616 -      }
7617 -    return FALSE;
7618 -
7619 -    /* An alternation is the end of a branch; scan along to find the end of the
7620 -    bracketed group and go to there. */
7621 -
7622 -    case OP_ALT:
7623 -    do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
7624 -    break;
7625 -
7626 -    /* BRAZERO and BRAMINZERO occur just before a bracket group, indicating
7627 -    that it may occur zero times. It may repeat infinitely, or not at all -
7628 -    i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper
7629 -    repeat limits are compiled as a number of copies, with the optional ones
7630 -    preceded by BRAZERO or BRAMINZERO. */
7631 -
7632 -    case OP_BRAZERO:
7633 -      {
7634 -      const uschar *next = ecode+1;
7635 -      if (match(eptr, next, offset_top, md, ims, eptrb, match_isgroup))
7636 -        return TRUE;
7637 -      do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
7638 -      ecode = next + 3;
7639 -      }
7640 -    break;
7641 -
7642 -    case OP_BRAMINZERO:
7643 -      {
7644 -      const uschar *next = ecode+1;
7645 -      do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
7646 -      if (match(eptr, next+3, offset_top, md, ims, eptrb, match_isgroup))
7647 -        return TRUE;
7648 -      ecode++;
7649 -      }
7650 -    break;
7651 -
7652 -    /* End of a group, repeated or non-repeating. If we are at the end of
7653 -    an assertion "group", stop matching and return TRUE, but record the
7654 -    current high water mark for use by positive assertions. Do this also
7655 -    for the "once" (not-backup up) groups. */
7656 -
7657 -    case OP_KET:
7658 -    case OP_KETRMIN:
7659 -    case OP_KETRMAX:
7660 -      {
7661 -      const uschar *prev = ecode - (ecode[1] << 8) - ecode[2];
7662 -      const uschar *saved_eptr = eptrb->saved_eptr;
7663 -
7664 -      eptrb = eptrb->prev;    /* Back up the stack of bracket start pointers */
7665 -
7666 -      if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||
7667 -          *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT ||
7668 -          *prev == OP_ONCE)
7669 -        {
7670 -        md->end_match_ptr = eptr;      /* For ONCE */
7671 -        md->end_offset_top = offset_top;
7672 -        return TRUE;
7673 -        }
7674 -
7675 -      /* In all other cases except a conditional group we have to check the
7676 -      group number back at the start and if necessary complete handling an
7677 -      extraction by setting the offsets and bumping the high water mark. */
7678 -
7679 -      if (*prev != OP_COND)
7680 -        {
7681 -        int offset;
7682 -        int number = *prev - OP_BRA;
7683 -
7684 -        /* For extended extraction brackets (large number), we have to fish out
7685 -        the number from a dummy opcode at the start. */
7686 -
7687 -        if (number > EXTRACT_BASIC_MAX) number = (prev[4] << 8) | prev[5];
7688 -        offset = number << 1;
7689 -
7690 -#ifdef DEBUG
7691 -        printf("end bracket %d", number);
7692 -        printf("\n");
7693 -#endif
7694 -
7695 -        if (number > 0)
7696 -          {
7697 -          if (offset >= md->offset_max) md->offset_overflow = TRUE; else
7698 -            {
7699 -            md->offset_vector[offset] =
7700 -              md->offset_vector[md->offset_end - number];
7701 -            md->offset_vector[offset+1] = eptr - md->start_subject;
7702 -            if (offset_top <= offset) offset_top = offset + 2;
7703 -            }
7704 -          }
7705 -        }
7706 -
7707 -      /* Reset the value of the ims flags, in case they got changed during
7708 -      the group. */
7709 -
7710 -      ims = original_ims;
7711 -      DPRINTF(("ims reset to %02lx\n", ims));
7712 -
7713 -      /* For a non-repeating ket, just continue at this level. This also
7714 -      happens for a repeating ket if no characters were matched in the group.
7715 -      This is the forcible breaking of infinite loops as implemented in Perl
7716 -      5.005. If there is an options reset, it will get obeyed in the normal
7717 -      course of events. */
7718 -
7719 -      if (*ecode == OP_KET || eptr == saved_eptr)
7720 -        {
7721 -        ecode += 3;
7722 -        break;
7723 -        }
7724 -
7725 -      /* The repeating kets try the rest of the pattern or restart from the
7726 -      preceding bracket, in the appropriate order. */
7727 -
7728 -      if (*ecode == OP_KETRMIN)
7729 -        {
7730 -        if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
7731 -            match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
7732 -              return TRUE;
7733 -        }
7734 -      else  /* OP_KETRMAX */
7735 -        {
7736 -        if (match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup) ||
7737 -            match(eptr, ecode+3, offset_top, md, ims, eptrb, 0)) return TRUE;
7738 -        }
7739 -      }
7740 -    return FALSE;
7741 -
7742 -    /* Start of subject unless notbol, or after internal newline if multiline */
7743 -
7744 -    case OP_CIRC:
7745 -    if (md->notbol && eptr == md->start_subject) return FALSE;
7746 -    if ((ims & PCRE_MULTILINE) != 0)
7747 -      {
7748 -      if (eptr != md->start_subject && eptr[-1] != NEWLINE) return FALSE;
7749 -      ecode++;
7750 -      break;
7751 -      }
7752 -    /* ... else fall through */
7753 -
7754 -    /* Start of subject assertion */
7755 -
7756 -    case OP_SOD:
7757 -    if (eptr != md->start_subject) return FALSE;
7758 -    ecode++;
7759 -    break;
7760 -
7761 -    /* Assert before internal newline if multiline, or before a terminating
7762 -    newline unless endonly is set, else end of subject unless noteol is set. */
7763 -
7764 -    case OP_DOLL:
7765 -    if ((ims & PCRE_MULTILINE) != 0)
7766 -      {
7767 -      if (eptr < md->end_subject) { if (*eptr != NEWLINE) return FALSE; }
7768 -        else { if (md->noteol) return FALSE; }
7769 -      ecode++;
7770 -      break;
7771 -      }
7772 -    else
7773 -      {
7774 -      if (md->noteol) return FALSE;
7775 -      if (!md->endonly)
7776 -        {
7777 -        if (eptr < md->end_subject - 1 ||
7778 -           (eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE;
7779 -
7780 -        ecode++;
7781 -        break;
7782 -        }
7783 -      }
7784 -    /* ... else fall through */
7785 -
7786 -    /* End of subject assertion (\z) */
7787 -
7788 -    case OP_EOD:
7789 -    if (eptr < md->end_subject) return FALSE;
7790 -    ecode++;
7791 -    break;
7792 -
7793 -    /* End of subject or ending \n assertion (\Z) */
7794 -
7795 -    case OP_EODN:
7796 -    if (eptr < md->end_subject - 1 ||
7797 -       (eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE;
7798 -    ecode++;
7799 -    break;
7800 -
7801 -    /* Word boundary assertions */
7802 -
7803 -    case OP_NOT_WORD_BOUNDARY:
7804 -    case OP_WORD_BOUNDARY:
7805 -      {
7806 -      BOOL prev_is_word = (eptr != md->start_subject) &&
7807 -        ((md->ctypes[eptr[-1]] & ctype_word) != 0);
7808 -      BOOL cur_is_word = (eptr < md->end_subject) &&
7809 -        ((md->ctypes[*eptr] & ctype_word) != 0);
7810 -      if ((*ecode++ == OP_WORD_BOUNDARY)?
7811 -           cur_is_word == prev_is_word : cur_is_word != prev_is_word)
7812 -        return FALSE;
7813 -      }
7814 -    break;
7815 -
7816 -    /* Match a single character type; inline for speed */
7817 -
7818 -    case OP_ANY:
7819 -    if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == NEWLINE)
7820 -      return FALSE;
7821 -    if (eptr++ >= md->end_subject) return FALSE;
7822 -#ifdef SUPPORT_UTF8
7823 -    if (md->utf8)
7824 -      while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
7825 -#endif
7826 -    ecode++;
7827 -    break;
7828 -
7829 -    case OP_NOT_DIGIT:
7830 -    if (eptr >= md->end_subject ||
7831 -       (md->ctypes[*eptr++] & ctype_digit) != 0)
7832 -      return FALSE;
7833 -    ecode++;
7834 -    break;
7835 -
7836 -    case OP_DIGIT:
7837 -    if (eptr >= md->end_subject ||
7838 -       (md->ctypes[*eptr++] & ctype_digit) == 0)
7839 -      return FALSE;
7840 -    ecode++;
7841 -    break;
7842 -
7843 -    case OP_NOT_WHITESPACE:
7844 -    if (eptr >= md->end_subject ||
7845 -       (md->ctypes[*eptr++] & ctype_space) != 0)
7846 -      return FALSE;
7847 -    ecode++;
7848 -    break;
7849 -
7850 -    case OP_WHITESPACE:
7851 -    if (eptr >= md->end_subject ||
7852 -       (md->ctypes[*eptr++] & ctype_space) == 0)
7853 -      return FALSE;
7854 -    ecode++;
7855 -    break;
7856 -
7857 -    case OP_NOT_WORDCHAR:
7858 -    if (eptr >= md->end_subject ||
7859 -       (md->ctypes[*eptr++] & ctype_word) != 0)
7860 -      return FALSE;
7861 -    ecode++;
7862 -    break;
7863 -
7864 -    case OP_WORDCHAR:
7865 -    if (eptr >= md->end_subject ||
7866 -       (md->ctypes[*eptr++] & ctype_word) == 0)
7867 -      return FALSE;
7868 -    ecode++;
7869 -    break;
7870 -
7871 -    /* Match a back reference, possibly repeatedly. Look past the end of the
7872 -    item to see if there is repeat information following. The code is similar
7873 -    to that for character classes, but repeated for efficiency. Then obey
7874 -    similar code to character type repeats - written out again for speed.
7875 -    However, if the referenced string is the empty string, always treat
7876 -    it as matched, any number of times (otherwise there could be infinite
7877 -    loops). */
7878 -
7879 -    case OP_REF:
7880 -      {
7881 -      int length;
7882 -      int offset = (ecode[1] << 9) | (ecode[2] << 1); /* Doubled ref number */
7883 -      ecode += 3;                                     /* Advance past item */
7884 -
7885 -      /* If the reference is unset, set the length to be longer than the amount
7886 -      of subject left; this ensures that every attempt at a match fails. We
7887 -      can't just fail here, because of the possibility of quantifiers with zero
7888 -      minima. */
7889 -
7890 -      length = (offset >= offset_top || md->offset_vector[offset] < 0)?
7891 -        md->end_subject - eptr + 1 :
7892 -        md->offset_vector[offset+1] - md->offset_vector[offset];
7893 -
7894 -      /* Set up for repetition, or handle the non-repeated case */
7895 -
7896 -      switch (*ecode)
7897 -        {
7898 -        case OP_CRSTAR:
7899 -        case OP_CRMINSTAR:
7900 -        case OP_CRPLUS:
7901 -        case OP_CRMINPLUS:
7902 -        case OP_CRQUERY:
7903 -        case OP_CRMINQUERY:
7904 -        c = *ecode++ - OP_CRSTAR;
7905 -        minimize = (c & 1) != 0;
7906 -        min = rep_min[c];                 /* Pick up values from tables; */
7907 -        max = rep_max[c];                 /* zero for max => infinity */
7908 -        if (max == 0) max = INT_MAX;
7909 -        break;
7910 -
7911 -        case OP_CRRANGE:
7912 -        case OP_CRMINRANGE:
7913 -        minimize = (*ecode == OP_CRMINRANGE);
7914 -        min = (ecode[1] << 8) + ecode[2];
7915 -        max = (ecode[3] << 8) + ecode[4];
7916 -        if (max == 0) max = INT_MAX;
7917 -        ecode += 5;
7918 -        break;
7919 -
7920 -        default:               /* No repeat follows */
7921 -        if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
7922 -        eptr += length;
7923 -        continue;              /* With the main loop */
7924 -        }
7925 -
7926 -      /* If the length of the reference is zero, just continue with the
7927 -      main loop. */
7928 -
7929 -      if (length == 0) continue;
7930 -
7931 -      /* First, ensure the minimum number of matches are present. We get back
7932 -      the length of the reference string explicitly rather than passing the
7933 -      address of eptr, so that eptr can be a register variable. */
7934 -
7935 -      for (i = 1; i <= min; i++)
7936 -        {
7937 -        if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
7938 -        eptr += length;
7939 -        }
7940 -
7941 -      /* If min = max, continue at the same level without recursion.
7942 -      They are not both allowed to be zero. */
7943 -
7944 -      if (min == max) continue;
7945 -
7946 -      /* If minimizing, keep trying and advancing the pointer */
7947 -
7948 -      if (minimize)
7949 -        {
7950 -        for (i = min;; i++)
7951 -          {
7952 -          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
7953 -            return TRUE;
7954 -          if (i >= max || !match_ref(offset, eptr, length, md, ims))
7955 -            return FALSE;
7956 -          eptr += length;
7957 -          }
7958 -        /* Control never gets here */
7959 -        }
7960 -
7961 -      /* If maximizing, find the longest string and work backwards */
7962 -
7963 -      else
7964 -        {
7965 -        const uschar *pp = eptr;
7966 -        for (i = min; i < max; i++)
7967 -          {
7968 -          if (!match_ref(offset, eptr, length, md, ims)) break;
7969 -          eptr += length;
7970 -          }
7971 -        while (eptr >= pp)
7972 -          {
7973 -          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
7974 -            return TRUE;
7975 -          eptr -= length;
7976 -          }
7977 -        return FALSE;
7978 -        }
7979 -      }
7980 -    /* Control never gets here */
7981 -
7982 -
7983 -
7984 -    /* Match a character class, possibly repeatedly. Look past the end of the
7985 -    item to see if there is repeat information following. Then obey similar
7986 -    code to character type repeats - written out again for speed. */
7987 -
7988 -    case OP_CLASS:
7989 -      {
7990 -      const uschar *data = ecode + 1;  /* Save for matching */
7991 -      ecode += 33;                     /* Advance past the item */
7992 -
7993 -      switch (*ecode)
7994 -        {
7995 -        case OP_CRSTAR:
7996 -        case OP_CRMINSTAR:
7997 -        case OP_CRPLUS:
7998 -        case OP_CRMINPLUS:
7999 -        case OP_CRQUERY:
8000 -        case OP_CRMINQUERY:
8001 -        c = *ecode++ - OP_CRSTAR;
8002 -        minimize = (c & 1) != 0;
8003 -        min = rep_min[c];                 /* Pick up values from tables; */
8004 -        max = rep_max[c];                 /* zero for max => infinity */
8005 -        if (max == 0) max = INT_MAX;
8006 -        break;
8007 -
8008 -        case OP_CRRANGE:
8009 -        case OP_CRMINRANGE:
8010 -        minimize = (*ecode == OP_CRMINRANGE);
8011 -        min = (ecode[1] << 8) + ecode[2];
8012 -        max = (ecode[3] << 8) + ecode[4];
8013 -        if (max == 0) max = INT_MAX;
8014 -        ecode += 5;
8015 -        break;
8016 -
8017 -        default:               /* No repeat follows */
8018 -        min = max = 1;
8019 -        break;
8020 -        }
8021 -
8022 -      /* First, ensure the minimum number of matches are present. */
8023 -
8024 -      for (i = 1; i <= min; i++)
8025 -        {
8026 -        if (eptr >= md->end_subject) return FALSE;
8027 -        GETCHARINC(c, eptr)         /* Get character; increment eptr */
8028 -
8029 -#ifdef SUPPORT_UTF8
8030 -        /* We do not yet support class members > 255 */
8031 -        if (c > 255) return FALSE;
8032 -#endif
8033 -
8034 -        if ((data[c/8] & (1 << (c&7))) != 0) continue;
8035 -        return FALSE;
8036 -        }
8037 -
8038 -      /* If max == min we can continue with the main loop without the
8039 -      need to recurse. */
8040 -
8041 -      if (min == max) continue;
8042 -
8043 -      /* If minimizing, keep testing the rest of the expression and advancing
8044 -      the pointer while it matches the class. */
8045 -
8046 -      if (minimize)
8047 -        {
8048 -        for (i = min;; i++)
8049 -          {
8050 -          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
8051 -            return TRUE;
8052 -          if (i >= max || eptr >= md->end_subject) return FALSE;
8053 -          GETCHARINC(c, eptr)       /* Get character; increment eptr */
8054 -
8055 -#ifdef SUPPORT_UTF8
8056 -          /* We do not yet support class members > 255 */
8057 -          if (c > 255) return FALSE;
8058 -#endif
8059 -          if ((data[c/8] & (1 << (c&7))) != 0) continue;
8060 -          return FALSE;
8061 -          }
8062 -        /* Control never gets here */
8063 -        }
8064 -
8065 -      /* If maximizing, find the longest possible run, then work backwards. */
8066 -
8067 -      else
8068 -        {
8069 -        const uschar *pp = eptr;
8070 -        int len = 1;
8071 -        for (i = min; i < max; i++)
8072 -          {
8073 -          if (eptr >= md->end_subject) break;
8074 -          GETCHARLEN(c, eptr, len)  /* Get character, set length if UTF-8 */
8075 -
8076 -#ifdef SUPPORT_UTF8
8077 -          /* We do not yet support class members > 255 */
8078 -          if (c > 255) break;
8079 -#endif
8080 -          if ((data[c/8] & (1 << (c&7))) == 0) break;
8081 -          eptr += len;
8082 -          }
8083 -
8084 -        while (eptr >= pp)
8085 -          {
8086 -          if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
8087 -            return TRUE;
8088 -
8089 -#ifdef SUPPORT_UTF8
8090 -          BACKCHAR(eptr)
8091 -#endif
8092 -          }
8093 -        return FALSE;
8094 -        }
8095 -      }
8096 -    /* Control never gets here */
8097 -
8098 -    /* Match a run of characters */
8099 -
8100 -    case OP_CHARS:
8101 -      {
8102 -      register int length = ecode[1];
8103 -      ecode += 2;
8104 -
8105 -#ifdef DEBUG    /* Sigh. Some compilers never learn. */
8106 -      if (eptr >= md->end_subject)
8107 -        printf("matching subject <null> against pattern ");
8108 -      else
8109 -        {
8110 -        printf("matching subject ");
8111 -        pchars(eptr, length, TRUE, md);
8112 -        printf(" against pattern ");
8113 -        }
8114 -      pchars(ecode, length, FALSE, md);
8115 -      printf("\n");
8116 -#endif
8117 -
8118 -      if (length > md->end_subject - eptr) return FALSE;
8119 -      if ((ims & PCRE_CASELESS) != 0)
8120 -        {
8121 -        while (length-- > 0)
8122 -          if (md->lcc[*ecode++] != md->lcc[*eptr++])
8123 -            return FALSE;
8124 -        }
8125 -      else
8126 -        {
8127 -        while (length-- > 0) if (*ecode++ != *eptr++) return FALSE;
8128 -        }
8129 -      }
8130 -    break;
8131 -
8132 -    /* Match a single character repeatedly; different opcodes share code. */
8133 -
8134 -    case OP_EXACT:
8135 -    min = max = (ecode[1] << 8) + ecode[2];
8136 -    ecode += 3;
8137 -    goto REPEATCHAR;
8138 -
8139 -    case OP_UPTO:
8140 -    case OP_MINUPTO:
8141 -    min = 0;
8142 -    max = (ecode[1] << 8) + ecode[2];
8143 -    minimize = *ecode == OP_MINUPTO;
8144 -    ecode += 3;
8145 -    goto REPEATCHAR;
8146 -
8147 -    case OP_STAR:
8148 -    case OP_MINSTAR:
8149 -    case OP_PLUS:
8150 -    case OP_MINPLUS:
8151 -    case OP_QUERY:
8152 -    case OP_MINQUERY:
8153 -    c = *ecode++ - OP_STAR;
8154 -    minimize = (c & 1) != 0;
8155 -    min = rep_min[c];                 /* Pick up values from tables; */
8156 -    max = rep_max[c];                 /* zero for max => infinity */
8157 -    if (max == 0) max = INT_MAX;
8158 -
8159 -    /* Common code for all repeated single-character matches. We can give
8160 -    up quickly if there are fewer than the minimum number of characters left in
8161 -    the subject. */
8162 -
8163 -    REPEATCHAR:
8164 -    if (min > md->end_subject - eptr) return FALSE;
8165 -    c = *ecode++;
8166 -
8167 -    /* The code is duplicated for the caseless and caseful cases, for speed,
8168 -    since matching characters is likely to be quite common. First, ensure the
8169 -    minimum number of matches are present. If min = max, continue at the same
8170 -    level without recursing. Otherwise, if minimizing, keep trying the rest of
8171 -    the expression and advancing one matching character if failing, up to the
8172 -    maximum. Alternatively, if maximizing, find the maximum number of
8173 -    characters and work backwards. */
8174 -
8175 -    DPRINTF(("matching %c{%d,%d} against subject %.*s\n", c, min, max,
8176 -      max, eptr));
8177 -
8178 -    if ((ims & PCRE_CASELESS) != 0)
8179 -      {
8180 -      c = md->lcc[c];
8181 -      for (i = 1; i <= min; i++)
8182 -        if (c != md->lcc[*eptr++]) return FALSE;
8183 -      if (min == max) continue;
8184 -      if (minimize)
8185 -        {
8186 -        for (i = min;; i++)
8187 -          {
8188 -          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
8189 -            return TRUE;
8190 -          if (i >= max || eptr >= md->end_subject ||
8191 -              c != md->lcc[*eptr++])
8192 -            return FALSE;
8193 -          }
8194 -        /* Control never gets here */
8195 -        }
8196 -      else
8197 -        {
8198 -        const uschar *pp = eptr;
8199 -        for (i = min; i < max; i++)
8200 -          {
8201 -          if (eptr >= md->end_subject || c != md->lcc[*eptr]) break;
8202 -          eptr++;
8203 -          }
8204 -        while (eptr >= pp)
8205 -          if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
8206 -            return TRUE;
8207 -        return FALSE;
8208 -        }
8209 -      /* Control never gets here */
8210 -      }
8211 -
8212 -    /* Caseful comparisons */
8213 -
8214 -    else
8215 -      {
8216 -      for (i = 1; i <= min; i++) if (c != *eptr++) return FALSE;
8217 -      if (min == max) continue;
8218 -      if (minimize)
8219 -        {
8220 -        for (i = min;; i++)
8221 -          {
8222 -          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
8223 -            return TRUE;
8224 -          if (i >= max || eptr >= md->end_subject || c != *eptr++) return FALSE;
8225 -          }
8226 -        /* Control never gets here */
8227 -        }
8228 -      else
8229 -        {
8230 -        const uschar *pp = eptr;
8231 -        for (i = min; i < max; i++)
8232 -          {
8233 -          if (eptr >= md->end_subject || c != *eptr) break;
8234 -          eptr++;
8235 -          }
8236 -        while (eptr >= pp)
8237 -         if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
8238 -           return TRUE;
8239 -        return FALSE;
8240 -        }
8241 -      }
8242 -    /* Control never gets here */
8243 -
8244 -    /* Match a negated single character */
8245 -
8246 -    case OP_NOT:
8247 -    if (eptr >= md->end_subject) return FALSE;
8248 -    ecode++;
8249 -    if ((ims & PCRE_CASELESS) != 0)
8250 -      {
8251 -      if (md->lcc[*ecode++] == md->lcc[*eptr++]) return FALSE;
8252 -      }
8253 -    else
8254 -      {
8255 -      if (*ecode++ == *eptr++) return FALSE;
8256 -      }
8257 -    break;
8258 -
8259 -    /* Match a negated single character repeatedly. This is almost a repeat of
8260 -    the code for a repeated single character, but I haven't found a nice way of
8261 -    commoning these up that doesn't require a test of the positive/negative
8262 -    option for each character match. Maybe that wouldn't add very much to the
8263 -    time taken, but character matching *is* what this is all about... */
8264 -
8265 -    case OP_NOTEXACT:
8266 -    min = max = (ecode[1] << 8) + ecode[2];
8267 -    ecode += 3;
8268 -    goto REPEATNOTCHAR;
8269 -
8270 -    case OP_NOTUPTO:
8271 -    case OP_NOTMINUPTO:
8272 -    min = 0;
8273 -    max = (ecode[1] << 8) + ecode[2];
8274 -    minimize = *ecode == OP_NOTMINUPTO;
8275 -    ecode += 3;
8276 -    goto REPEATNOTCHAR;
8277 -
8278 -    case OP_NOTSTAR:
8279 -    case OP_NOTMINSTAR:
8280 -    case OP_NOTPLUS:
8281 -    case OP_NOTMINPLUS:
8282 -    case OP_NOTQUERY:
8283 -    case OP_NOTMINQUERY:
8284 -    c = *ecode++ - OP_NOTSTAR;
8285 -    minimize = (c & 1) != 0;
8286 -    min = rep_min[c];                 /* Pick up values from tables; */
8287 -    max = rep_max[c];                 /* zero for max => infinity */
8288 -    if (max == 0) max = INT_MAX;
8289 -
8290 -    /* Common code for all repeated single-character matches. We can give
8291 -    up quickly if there are fewer than the minimum number of characters left in
8292 -    the subject. */
8293 -
8294 -    REPEATNOTCHAR:
8295 -    if (min > md->end_subject - eptr) return FALSE;
8296 -    c = *ecode++;
8297 -
8298 -    /* The code is duplicated for the caseless and caseful cases, for speed,
8299 -    since matching characters is likely to be quite common. First, ensure the
8300 -    minimum number of matches are present. If min = max, continue at the same
8301 -    level without recursing. Otherwise, if minimizing, keep trying the rest of
8302 -    the expression and advancing one matching character if failing, up to the
8303 -    maximum. Alternatively, if maximizing, find the maximum number of
8304 -    characters and work backwards. */
8305 -
8306 -    DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", c, min, max,
8307 -      max, eptr));
8308 -
8309 -    if ((ims & PCRE_CASELESS) != 0)
8310 -      {
8311 -      c = md->lcc[c];
8312 -      for (i = 1; i <= min; i++)
8313 -        if (c == md->lcc[*eptr++]) return FALSE;
8314 -      if (min == max) continue;
8315 -      if (minimize)
8316 -        {
8317 -        for (i = min;; i++)
8318 -          {
8319 -          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
8320 -            return TRUE;
8321 -          if (i >= max || eptr >= md->end_subject ||
8322 -              c == md->lcc[*eptr++])
8323 -            return FALSE;
8324 -          }
8325 -        /* Control never gets here */
8326 -        }
8327 -      else
8328 -        {
8329 -        const uschar *pp = eptr;
8330 -        for (i = min; i < max; i++)
8331 -          {
8332 -          if (eptr >= md->end_subject || c == md->lcc[*eptr]) break;
8333 -          eptr++;
8334 -          }
8335 -        while (eptr >= pp)
8336 -          if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
8337 -            return TRUE;
8338 -        return FALSE;
8339 -        }
8340 -      /* Control never gets here */
8341 -      }
8342 -
8343 -    /* Caseful comparisons */
8344 -
8345 -    else
8346 -      {
8347 -      for (i = 1; i <= min; i++) if (c == *eptr++) return FALSE;
8348 -      if (min == max) continue;
8349 -      if (minimize)
8350 -        {
8351 -        for (i = min;; i++)
8352 -          {
8353 -          if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
8354 -            return TRUE;
8355 -          if (i >= max || eptr >= md->end_subject || c == *eptr++) return FALSE;
8356 -          }
8357 -        /* Control never gets here */
8358 -        }
8359 -      else
8360 -        {
8361 -        const uschar *pp = eptr;
8362 -        for (i = min; i < max; i++)
8363 -          {
8364 -          if (eptr >= md->end_subject || c == *eptr) break;
8365 -          eptr++;
8366 -          }
8367 -        while (eptr >= pp)
8368 -         if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
8369 -           return TRUE;
8370 -        return FALSE;
8371 -        }
8372 -      }
8373 -    /* Control never gets here */
8374 -
8375 -    /* Match a single character type repeatedly; several different opcodes
8376 -    share code. This is very similar to the code for single characters, but we
8377 -    repeat it in the interests of efficiency. */
8378 -
8379 -    case OP_TYPEEXACT:
8380 -    min = max = (ecode[1] << 8) + ecode[2];
8381 -    minimize = TRUE;
8382 -    ecode += 3;
8383 -    goto REPEATTYPE;
8384 -
8385 -    case OP_TYPEUPTO:
8386 -    case OP_TYPEMINUPTO:
8387 -    min = 0;
8388 -    max = (ecode[1] << 8) + ecode[2];
8389 -    minimize = *ecode == OP_TYPEMINUPTO;
8390 -    ecode += 3;
8391 -    goto REPEATTYPE;
8392 -
8393 -    case OP_TYPESTAR:
8394 -    case OP_TYPEMINSTAR:
8395 -    case OP_TYPEPLUS:
8396 -    case OP_TYPEMINPLUS:
8397 -    case OP_TYPEQUERY:
8398 -    case OP_TYPEMINQUERY:
8399 -    c = *ecode++ - OP_TYPESTAR;
8400 -    minimize = (c & 1) != 0;
8401 -    min = rep_min[c];                 /* Pick up values from tables; */
8402 -    max = rep_max[c];                 /* zero for max => infinity */
8403 -    if (max == 0) max = INT_MAX;
8404 -
8405 -    /* Common code for all repeated single character type matches */
8406 -
8407 -    REPEATTYPE:
8408 -    ctype = *ecode++;      /* Code for the character type */
8409 -
8410 -    /* First, ensure the minimum number of matches are present. Use inline
8411 -    code for maximizing the speed, and do the type test once at the start
8412 -    (i.e. keep it out of the loop). Also we can test that there are at least
8413 -    the minimum number of bytes before we start, except when doing '.' in
8414 -    UTF8 mode. Leave the test in in all cases; in the special case we have
8415 -    to test after each character. */
8416 -
8417 -    if (min > md->end_subject - eptr) return FALSE;
8418 -    if (min > 0) switch(ctype)
8419 -      {
8420 -      case OP_ANY:
8421 -#ifdef SUPPORT_UTF8
8422 -      if (md->utf8)
8423 -        {
8424 -        for (i = 1; i <= min; i++)
8425 -          {
8426 -          if (eptr >= md->end_subject ||
8427 -             (*eptr++ == NEWLINE && (ims & PCRE_DOTALL) == 0))
8428 -            return FALSE;
8429 -          while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
8430 -          }
8431 -        break;
8432 -        }
8433 -#endif
8434 -      /* Non-UTF8 can be faster */
8435 -      if ((ims & PCRE_DOTALL) == 0)
8436 -        { for (i = 1; i <= min; i++) if (*eptr++ == NEWLINE) return FALSE; }
8437 -      else eptr += min;
8438 -      break;
8439 -
8440 -      case OP_NOT_DIGIT:
8441 -      for (i = 1; i <= min; i++)
8442 -        if ((md->ctypes[*eptr++] & ctype_digit) != 0) return FALSE;
8443 -      break;
8444 -
8445 -      case OP_DIGIT:
8446 -      for (i = 1; i <= min; i++)
8447 -        if ((md->ctypes[*eptr++] & ctype_digit) == 0) return FALSE;
8448 -      break;
8449 -
8450 -      case OP_NOT_WHITESPACE:
8451 -      for (i = 1; i <= min; i++)
8452 -        if ((md->ctypes[*eptr++] & ctype_space) != 0) return FALSE;
8453 -      break;
8454 -
8455 -      case OP_WHITESPACE:
8456 -      for (i = 1; i <= min; i++)
8457 -        if ((md->ctypes[*eptr++] & ctype_space) == 0) return FALSE;
8458 -      break;
8459 -
8460 -      case OP_NOT_WORDCHAR:
8461 -      for (i = 1; i <= min; i++)
8462 -        if ((md->ctypes[*eptr++] & ctype_word) != 0)
8463 -          return FALSE;
8464 -      break;
8465 -
8466 -      case OP_WORDCHAR:
8467 -      for (i = 1; i <= min; i++)
8468 -        if ((md->ctypes[*eptr++] & ctype_word) == 0)
8469 -          return FALSE;
8470 -      break;
8471 -      }
8472 -
8473 -    /* If min = max, continue at the same level without recursing */
8474 -
8475 -    if (min == max) continue;
8476 -
8477 -    /* If minimizing, we have to test the rest of the pattern before each
8478 -    subsequent match. */
8479 -
8480 -    if (minimize)
8481 -      {
8482 -      for (i = min;; i++)
8483 -        {
8484 -        if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE;
8485 -        if (i >= max || eptr >= md->end_subject) return FALSE;
8486 -
8487 -        c = *eptr++;
8488 -        switch(ctype)
8489 -          {
8490 -          case OP_ANY:
8491 -          if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) return FALSE;
8492 -#ifdef SUPPORT_UTF8
8493 -          if (md->utf8)
8494 -            while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
8495 -#endif
8496 -          break;
8497 -
8498 -          case OP_NOT_DIGIT:
8499 -          if ((md->ctypes[c] & ctype_digit) != 0) return FALSE;
8500 -          break;
8501 -
8502 -          case OP_DIGIT:
8503 -          if ((md->ctypes[c] & ctype_digit) == 0) return FALSE;
8504 -          break;
8505 -
8506 -          case OP_NOT_WHITESPACE:
8507 -          if ((md->ctypes[c] & ctype_space) != 0) return FALSE;
8508 -          break;
8509 -
8510 -          case OP_WHITESPACE:
8511 -          if  ((md->ctypes[c] & ctype_space) == 0) return FALSE;
8512 -          break;
8513 -
8514 -          case OP_NOT_WORDCHAR:
8515 -          if ((md->ctypes[c] & ctype_word) != 0) return FALSE;
8516 -          break;
8517 -
8518 -          case OP_WORDCHAR:
8519 -          if ((md->ctypes[c] & ctype_word) == 0) return FALSE;
8520 -          break;
8521 -          }
8522 -        }
8523 -      /* Control never gets here */
8524 -      }
8525 -
8526 -    /* If maximizing it is worth using inline code for speed, doing the type
8527 -    test once at the start (i.e. keep it out of the loop). */
8528 -
8529 -    else
8530 -      {
8531 -      const uschar *pp = eptr;
8532 -      switch(ctype)
8533 -        {
8534 -        case OP_ANY:
8535 -
8536 -        /* Special code is required for UTF8, but when the maximum is unlimited
8537 -        we don't need it. */
8538 -
8539 -#ifdef SUPPORT_UTF8
8540 -        if (md->utf8 && max < INT_MAX)
8541 -          {
8542 -          if ((ims & PCRE_DOTALL) == 0)
8543 -            {
8544 -            for (i = min; i < max; i++)
8545 -              {
8546 -              if (eptr >= md->end_subject || *eptr++ == NEWLINE) break;
8547 -              while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
8548 -              }
8549 -            }
8550 -          else
8551 -            {
8552 -            for (i = min; i < max; i++)
8553 -              {
8554 -              eptr++;
8555 -              while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
8556 -              }
8557 -            }
8558 -          break;
8559 -          }
8560 -#endif
8561 -        /* Non-UTF8 can be faster */
8562 -        if ((ims & PCRE_DOTALL) == 0)
8563 -          {
8564 -          for (i = min; i < max; i++)
8565 -            {
8566 -            if (eptr >= md->end_subject || *eptr == NEWLINE) break;
8567 -            eptr++;
8568 -            }
8569 -          }
8570 -        else
8571 -          {
8572 -          c = max - min;
8573 -          if (c > md->end_subject - eptr) c = md->end_subject - eptr;
8574 -          eptr += c;
8575 -          }
8576 -        break;
8577 -
8578 -        case OP_NOT_DIGIT:
8579 -        for (i = min; i < max; i++)
8580 -          {
8581 -          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0)
8582 -            break;
8583 -          eptr++;
8584 -          }
8585 -        break;
8586 -
8587 -        case OP_DIGIT:
8588 -        for (i = min; i < max; i++)
8589 -          {
8590 -          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0)
8591 -            break;
8592 -          eptr++;
8593 -          }
8594 -        break;
8595 -
8596 -        case OP_NOT_WHITESPACE:
8597 -        for (i = min; i < max; i++)
8598 -          {
8599 -          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0)
8600 -            break;
8601 -          eptr++;
8602 -          }
8603 -        break;
8604 -
8605 -        case OP_WHITESPACE:
8606 -        for (i = min; i < max; i++)
8607 -          {
8608 -          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0)
8609 -            break;
8610 -          eptr++;
8611 -          }
8612 -        break;
8613 -
8614 -        case OP_NOT_WORDCHAR:
8615 -        for (i = min; i < max; i++)
8616 -          {
8617 -          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0)
8618 -            break;
8619 -          eptr++;
8620 -          }
8621 -        break;
8622 -
8623 -        case OP_WORDCHAR:
8624 -        for (i = min; i < max; i++)
8625 -          {
8626 -          if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0)
8627 -            break;
8628 -          eptr++;
8629 -          }
8630 -        break;
8631 -        }
8632 -
8633 -      while (eptr >= pp)
8634 -        {
8635 -        if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
8636 -          return TRUE;
8637 -#ifdef SUPPORT_UTF8
8638 -        if (md->utf8)
8639 -          while (eptr > pp && (*eptr & 0xc0) == 0x80) eptr--;
8640 -#endif
8641 -        }
8642 -      return FALSE;
8643 -      }
8644 -    /* Control never gets here */
8645 -
8646 -    /* There's been some horrible disaster. */
8647 -
8648 -    default:
8649 -    DPRINTF(("Unknown opcode %d\n", *ecode));
8650 -    md->errorcode = PCRE_ERROR_UNKNOWN_NODE;
8651 -    return FALSE;
8652 -    }
8653 -
8654 -  /* Do not stick any code in here without much thought; it is assumed
8655 -  that "continue" in the code above comes out to here to repeat the main
8656 -  loop. */
8657 -
8658 -  }             /* End of main loop */
8659 -/* Control never reaches here */
8660 -}
8661 -
8662 -
8663 -
8664 -
8665 -/*************************************************
8666 -*         Execute a Regular Expression           *
8667 -*************************************************/
8668 -
8669 -/* This function applies a compiled re to a subject string and picks out
8670 -portions of the string if it matches. Two elements in the vector are set for
8671 -each substring: the offsets to the start and end of the substring.
8672 -
8673 -Arguments:
8674 -  external_re     points to the compiled expression
8675 -  external_extra  points to "hints" from pcre_study() or is NULL
8676 -  subject         points to the subject string
8677 -  length          length of subject string (may contain binary zeros)
8678 -  start_offset    where to start in the subject string
8679 -  options         option bits
8680 -  offsets         points to a vector of ints to be filled in with offsets
8681 -  offsetcount     the number of elements in the vector
8682 -
8683 -Returns:          > 0 => success; value is the number of elements filled in
8684 -                  = 0 => success, but offsets is not big enough
8685 -                   -1 => failed to match
8686 -                 < -1 => some kind of unexpected problem
8687 -*/
8688 -
8689 -int
8690 -pcre_exec(const pcre *external_re, const pcre_extra *external_extra,
8691 -  const char *subject, int length, int start_offset, int options, int *offsets,
8692 -  int offsetcount)
8693 -{
8694 -int resetcount, ocount;
8695 -int first_char = -1;
8696 -int req_char = -1;
8697 -int req_char2 = -1;
8698 -unsigned long int ims = 0;
8699 -match_data match_block;
8700 -const uschar *start_bits = NULL;
8701 -const uschar *start_match = (const uschar *)subject + start_offset;
8702 -const uschar *end_subject;
8703 -const uschar *req_char_ptr = start_match - 1;
8704 -const real_pcre *re = (const real_pcre *)external_re;
8705 -const real_pcre_extra *extra = (const real_pcre_extra *)external_extra;
8706 -BOOL using_temporary_offsets = FALSE;
8707 -BOOL anchored;
8708 -BOOL startline;
8709 -
8710 -if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
8711 -
8712 -if (re == NULL || subject == NULL ||
8713 -   (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL;
8714 -if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
8715 -
8716 -anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
8717 -startline = (re->options & PCRE_STARTLINE) != 0;
8718 -
8719 -match_block.start_pattern = re->code;
8720 -match_block.start_subject = (const uschar *)subject;
8721 -match_block.end_subject = match_block.start_subject + length;
8722 -end_subject = match_block.end_subject;
8723 -
8724 -match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
8725 -match_block.utf8 = (re->options & PCRE_UTF8) != 0;
8726 -
8727 -match_block.notbol = (options & PCRE_NOTBOL) != 0;
8728 -match_block.noteol = (options & PCRE_NOTEOL) != 0;
8729 -match_block.notempty = (options & PCRE_NOTEMPTY) != 0;
8730 -
8731 -match_block.errorcode = PCRE_ERROR_NOMATCH;     /* Default error */
8732 -
8733 -match_block.lcc = re->tables + lcc_offset;
8734 -match_block.ctypes = re->tables + ctypes_offset;
8735 -
8736 -/* The ims options can vary during the matching as a result of the presence
8737 -of (?ims) items in the pattern. They are kept in a local variable so that
8738 -restoring at the exit of a group is easy. */
8739 -
8740 -ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL);
8741 -
8742 -/* If the expression has got more back references than the offsets supplied can
8743 -hold, we get a temporary bit of working store to use during the matching.
8744 -Otherwise, we can use the vector supplied, rounding down its size to a multiple
8745 -of 3. */
8746 -
8747 -ocount = offsetcount - (offsetcount % 3);
8748 -
8749 -if (re->top_backref > 0 && re->top_backref >= ocount/3)
8750 -  {
8751 -  ocount = re->top_backref * 3 + 3;
8752 -  match_block.offset_vector = (int *)(pcre_malloc)(ocount * sizeof(int));
8753 -  if (match_block.offset_vector == NULL) return PCRE_ERROR_NOMEMORY;
8754 -  using_temporary_offsets = TRUE;
8755 -  DPRINTF(("Got memory to hold back references\n"));
8756 -  }
8757 -else match_block.offset_vector = offsets;
8758 -
8759 -match_block.offset_end = ocount;
8760 -match_block.offset_max = (2*ocount)/3;
8761 -match_block.offset_overflow = FALSE;
8762 -
8763 -/* Compute the minimum number of offsets that we need to reset each time. Doing
8764 -this makes a huge difference to execution time when there aren't many brackets
8765 -in the pattern. */
8766 -
8767 -resetcount = 2 + re->top_bracket * 2;
8768 -if (resetcount > offsetcount) resetcount = ocount;
8769 -
8770 -/* Reset the working variable associated with each extraction. These should
8771 -never be used unless previously set, but they get saved and restored, and so we
8772 -initialize them to avoid reading uninitialized locations. */
8773 -
8774 -if (match_block.offset_vector != NULL)
8775 -  {
8776 -  register int *iptr = match_block.offset_vector + ocount;
8777 -  register int *iend = iptr - resetcount/2 + 1;
8778 -  while (--iptr >= iend) *iptr = -1;
8779 -  }
8780 -
8781 -/* Set up the first character to match, if available. The first_char value is
8782 -never set for an anchored regular expression, but the anchoring may be forced
8783 -at run time, so we have to test for anchoring. The first char may be unset for
8784 -an unanchored pattern, of course. If there's no first char and the pattern was
8785 -studied, there may be a bitmap of possible first characters. */
8786 -
8787 -if (!anchored)
8788 -  {
8789 -  if ((re->options & PCRE_FIRSTSET) != 0)
8790 -    {
8791 -    first_char = re->first_char;
8792 -    if ((ims & PCRE_CASELESS) != 0) first_char = match_block.lcc[first_char];
8793 -    }
8794 -  else
8795 -    if (!startline && extra != NULL &&
8796 -      (extra->options & PCRE_STUDY_MAPPED) != 0)
8797 -        start_bits = extra->start_bits;
8798 -  }
8799 -
8800 -/* For anchored or unanchored matches, there may be a "last known required
8801 -character" set. If the PCRE_CASELESS is set, implying that the match starts
8802 -caselessly, or if there are any changes of this flag within the regex, set up
8803 -both cases of the character. Otherwise set the two values the same, which will
8804 -avoid duplicate testing (which takes significant time). This covers the vast
8805 -majority of cases. It will be suboptimal when the case flag changes in a regex
8806 -and the required character in fact is caseful. */
8807 -
8808 -if ((re->options & PCRE_REQCHSET) != 0)
8809 -  {
8810 -  req_char = re->req_char;
8811 -  req_char2 = ((re->options & (PCRE_CASELESS | PCRE_ICHANGED)) != 0)?
8812 -    (re->tables + fcc_offset)[req_char] : req_char;
8813 -  }
8814 -
8815 -/* Loop for handling unanchored repeated matching attempts; for anchored regexs
8816 -the loop runs just once. */
8817 -
8818 -do
8819 -  {
8820 -  int rc;
8821 -  register int *iptr = match_block.offset_vector;
8822 -  register int *iend = iptr + resetcount;
8823 -
8824 -  /* Reset the maximum number of extractions we might see. */
8825 -
8826 -  while (iptr < iend) *iptr++ = -1;
8827 -
8828 -  /* Advance to a unique first char if possible */
8829 -
8830 -  if (first_char >= 0)
8831 -    {
8832 -    if ((ims & PCRE_CASELESS) != 0)
8833 -      while (start_match < end_subject &&
8834 -             match_block.lcc[*start_match] != first_char)
8835 -        start_match++;
8836 -    else
8837 -      while (start_match < end_subject && *start_match != first_char)
8838 -        start_match++;
8839 -    }
8840 -
8841 -  /* Or to just after \n for a multiline match if possible */
8842 -
8843 -  else if (startline)
8844 -    {
8845 -    if (start_match > match_block.start_subject + start_offset)
8846 -      {
8847 -      while (start_match < end_subject && start_match[-1] != NEWLINE)
8848 -        start_match++;
8849 -      }
8850 -    }
8851 -
8852 -  /* Or to a non-unique first char after study */
8853 -
8854 -  else if (start_bits != NULL)
8855 -    {
8856 -    while (start_match < end_subject)
8857 -      {
8858 -      register int c = *start_match;
8859 -      if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break;
8860 -      }
8861 -    }
8862 -
8863 -#ifdef DEBUG  /* Sigh. Some compilers never learn. */
8864 -  printf(">>>> Match against: ");
8865 -  pchars(start_match, end_subject - start_match, TRUE, &match_block);
8866 -  printf("\n");
8867 -#endif
8868 -
8869 -  /* If req_char is set, we know that that character must appear in the subject
8870 -  for the match to succeed. If the first character is set, req_char must be
8871 -  later in the subject; otherwise the test starts at the match point. This
8872 -  optimization can save a huge amount of backtracking in patterns with nested
8873 -  unlimited repeats that aren't going to match. We don't know what the state of
8874 -  case matching may be when this character is hit, so test for it in both its
8875 -  cases if necessary. However, the different cased versions will not be set up
8876 -  unless PCRE_CASELESS was given or the casing state changes within the regex.
8877 -  Writing separate code makes it go faster, as does using an autoincrement and
8878 -  backing off on a match. */
8879 -
8880 -  if (req_char >= 0)
8881 -    {
8882 -    register const uschar *p = start_match + ((first_char >= 0)? 1 : 0);
8883 -
8884 -    /* We don't need to repeat the search if we haven't yet reached the
8885 -    place we found it at last time. */
8886 -
8887 -    if (p > req_char_ptr)
8888 -      {
8889 -      /* Do a single test if no case difference is set up */
8890 -
8891 -      if (req_char == req_char2)
8892 -        {
8893 -        while (p < end_subject)
8894 -          {
8895 -          if (*p++ == req_char) { p--; break; }
8896 -          }
8897 -        }
8898 -
8899 -      /* Otherwise test for either case */
8900 -
8901 -      else
8902 -        {
8903 -        while (p < end_subject)
8904 -          {
8905 -          register int pp = *p++;
8906 -          if (pp == req_char || pp == req_char2) { p--; break; }
8907 -          }
8908 -        }
8909 -
8910 -      /* If we can't find the required character, break the matching loop */
8911 -
8912 -      if (p >= end_subject) break;
8913 -
8914 -      /* If we have found the required character, save the point where we
8915 -      found it, so that we don't search again next time round the loop if
8916 -      the start hasn't passed this character yet. */
8917 -
8918 -      req_char_ptr = p;
8919 -      }
8920 -    }
8921 -
8922 -  /* When a match occurs, substrings will be set for all internal extractions;
8923 -  we just need to set up the whole thing as substring 0 before returning. If
8924 -  there were too many extractions, set the return code to zero. In the case
8925 -  where we had to get some local store to hold offsets for backreferences, copy
8926 -  those back references that we can. In this case there need not be overflow
8927 -  if certain parts of the pattern were not used. */
8928 -
8929 -  match_block.start_match = start_match;
8930 -  if (!match(start_match, re->code, 2, &match_block, ims, NULL, match_isgroup))
8931 -    continue;
8932 -
8933 -  /* Copy the offset information from temporary store if necessary */
8934 -
8935 -  if (using_temporary_offsets)
8936 -    {
8937 -    if (offsetcount >= 4)
8938 -      {
8939 -      memcpy(offsets + 2, match_block.offset_vector + 2,
8940 -        (offsetcount - 2) * sizeof(int));
8941 -      DPRINTF(("Copied offsets from temporary memory\n"));
8942 -      }
8943 -    if (match_block.end_offset_top > offsetcount)
8944 -      match_block.offset_overflow = TRUE;
8945 -
8946 -    DPRINTF(("Freeing temporary memory\n"));
8947 -    (pcre_free)(match_block.offset_vector);
8948 -    }
8949 -
8950 -  rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2;
8951 -
8952 -  if (offsetcount < 2) rc = 0; else
8953 -    {
8954 -    offsets[0] = start_match - match_block.start_subject;
8955 -    offsets[1] = match_block.end_match_ptr - match_block.start_subject;
8956 -    }
8957 -
8958 -  DPRINTF((">>>> returning %d\n", rc));
8959 -  return rc;
8960 -  }
8961 -
8962 -/* This "while" is the end of the "do" above */
8963 -
8964 -while (!anchored &&
8965 -       match_block.errorcode == PCRE_ERROR_NOMATCH &&
8966 -       start_match++ < end_subject);
8967 -
8968 -if (using_temporary_offsets)
8969 -  {
8970 -  DPRINTF(("Freeing temporary memory\n"));
8971 -  (pcre_free)(match_block.offset_vector);
8972 -  }
8973 -
8974 -DPRINTF((">>>> returning %d\n", match_block.errorcode));
8975 -
8976 -return match_block.errorcode;
8977 -}
8978 -
8979 -/* End of pcre.c */
8980
8981 === removed file 'parser/pcre/pcre.h'
8982 --- parser/pcre/pcre.h  2006-04-11 21:52:54 +0000
8983 +++ parser/pcre/pcre.h  1970-01-01 00:00:00 +0000
8984 @@ -1,113 +0,0 @@
8985 -/*************************************************
8986 -*       Perl-Compatible Regular Expressions      *
8987 -*************************************************/
8988 -
8989 -/* Copyright (c) 1997-2001 University of Cambridge */
8990 -
8991 -#ifndef _PCRE_H
8992 -#define _PCRE_H
8993 -
8994 -/* The file pcre.h is build by "configure". Do not edit it; instead
8995 -make changes to pcre.in. */
8996 -
8997 -#define PCRE_MAJOR          3
8998 -#define PCRE_MINOR          9
8999 -#define PCRE_DATE           02-Jan-2002
9000 -
9001 -/* Win32 uses DLL by default */
9002 -
9003 -#ifdef _WIN32
9004 -# ifdef STATIC
9005 -#  define PCRE_DL_IMPORT
9006 -# else
9007 -#  define PCRE_DL_IMPORT __declspec(dllimport)
9008 -# endif
9009 -#else
9010 -# define PCRE_DL_IMPORT
9011 -#endif
9012 -
9013 -/* Have to include stdlib.h in order to ensure that size_t is defined;
9014 -it is needed here for malloc. */
9015 -
9016 -#include <stdlib.h>
9017 -
9018 -/* Allow for C++ users */
9019 -
9020 -#ifdef __cplusplus
9021 -extern "C" {
9022 -#endif
9023 -
9024 -/* Options */
9025 -
9026 -#define PCRE_CASELESS        0x0001
9027 -#define PCRE_MULTILINE       0x0002
9028 -#define PCRE_DOTALL          0x0004
9029 -#define PCRE_EXTENDED        0x0008
9030 -#define PCRE_ANCHORED        0x0010
9031 -#define PCRE_DOLLAR_ENDONLY  0x0020
9032 -#define PCRE_EXTRA           0x0040
9033 -#define PCRE_NOTBOL          0x0080
9034 -#define PCRE_NOTEOL          0x0100
9035 -#define PCRE_UNGREEDY        0x0200
9036 -#define PCRE_NOTEMPTY        0x0400
9037 -#define PCRE_UTF8            0x0800
9038 -
9039 -/* Exec-time and get-time error codes */
9040 -
9041 -#define PCRE_ERROR_NOMATCH        (-1)
9042 -#define PCRE_ERROR_NULL           (-2)
9043 -#define PCRE_ERROR_BADOPTION      (-3)
9044 -#define PCRE_ERROR_BADMAGIC       (-4)
9045 -#define PCRE_ERROR_UNKNOWN_NODE   (-5)
9046 -#define PCRE_ERROR_NOMEMORY       (-6)
9047 -#define PCRE_ERROR_NOSUBSTRING    (-7)
9048 -
9049 -/* Request types for pcre_fullinfo() */
9050 -
9051 -#define PCRE_INFO_OPTIONS         0
9052 -#define PCRE_INFO_SIZE            1
9053 -#define PCRE_INFO_CAPTURECOUNT    2
9054 -#define PCRE_INFO_BACKREFMAX      3
9055 -#define PCRE_INFO_FIRSTCHAR       4
9056 -#define PCRE_INFO_FIRSTTABLE      5
9057 -#define PCRE_INFO_LASTLITERAL     6
9058 -
9059 -/* Types */
9060 -
9061 -struct real_pcre;        /* declaration; the definition is private  */
9062 -struct real_pcre_extra;  /* declaration; the definition is private */
9063 -
9064 -typedef struct real_pcre pcre;
9065 -typedef struct real_pcre_extra pcre_extra;
9066 -
9067 -/* Store get and free functions. These can be set to alternative malloc/free
9068 -functions if required. Some magic is required for Win32 DLL; it is null on
9069 -other OS. */
9070 -
9071 -PCRE_DL_IMPORT extern void *(*pcre_malloc)(size_t);
9072 -PCRE_DL_IMPORT extern void  (*pcre_free)(void *);
9073 -
9074 -#undef PCRE_DL_IMPORT
9075 -
9076 -/* Functions */
9077 -
9078 -extern pcre *pcre_compile(const char *, int, const char **, int *,
9079 -              const unsigned char *);
9080 -extern int  pcre_copy_substring(const char *, int *, int, int, char *, int);
9081 -extern int  pcre_exec(const pcre *, const pcre_extra *, const char *,
9082 -              int, int, int, int *, int);
9083 -extern void pcre_free_substring(const char *);
9084 -extern void pcre_free_substring_list(const char **);
9085 -extern int  pcre_get_substring(const char *, int *, int, int, const char **);
9086 -extern int  pcre_get_substring_list(const char *, int *, int, const char ***);
9087 -extern int  pcre_info(const pcre *, int *, int *);
9088 -extern int  pcre_fullinfo(const pcre *, const pcre_extra *, int, void *);
9089 -extern const unsigned char *pcre_maketables(void);
9090 -extern pcre_extra *pcre_study(const pcre *, int, const char **);
9091 -extern const char *pcre_version(void);
9092 -
9093 -#ifdef __cplusplus
9094 -}  /* extern "C" */
9095 -#endif
9096 -
9097 -#endif /* End of pcre.h */
9098
9099 === modified file 'parser/tst/Makefile'
9100 --- parser/tst/Makefile 2006-12-15 08:10:25 +0000
9101 +++ parser/tst/Makefile 2010-08-03 17:27:13 +0000
9102 @@ -1,8 +1,9 @@
9103  #
9104 -# $Id$
9105 -#
9106  PROVE=/usr/bin/prove
9107  TESTS=simple.pl
9108 +PARSER_DIR=..
9109 +PARSER_BIN=apparmor_parser
9110 +PARSER=$(PARSER_DIR)/$(PARSER_BIN)
9111  
9112  ifeq ($(VERBOSE),1)
9113    PROVE_ARG=-v
9114 @@ -10,9 +11,23 @@
9115  
9116  all: tests
9117  
9118 -.PHONY: tests
9119 -tests: ../apparmor_parser
9120 +.PHONY: tests error_output parser_sanity
9121 +tests: error_output parser_sanity
9122 +
9123 +error_output: $(PARSER)
9124 +       $(PARSER) -S -I errors >/dev/null errors/okay.sd
9125 +       LANG=C $(PARSER) -S -I errors 2>&1 >/dev/null errors/single.sd | \
9126 +               grep -q "AppArmor parser error for errors/single.sd in errors/single.sd at line 3: Could not open 'failure'"
9127 +       LANG=C $(PARSER) -S -I errors 2>&1 >/dev/null errors/double.sd | \
9128 +               grep -q "AppArmor parser error for errors/double.sd in errors/includes/busted at line 67: Could not open 'does-not-exist'"
9129 +       LANG=C $(PARSER) -S -I errors 2>&1 >/dev/null errors/modefail.sd | \
9130 +               grep -q "AppArmor parser error for errors/modefail.sd in errors/modefail.sd at line 6: syntax error"
9131 +       LANG=C $(PARSER) -S -I errors 2>&1 >/dev/null errors/multi_include.sd | \
9132 +               grep -q "AppArmor parser error for errors/multi_include.sd in errors/multi_include.sd at line 12: Could not open 'failure'"
9133 +       @echo "Error Output: PASS"
9134 +
9135 +parser_sanity: $(PARSER)
9136         $(Q)${PROVE} ${PROVE_ARG} ${TESTS}
9137  
9138 -../apparmor_parser:
9139 -       make -C .. apparmor_parser
9140 +$(PARSER):
9141 +       make -C $(PARSER_DIR) $(PARSER_BIN)
9142
9143 === modified file 'parser/tst/README'
9144 --- parser/tst/README   2006-06-01 17:02:28 +0000
9145 +++ parser/tst/README   2010-06-05 06:11:20 +0000
9146 @@ -64,5 +64,3 @@
9147      loop.
9148  
9149  Otherwise, the profile is passed on as-is to the subdomain parser.
9150 -
9151 -$Id$ 
9152
9153 === added directory 'parser/tst/errors'
9154 === added file 'parser/tst/errors/double.sd'
9155 --- parser/tst/errors/double.sd 1970-01-01 00:00:00 +0000
9156 +++ parser/tst/errors/double.sd 2010-06-05 06:11:20 +0000
9157 @@ -0,0 +1,5 @@
9158 +#
9159 +/does/not/exist {
9160 +  #include <includes/base>
9161 +  #include <includes/busted>
9162 +}
9163
9164 === added directory 'parser/tst/errors/includes'
9165 === added file 'parser/tst/errors/includes/base'
9166 --- parser/tst/errors/includes/base     1970-01-01 00:00:00 +0000
9167 +++ parser/tst/errors/includes/base     2010-06-05 06:11:20 +0000
9168 @@ -0,0 +1,81 @@
9169 +# $Id$
9170 +# ------------------------------------------------------------------
9171 +#
9172 +#    Copyright (C) 2002-2005 Novell/SUSE
9173 +#
9174 +#    This program is free software; you can redistribute it and/or
9175 +#    modify it under the terms of version 2 of the GNU General Public
9176 +#    License published by the Free Software Foundation.
9177 +#
9178 +# ------------------------------------------------------------------
9179 +
9180 +
9181 +
9182 +  # (Note that the ldd profile has inlined this file; if you make
9183 +  # modifications here, please consider including them in the ldd
9184 +  # profile as well.)
9185 +
9186 +  # The __canary_death_handler function writes a time-stamped log
9187 +  # message to /dev/log for logging by syslogd. So, /dev/log, timezones,
9188 +  # and localisations of date should be available EVERYWHERE, so
9189 +  # StackGuard, FormatGuard, etc., alerts can be properly logged.
9190 +  /dev/log                       w,
9191 +  /dev/urandom                   r,
9192 +  /etc/locale/**                 r,
9193 +  /etc/localtime                 r,
9194 +  /usr/share/locale/**           r,
9195 +  /usr/share/zoneinfo/**         r,
9196 +
9197 +  /usr/lib64/locale/**           r,
9198 +  /usr/lib64/gconv/*.so          r,
9199 +  /usr/lib64/gconv/gconv-modules*  r,
9200 +  /usr/lib/locale/**             r,
9201 +  /usr/lib/gconv/*.so            r,
9202 +  /usr/lib/gconv/gconv-modules*  r,
9203 +
9204 +  # used by glibc when binding to ephemeral ports
9205 +  /etc/bindresvport.blacklist    r,
9206 +
9207 +  # ld.so.cache and ld are used to load shared libraries; they are best
9208 +  # available everywhere
9209 +  /etc/ld.so.cache               r,
9210 +  # 'px' requires a profile to be available for the transition to
9211 +  # function; without a loaded profile, the kernel will fail the exec.
9212 +  /lib/ld-*.so                   px,
9213 +  /lib64/ld-*.so                 px,
9214 +  /opt/*-linux-uclibc/lib/ld-uClibc*so* px,
9215 +
9216 +  # we might as well allow everything to use common libraries
9217 +  /lib/lib*.so*                  r,
9218 +  /lib/tls/lib*.so*              r,
9219 +  /lib/power4/lib*.so*           r,
9220 +  /lib/power5/lib*.so*           r,
9221 +  /lib/power5+/lib*.so*          r,
9222 +  /lib64/power4/lib*.so*         r,
9223 +  /lib64/power5/lib*.so*         r,
9224 +  /lib64/power5+/lib*.so*        r,
9225 +  /usr/lib/*.so*                 r,
9226 +  /usr/lib/tls/lib*.so*          r,
9227 +  /usr/lib/power4/lib*.so*       r,
9228 +  /usr/lib/power5/lib*.so*       r,
9229 +  /usr/lib/power5+/lib*.so*      r,
9230 +  /lib64/lib*.so*                r,
9231 +  /lib64/tls/lib*.so*            r,
9232 +  /usr/lib64/*.so*               r,
9233 +  /usr/lib64/tls/lib*.so*        r,
9234 +
9235 +  # /dev/null is pretty harmless and frequently used
9236 +  /dev/null                      rw,
9237 +  # as is /dev/zero
9238 +  /dev/zero                      rw,
9239 +
9240 +  # Sometimes used to determine kernel/user interfaces to use
9241 +  /proc/sys/kernel/version       r,
9242 +  # Depending on which glibc routine uses this file, base may not be the
9243 +  # best place -- but many profiles require it, and it is quite harmless.
9244 +  /proc/sys/kernel/ngroups_max   r,
9245 +
9246 +  # glibc's sysconf(3) routine to determine free memory, etc
9247 +  /proc/meminfo                  r,
9248 +  /proc/stat                     r,
9249 +  /proc/cpuinfo                  r,
9250
9251 === added file 'parser/tst/errors/includes/busted'
9252 --- parser/tst/errors/includes/busted   1970-01-01 00:00:00 +0000
9253 +++ parser/tst/errors/includes/busted   2010-06-05 06:11:20 +0000
9254 @@ -0,0 +1,83 @@
9255 +# $Id$
9256 +# ------------------------------------------------------------------
9257 +#
9258 +#    Copyright (C) 2002-2005 Novell/SUSE
9259 +#
9260 +#    This program is free software; you can redistribute it and/or
9261 +#    modify it under the terms of version 2 of the GNU General Public
9262 +#    License published by the Free Software Foundation.
9263 +#
9264 +# ------------------------------------------------------------------
9265 +
9266 +
9267 +
9268 +  # (Note that the ldd profile has inlined this file; if you make
9269 +  # modifications here, please consider including them in the ldd
9270 +  # profile as well.)
9271 +
9272 +  # The __canary_death_handler function writes a time-stamped log
9273 +  # message to /dev/log for logging by syslogd. So, /dev/log, timezones,
9274 +  # and localisations of date should be available EVERYWHERE, so
9275 +  # StackGuard, FormatGuard, etc., alerts can be properly logged.
9276 +  /dev/log                       w,
9277 +  /dev/urandom                   r,
9278 +  /etc/locale/**                 r,
9279 +  /etc/localtime                 r,
9280 +  /usr/share/locale/**           r,
9281 +  /usr/share/zoneinfo/**         r,
9282 +
9283 +  /usr/lib64/locale/**           r,
9284 +  /usr/lib64/gconv/*.so          r,
9285 +  /usr/lib64/gconv/gconv-modules*  r,
9286 +  /usr/lib/locale/**             r,
9287 +  /usr/lib/gconv/*.so            r,
9288 +  /usr/lib/gconv/gconv-modules*  r,
9289 +
9290 +  # used by glibc when binding to ephemeral ports
9291 +  /etc/bindresvport.blacklist    r,
9292 +
9293 +  # ld.so.cache and ld are used to load shared libraries; they are best
9294 +  # available everywhere
9295 +  /etc/ld.so.cache               r,
9296 +  # 'px' requires a profile to be available for the transition to
9297 +  # function; without a loaded profile, the kernel will fail the exec.
9298 +  /lib/ld-*.so                   px,
9299 +  /lib64/ld-*.so                 px,
9300 +  /opt/*-linux-uclibc/lib/ld-uClibc*so* px,
9301 +
9302 +  # we might as well allow everything to use common libraries
9303 +  /lib/lib*.so*                  r,
9304 +  /lib/tls/lib*.so*              r,
9305 +  /lib/power4/lib*.so*           r,
9306 +  /lib/power5/lib*.so*           r,
9307 +  /lib/power5+/lib*.so*          r,
9308 +  /lib64/power4/lib*.so*         r,
9309 +  /lib64/power5/lib*.so*         r,
9310 +  /lib64/power5+/lib*.so*        r,
9311 +  /usr/lib/*.so*                 r,
9312 +  /usr/lib/tls/lib*.so*          r,
9313 +  /usr/lib/power4/lib*.so*       r,
9314 +  /usr/lib/power5/lib*.so*       r,
9315 +  /usr/lib/power5+/lib*.so*      r,
9316 +  /lib64/lib*.so*                r,
9317 +  /lib64/tls/lib*.so*            r,
9318 +  /usr/lib64/*.so*               r,
9319 +  /usr/lib64/tls/lib*.so*        r,
9320 +
9321 +  #include <does-not-exist>
9322 +
9323 +  # /dev/null is pretty harmless and frequently used
9324 +  /dev/null                      rw,
9325 +  # as is /dev/zero
9326 +  /dev/zero                      rw,
9327 +
9328 +  # Sometimes used to determine kernel/user interfaces to use
9329 +  /proc/sys/kernel/version       r,
9330 +  # Depending on which glibc routine uses this file, base may not be the
9331 +  # best place -- but many profiles require it, and it is quite harmless.
9332 +  /proc/sys/kernel/ngroups_max   r,
9333 +
9334 +  # glibc's sysconf(3) routine to determine free memory, etc
9335 +  /proc/meminfo                  r,
9336 +  /proc/stat                     r,
9337 +  /proc/cpuinfo                  r,
9338
9339 === added file 'parser/tst/errors/modefail.sd'
9340 --- parser/tst/errors/modefail.sd       1970-01-01 00:00:00 +0000
9341 +++ parser/tst/errors/modefail.sd       2010-08-03 17:27:13 +0000
9342 @@ -0,0 +1,7 @@
9343 +#      1
9344 +#      2
9345 +#      3
9346 +/does/not/exist {      # 4
9347 +  /lib/lib*.so rm,     # 5
9348 +  /fail abcdefgh,      # 6
9349 +}                      # 7
9350
9351 === added file 'parser/tst/errors/multi_include.sd'
9352 --- parser/tst/errors/multi_include.sd  1970-01-01 00:00:00 +0000
9353 +++ parser/tst/errors/multi_include.sd  2010-08-03 17:27:13 +0000
9354 @@ -0,0 +1,13 @@
9355 +#
9356 +#
9357 +#
9358 +/does/not/exist {
9359 +  #include <includes/base>
9360 +  #include <includes/base>
9361 +  #include <includes/base>
9362 +  #include <includes/base>
9363 +
9364 +  /bin/true rix,
9365 +
9366 +  #include <failure>
9367 +}
9368
9369 === added file 'parser/tst/errors/okay.sd'
9370 --- parser/tst/errors/okay.sd   1970-01-01 00:00:00 +0000
9371 +++ parser/tst/errors/okay.sd   2010-06-05 06:11:20 +0000
9372 @@ -0,0 +1,4 @@
9373 +#
9374 +/does/not/exist {
9375 +  #include <includes/base>
9376 +}
9377
9378 === added file 'parser/tst/errors/single.sd'
9379 --- parser/tst/errors/single.sd 1970-01-01 00:00:00 +0000
9380 +++ parser/tst/errors/single.sd 2010-06-05 06:11:20 +0000
9381 @@ -0,0 +1,7 @@
9382 +#
9383 +#
9384 +#include <failure>
9385 +#
9386 +/does/not/exist {
9387 +  #include <includes/base>
9388 +}
9389
9390 === modified file 'profiles/apparmor.d/abstractions/base'
9391 --- profiles/apparmor.d/abstractions/base       2010-01-03 21:16:38 +0000
9392 +++ profiles/apparmor.d/abstractions/base       2010-06-05 06:11:20 +0000
9393 @@ -85,6 +85,9 @@
9394    # some applications will display license information
9395    /usr/share/common-licenses/**  r,
9396  
9397 +  # glibc statvfs
9398 +  @{PROC}/filesystems            r,
9399 +
9400    # Workaround https://launchpad.net/bugs/359338 until upstream handles stacked
9401    # filesystems generally. This does not appreciably decrease security with
9402    # Ubuntu profiles because the user is expected to have access to files owned
9403
9404 === modified file 'profiles/apparmor.d/abstractions/dbus'
9405 --- profiles/apparmor.d/abstractions/dbus       2009-11-04 20:25:42 +0000
9406 +++ profiles/apparmor.d/abstractions/dbus       2010-08-03 17:27:13 +0000
9407 @@ -2,7 +2,7 @@
9408  # $Id$
9409  # ------------------------------------------------------------------
9410  #
9411 -#    Copyright (C) 2009 Canonical Ltd.
9412 +#    Copyright (C) 2009-2010 Canonical Ltd.
9413  #
9414  #    This program is free software; you can redistribute it and/or
9415  #    modify it under the terms of version 2 of the GNU General Public
9416 @@ -10,8 +10,5 @@
9417  #
9418  # ------------------------------------------------------------------
9419  
9420 -  # System socket
9421 +  # System socket. Be careful when including this abstraction.
9422    /var/run/dbus/system_bus_socket w,
9423 -
9424 -  # Machine id
9425 -  /var/lib/dbus/machine-id r,
9426
9427 === added file 'profiles/apparmor.d/abstractions/dbus-session'
9428 --- profiles/apparmor.d/abstractions/dbus-session       1970-01-01 00:00:00 +0000
9429 +++ profiles/apparmor.d/abstractions/dbus-session       2010-08-03 17:27:13 +0000
9430 @@ -0,0 +1,14 @@
9431 +# vim:syntax=apparmor
9432 +# $Id$
9433 +# ------------------------------------------------------------------
9434 +#
9435 +#    Copyright (C) 2010 Canonical Ltd.
9436 +#
9437 +#    This program is free software; you can redistribute it and/or
9438 +#    modify it under the terms of version 2 of the GNU General Public
9439 +#    License published by the Free Software Foundation.
9440 +#
9441 +# ------------------------------------------------------------------
9442 +
9443 +  /usr/bin/dbus-launch Pix,
9444 +  /var/lib/dbus/machine-id r,
9445
9446 === modified file 'profiles/apparmor.d/abstractions/fonts'
9447 --- profiles/apparmor.d/abstractions/fonts      2009-11-04 20:25:42 +0000
9448 +++ profiles/apparmor.d/abstractions/fonts      2010-06-05 06:11:20 +0000
9449 @@ -15,6 +15,7 @@
9450  
9451    /usr/lib/xorg/modules/fonts/**.so*    mr,
9452  
9453 +  /usr/share/fonts/                     r,
9454    /usr/share/fonts/**                   r,
9455  
9456    /etc/fonts/**                         r,
9457
9458 === modified file 'profiles/apparmor.d/abstractions/freedesktop.org'
9459 --- profiles/apparmor.d/abstractions/freedesktop.org    2009-11-04 20:25:42 +0000
9460 +++ profiles/apparmor.d/abstractions/freedesktop.org    2010-06-05 06:11:20 +0000
9461 @@ -27,3 +27,7 @@
9462    @{HOME}/.icons/                 r,
9463    @{HOME}/.recently-used.xbel*    rw,
9464    @{HOME}/.config/user-dirs.dirs  r,
9465 +  @{HOME}/.local/share/icons/     r,
9466 +  @{HOME}/.local/share/icons/**   r,
9467 +  @{HOME}/.local/share/mime/      r,
9468 +  @{HOME}/.local/share/mime/**    r,
9469
9470 === modified file 'profiles/apparmor.d/abstractions/gnome'
9471 --- profiles/apparmor.d/abstractions/gnome      2009-11-10 20:04:26 +0000
9472 +++ profiles/apparmor.d/abstractions/gnome      2010-08-03 17:27:13 +0000
9473 @@ -3,7 +3,7 @@
9474  # ------------------------------------------------------------------
9475  #
9476  #    Copyright (C) 2002-2009 Novell/SUSE
9477 -#    Copyright (C) 2009 Canonical Ltd.
9478 +#    Copyright (C) 2009-2010 Canonical Ltd.
9479  #
9480  #    This program is free software; you can redistribute it and/or
9481  #    modify it under the terms of version 2 of the GNU General Public
9482 @@ -31,6 +31,7 @@
9483    /etc/pango/*                    r,
9484    /usr/lib{,32,64}/pango/**       mr,
9485    /usr/lib{,32,64}/gtk-*/**       mr,
9486 +  /usr/lib{,32,64}/gdk-pixbuf-*/** mr,
9487  
9488    # per-user gtk configuration
9489    @{HOME}/.gnome/Gnome            r,
9490
9491 === modified file 'profiles/apparmor.d/abstractions/nameservice'
9492 --- profiles/apparmor.d/abstractions/nameservice        2009-11-04 20:25:42 +0000
9493 +++ profiles/apparmor.d/abstractions/nameservice        2010-06-05 06:11:20 +0000
9494 @@ -77,3 +77,5 @@
9495    network inet  dgram,
9496    network inet6 dgram,
9497  
9498 +  # interface details
9499 +  @{PROC}/*/net/route r,
9500
9501 === modified file 'profiles/apparmor.d/abstractions/php5'
9502 --- profiles/apparmor.d/abstractions/php5       2010-01-03 21:16:38 +0000
9503 +++ profiles/apparmor.d/abstractions/php5       2010-05-31 18:58:40 +0000
9504 @@ -2,7 +2,7 @@
9505  # ------------------------------------------------------------------
9506  #
9507  #    Copyright (C) 2002-2006 Novell/SUSE
9508 -#    Copyright (C) 2009 Canonical, Ltd.
9509 +#    Copyright (C) 2009-2010 Canonical Ltd.
9510  #
9511  #    This program is free software; you can redistribute it and/or
9512  #    modify it under the terms of version 2 of the GNU General Public
9513 @@ -11,13 +11,13 @@
9514  # ------------------------------------------------------------------
9515  
9516    # shared snippets for config files
9517 -  /etc/php5/{conf.d,apache2,cli,fastcgi}/ r,
9518 -  /etc/php5/{conf.d,apache2,cli,fastcgi}/*.ini r,
9519 +  /etc/php5/{conf.d,apache2,cli,fastcgi,cgi}/ r,
9520 +  /etc/php5/{conf.d,apache2,cli,fastcgi,cgi}/*.ini r,
9521  
9522    # Xlibs
9523    /usr/X11R6/lib{,32,64}/lib*.so* mr,
9524    # php extensions
9525 -  /usr/lib{64,}/php5/{libexec,extensions}/*.so mr,
9526 +  /usr/lib{64,}/php5/*/*.so mr,
9527  
9528    # php5 session mmap socket
9529    /var/lib/php5/session_mm_* rwlk,
9530
9531 === modified file 'profiles/apparmor.d/abstractions/samba'
9532 --- profiles/apparmor.d/abstractions/samba      2009-11-04 20:25:42 +0000
9533 +++ profiles/apparmor.d/abstractions/samba      2010-05-31 18:58:40 +0000
9534 @@ -2,7 +2,7 @@
9535  # $Id$
9536  # ------------------------------------------------------------------
9537  #
9538 -#    Copyright (C) 2009 Canonical Ltd.
9539 +#    Copyright (C) 2009-2010 Canonical Ltd.
9540  #
9541  #    This program is free software; you can redistribute it and/or
9542  #    modify it under the terms of version 2 of the GNU General Public
9543 @@ -12,7 +12,7 @@
9544  
9545    /etc/samba/smb.conf r,
9546    /usr/share/samba/*.dat r,
9547 -  /var/lib/samba/**.tdb rw,
9548 +  /var/lib/samba/**.tdb rwk,
9549    /var/log/samba/cores/* w,
9550    /var/log/samba/log.* w,
9551    /var/run/samba/*.tdb rw,
9552
9553 === modified file 'profiles/apparmor.d/abstractions/ubuntu-email'
9554 --- profiles/apparmor.d/abstractions/ubuntu-email       2009-11-11 19:42:30 +0000
9555 +++ profiles/apparmor.d/abstractions/ubuntu-email       2010-08-03 17:27:13 +0000
9556 @@ -15,5 +15,5 @@
9557    /usr/bin/tkrat Ux,
9558  
9559    /usr/lib/thunderbird/thunderbird Ux,
9560 -
9561 +  /usr/lib/thunderbird-3*/thunderbird Ux,
9562  
9563
9564 === modified file 'profiles/apparmor.d/abstractions/ubuntu-media-players'
9565 --- profiles/apparmor.d/abstractions/ubuntu-media-players       2010-03-08 19:50:25 +0000
9566 +++ profiles/apparmor.d/abstractions/ubuntu-media-players       2010-08-03 17:27:13 +0000
9567 @@ -24,6 +24,7 @@
9568  
9569    # mplayer
9570    /etc/mplayerplug-in.conf r,
9571 +  /usr/bin/gmplayer Uxr,
9572    /usr/bin/gnome-mplayer Uxr,
9573    /usr/bin/kmplayer Uxr,
9574    /usr/bin/mplayer Uxr,
9575
9576 === modified file 'profiles/apparmor.d/abstractions/user-tmp'
9577 --- profiles/apparmor.d/abstractions/user-tmp   2009-11-04 20:25:42 +0000
9578 +++ profiles/apparmor.d/abstractions/user-tmp   2010-05-31 18:58:40 +0000
9579 @@ -2,7 +2,7 @@
9580  # ------------------------------------------------------------------
9581  #
9582  #    Copyright (C) 2002-2009 Novell/SUSE
9583 -#    Copyright (C) 2009 Canonical Ltd.
9584 +#    Copyright (C) 2009-2010 Canonical Ltd.
9585  #
9586  #    This program is free software; you can redistribute it and/or
9587  #    modify it under the terms of version 2 of the GNU General Public
9588 @@ -11,11 +11,11 @@
9589  # ------------------------------------------------------------------
9590  
9591    # per-user tmp directories
9592 -  @{HOME}/tmp/**  rwkl,
9593 -  @{HOME}/tmp/    rw,
9594 +  owner @{HOME}/tmp/**  rwkl,
9595 +  owner @{HOME}/tmp/    rw,
9596  
9597    # global tmp directories
9598 -  /var/tmp/**     rwkl,
9599 -  /var/tmp/       rw,
9600 -  /tmp/**         rwkl,
9601 -  /tmp/           rw,
9602 +  owner /var/tmp/**     rwkl,
9603 +  owner /var/tmp/       rw,
9604 +  owner /tmp/**         rwkl,
9605 +  owner /tmp/           rw,
9606
9607 === renamed directory 'tests/regression/subdomain' => 'tests/regression/apparmor'
9608 === modified file 'tests/regression/apparmor/Makefile'
9609 --- tests/regression/subdomain/Makefile 2009-08-21 20:39:45 +0000
9610 +++ tests/regression/apparmor/Makefile  2010-08-03 17:27:13 +0000
9611 @@ -22,6 +22,7 @@
9612      chmod.c \
9613      chown.c \
9614      clone.c \
9615 +    coredump.c \
9616      deleted.c \
9617      environ.c \
9618      env_check.c \
9619 @@ -113,6 +114,7 @@
9620        changehat_misc \
9621        chdir \
9622        clone \
9623 +      coredump \
9624        deleted \
9625        environ \
9626        exec \
9627 @@ -158,27 +160,39 @@
9628  tests: all
9629         @if [ `whoami` = "root" ] ;\
9630         then \
9631 +               rc=0; \
9632                 for i in $(TESTS) ;\
9633                 do \
9634                         echo ;\
9635                         echo "running $$i" ;\
9636                         bash $$i.sh ;\
9637 +                       if [ $$? -ne 0 ] ; then \
9638 +                               rc=1;\
9639 +                       fi;\
9640                 done ;\
9641 +               exit $$rc;\
9642         else \
9643                 echo "must be root to run tests" ;\
9644 +               exit 1;\
9645         fi
9646  
9647  alltests: all
9648         @if [ `whoami` = "root" ] ;\
9649         then \
9650 +               rc=0; \
9651                 for i in $(TESTS) $(RISKY_TESTS) ;\
9652                 do \
9653                         echo ;\
9654                         echo "running $$i" ;\
9655                         bash $$i.sh ;\
9656 +                       if [ $$? -ne 0 ] ; then \
9657 +                               rc=1;\
9658 +                       fi;\
9659                 done ;\
9660 +               exit $$rc;\
9661         else \
9662                 echo "must be root to run tests" ;\
9663 +               exit 1;\
9664         fi
9665  
9666  clean:
9667
9668 === modified file 'tests/regression/apparmor/README'
9669 --- tests/regression/subdomain/README   2006-09-15 22:39:59 +0000
9670 +++ tests/regression/apparmor/README    2010-08-03 17:27:13 +0000
9671 @@ -1,10 +1,10 @@
9672  Running tests
9673  =============
9674  
9675 -Type "make tests" at the shell prompt, this will make the subprograms
9676 -and run the tests.
9677 +Type "sudo make tests" at the shell prompt, this will make the
9678 +subprograms and run the tests.
9679  
9680 -You must be root to execute make tests (a requirement of subdomain).
9681 +You must be root to execute "make tests" (a requirement of AppArmor).
9682  
9683  (There is also a 'make alltests', which adds a test for bug that, when
9684  triggered, would cause the kernel to crash.)
9685 @@ -12,10 +12,13 @@
9686  Test output
9687  ===========
9688  
9689 -No output is displayed for a passing test.  The makefile will output
9690 +By default, no output is displayed for a passing test.  The makefile will
9691 +output:
9692         running <testname> for each test.
9693  
9694 -Output other than this indicates a problem.
9695 +To have verbose output with each subtest reporting successes, set the
9696 +environment variable VERBOSE=1:
9697 +       sudo VERBOSE=1 make tests
9698  
9699  There are three typical failure scenarios:
9700         - Test failed when it was expected to pass
9701 @@ -29,7 +32,7 @@
9702  
9703  Common user changeable environment variables are stored in the file
9704  'uservars.inc'.  Currently the path to the tmp directory, the path
9705 -to the subdomain_parser executable, and any additional arguments to give
9706 +to the apparmor_parser executable, and any additional arguments to give
9707  to the parser are specified in this configuration file.
9708  
9709  (Note: the tmp directory specified in uservars.inc will have an added
9710 @@ -66,7 +69,7 @@
9711  directory will contain the files for the failed subtest.
9712  
9713  It may be necessary to create certain temp files in this directory in order to 
9714 -have the test function correctly, see the subdomain profile 'profile' in the 
9715 +have the test function correctly, see the AppArmor profile 'profile' in the 
9716  directory in order to determine which files may need to be created to support
9717  the executable.
9718  
9719 @@ -155,7 +158,7 @@
9720         <requirement placed on the shell script author by prologue.inc>
9721         bin=$pwd
9722         
9723 -       <prologie.inc must be included before running any tests>
9724 +       <prologue.inc must be included before running any tests>
9725         . $bin/prologue.inc
9726         
9727         <variable definitions used by this script?
9728 @@ -174,7 +177,7 @@
9729         
9730         # NOLINK PERMTEST
9731         <generate a new profile allowing only r access to /bin/true>
9732 -       <subdomain_parser will automatically be invoked in -r mode>
9733 +       <apparmor_parser will automatically be invoked in -r mode>
9734         genprofile $file:$badperm
9735  
9736         <run this test (exec) passing /bin/true as argv[1]>
9737 @@ -183,16 +186,11 @@
9738  
9739         <Thats it. Exit status $rc is automatically returned by epilogue.inc>
9740  
9741 -Additional documentation
9742 -========================
9743 -
9744 -See the file 'subdomain_test.txt'
9745 -
9746  Supporting files
9747  ================
9748  
9749  strace.sh      Not a test harness, used to support strace testing.
9750 -mkprofile.sh   Not a test harness, used to generate subdomain profiles.
9751 +mkprofile.sh   Not a test harness, used to generate AppArmor profiles.
9752  prologue.inc   Must be dotted (included) into the test harness. Provides
9753                 support routines.
9754  epilogue.inc   Cleanup support, automatically called upon successful or
9755 @@ -222,17 +220,3 @@
9756     This is not an error, rather a sign that bash noticed the kernel had killed 
9757     a process which was attempting to use a bogus MAGIC number.  Alas, there is 
9758     no way to get bash to not print this diagnostic
9759 -
9760 -3) Ptrace
9761 -       Error: open passed. Test 'STRACE OPEN (x confinement)' 
9762 -       was expected to 'fail'
9763
9764 -   Regression from 2.4.18 to 2.4.20. (We aren't sure on the first
9765 -   endpoint, and the problem still happens in 2.4.20-20_imnx_10smp.)
9766 -
9767 -4) Open
9768 -       Error: open passed. Test 'OPEN W (create)' was expected to 'fail'
9769 -
9770 -   LSM issue.  Flags passed to inode_permission are 0 if O_CREAT is used to
9771 -   open file.  Need to submit a patch to inode_create hook to receive the
9772 -   O_RDWR flags. See https://bugs.wirex.com/show_bug.cgi?id=2885
9773
9774 === modified file 'tests/regression/apparmor/changehat_misc.sh'
9775 --- tests/regression/subdomain/changehat_misc.sh        2006-05-19 17:32:14 +0000
9776 +++ tests/regression/apparmor/changehat_misc.sh 2010-08-03 17:27:13 +0000
9777 @@ -64,7 +64,7 @@
9778  echo "*** A 'Killed' message from bash is expected for the following test"
9779  runchecktest "CHANGEHAT (subprofile->subprofile w/ bad magic)" signal9 $subtest $subtest2 badmagic $file
9780  
9781 -# 1. ATTEMPT TO CHANGEGAT TO AN INVALUD PROFILE, SHOULD PUT US INTO A NULL
9782 +# 1. ATTEMPT TO CHANGEHAT TO AN INVALID PROFILE, SHOULD PUT US INTO A NULL
9783  #    PROFILE
9784  # 2. ATTEMPT TO CHANGEHAT OUT WITH BAD TOKEN
9785  settest changehat_fail
9786
9787 === modified file 'tests/regression/apparmor/coredump.c'
9788 --- tests/regression/subdomain/coredump.c       2006-05-19 17:32:14 +0000
9789 +++ tests/regression/apparmor/coredump.c        2010-08-03 17:27:13 +0000
9790 @@ -1,7 +1,9 @@
9791 +#include <stdio.h>
9792  int *ptr;
9793  
9794  /*
9795   *     Copyright (C) 2002-2005 Novell/SUSE
9796 + *     Copyright (C) 2010 Canonical, Ltd
9797   *
9798   *     This program is free software; you can redistribute it and/or
9799   *     modify it under the terms of the GNU General Public License as
9800 @@ -9,7 +11,7 @@
9801   *     License.
9802   */
9803  
9804 -main()
9805 +int main(int argc, char *argv[])
9806  {
9807         printf("This will cause a sigsegv\n");
9808  
9809
9810 === modified file 'tests/regression/apparmor/coredump.sh'
9811 --- tests/regression/subdomain/coredump.sh      2006-05-19 17:32:14 +0000
9812 +++ tests/regression/apparmor/coredump.sh       2010-08-03 17:27:13 +0000
9813 @@ -1,7 +1,6 @@
9814  #! /bin/bash
9815 -# $Id$
9816 -
9817  #      Copyright (C) 2002-2005 Novell/SUSE
9818 +#      Copyright (C) 2010 Canonical, Ltd
9819  #
9820  #      This program is free software; you can redistribute it and/or
9821  #      modify it under the terms of the GNU General Public License as
9822 @@ -11,26 +10,52 @@
9823  #=NAME coredump
9824  #=DESCRIPTION coredump test
9825  
9826 +cleancorefile()
9827 +{
9828 +       rm -f core core.*
9829 +}
9830 +
9831  checkcorefile()
9832  {
9833 -_corefilelist=`echo core.*`
9834 -if [ "$_corefilelist" = "core.*" ]
9835 -then
9836 -       _corefile=no
9837 -else
9838 -       _corefile=yes
9839 -fi
9840 -
9841 -if [ "$1" = "yes" -a "$_corefile" = "no" ]
9842 -then
9843 -       echo "Error: corefile expected but not present - $2"
9844 -elif [ "$1" = "no" -a "$_corefile"  = "yes" ]
9845 -then
9846 -       echo "Error: corefile present when not expected -- $2"
9847 -fi
9848 -
9849 -unset _corefile _corefilelist
9850 -rm -f core.*
9851 +       # global _testdesc _pfmode _known outfile
9852 +       if [ ${1:0:1} == "x" ] ; then
9853 +               requirement=${1#x}
9854 +               _known=" (known problem)"
9855 +        else
9856 +               requirement=$1
9857 +               _known=""
9858 +        fi
9859 +
9860 +       _corefilelist=`echo core.*`
9861 +       if [ ! -f core ] && [ "$_corefilelist" = "core.*" ]
9862 +       then
9863 +               _corefile=no
9864 +       else
9865 +               _corefile=yes
9866 +       fi
9867 +
9868 +       if [ "$requirement" = "yes" -a "$_corefile" = "no" ] ; then
9869 +               if [ -n $_known ] ; then
9870 +                       echo -n "XFAIL: "
9871 +               fi
9872 +               echo "Error: corefile expected but not present - $2"
9873 +               if [ -z $_known ] ; then
9874 +                       cat $profile
9875 +                       testfailed
9876 +               fi
9877 +       elif [ "$requirement" = "no" -a "$_corefile"  = "yes" ] ; then
9878 +               if [ -n "$_known" ] ; then
9879 +                       echo -n "XFAIL: "
9880 +               fi
9881 +               echo "Error: corefile present when not expected -- $2"
9882 +               if [ -z "$_known" ] ; then
9883 +                       cat $profile
9884 +                       testfailed
9885 +               fi
9886 +       fi
9887 +
9888 +       unset _corefile _corefilelist
9889 +       cleancorefile
9890  }
9891  
9892  pwd=`dirname $0`
9893 @@ -45,15 +70,18 @@
9894  
9895  # enable coredumps
9896  ulimit -c 1000000
9897 +cleancorefile
9898 +checkcorefile no "COREDUMP (starting with clean slate)"
9899  
9900  # PASS TEST, no confinement
9901 +cleancorefile
9902  echo "*** A 'Segmentation Fault' message from bash is expected for the following test"
9903  runchecktest "COREDUMP (no confinement)" signal11
9904  checkcorefile yes "COREDUMP (no confinement)"
9905  
9906  # PASS TEST, with r confinement
9907 -genprofile $test:$coreperm
9908 -cat $profile
9909 +cleancorefile
9910 +genprofile image=$test:$coreperm
9911  
9912  echo
9913  echo "*** A 'Segmentation Fault' message from bash is expected for the following test"
9914 @@ -61,10 +89,10 @@
9915  checkcorefile yes "COREDUMP ($coreperm confinement)"
9916  
9917  # FAIL TEST, with x confinement
9918 -genprofile $test:$nocoreperm
9919 -cat $profile
9920 +cleancorefile
9921 +genprofile image=$test:$nocoreperm
9922  
9923  echo
9924  echo "*** A 'Segmentation Fault' message from bash is expected for the following test"
9925  runchecktest "COREDUMP ($nocoreperm confinement)" signal11
9926 -checkcorefile no "COREDUMP ($nocoreperm confinement)"
9927 +checkcorefile xno "COREDUMP ($nocoreperm confinement)"
9928
9929 === modified file 'tests/regression/apparmor/mkprofile.pl'
9930 --- tests/regression/subdomain/mkprofile.pl     2009-11-11 18:44:26 +0000
9931 +++ tests/regression/apparmor/mkprofile.pl      2010-08-03 17:27:13 +0000
9932 @@ -5,7 +5,7 @@
9933  #
9934  # Gawd, I hate writing perl. It shows, too.
9935  #
9936 -my $__VERSION__='$Id$';
9937 +my $__VERSION__=$0;
9938  
9939  use strict;
9940  use Getopt::Long;
9941
9942 === modified file 'tests/regression/apparmor/prologue.inc'
9943 --- tests/regression/subdomain/prologue.inc     2010-02-07 07:04:57 +0000
9944 +++ tests/regression/apparmor/prologue.inc      2010-08-03 17:27:13 +0000
9945 @@ -1,9 +1,14 @@
9946  # vim:syntax=sh
9947  #
9948 -# prologue.inc
9949 -#
9950  # Test infrastructure support.
9951  #
9952 +# Copyright 2010 Canonical, Ltd.
9953 +#
9954 +#      This program is free software; you can redistribute it and/or
9955 +#      modify it under the terms of the GNU General Public License as
9956 +#      published by the Free Software Foundation, version 2 of the
9957 +#      License.
9958 +#
9959  # This file should be included by each test case
9960  # It does a lot of hidden 'magic',  Downside is that
9961  # this magic makes debugging fauling tests more difficult.
9962 @@ -93,8 +98,10 @@
9963  
9964         while [ -h ${link} ]
9965         do
9966 -               if [ -x /usr/bin/readlink ] ; then 
9967 -                       target=$(/usr/bin/readlink ${link})
9968 +               if [ -x /usr/bin/readlink ] ; then
9969 +                       target=$(/usr/bin/readlink -f ${link})
9970 +               elif [ -x /bin/readlink ] ; then
9971 +                       target=$(/bin/readlink -f ${link})
9972                 else 
9973                         # I'm sure there's a more perlish way to do this
9974                         target=$( perl -e "printf (\"%s\n\", readlink(\"${link}\"));") 
9975 @@ -251,6 +258,7 @@
9976                         then
9977                                 echo "Error: ${testname} passed. Test '${_testdesc}' was expected to '${_pfmode}'"
9978                                 testfailed
9979 +                               return
9980                         elif [ "$_pfmode" == "pass" -a -n "${_known}" ]
9981                         then
9982                                 echo "Alert: ${testname} passed. Test '${_testdesc}' was marked as expected pass but known problem (xpass)"
9983 @@ -260,6 +268,7 @@
9984                         then
9985                                 echo "Error: ${testname} failed. Test '${_testdesc}' was expected to '${_pfmode}'. Reason for failure '${ret}'"
9986                                 testfailed
9987 +                               return
9988                         elif [ "$_pfmode" == "fail" -a -n "${_known}" ]
9989                         then
9990                                 echo "Alert: ${testname} failed. Test '${_testdesc}' was marked as expected fail but known problem (xfail)."
9991 @@ -272,16 +281,23 @@
9992                                 then
9993                                         echo "Error: ${testname} failed. Test '${_testdesc}' was expected to terminate with signal ${expectedsig}${_known}. Instead it terminated with signal ${killedsig}"
9994                                         testfailed
9995 +                                       return
9996                                 fi
9997                                 ;;
9998                         *)      echo "Error: ${testname} failed. Test '${_testdesc}' was expected to '${_pfmode}'${_known}. Reason for failure 'killed by signal ${killedsig}'"
9999                                 testfailed
10000 +                               return
10001                                 ;;      
10002                         esac
10003                         ;;
10004                 *)      testerror
10005 +                       return
10006                         ;;
10007         esac
10008 +
10009 +       if [ -n "$VERBOSE" ]; then
10010 +               echo "ok: ${_testdesc}"
10011 +       fi
10012  }
10013  
10014  runchecktest()
10015 @@ -399,22 +415,12 @@
10016                 # it is most often used after --, in fact it is basically
10017                 # mandatory after --
10018                 case "$1" in
10019 -                       profile=*) imagename=`echo $1 | sed 's/^profile=[rix]*//'`
10020 -                                perm=`echo $1 | sed -n 's/^profile=\([rix]*\).*$/\1/p'`
10021 -                                if [ -n "$perm" ]
10022 -                                then
10023 -                                       imageperm=$perm
10024 -                                fi
10025 -                                num_emitted=0
10026 -                                shift
10027 -                                ;;
10028 -
10029 -                       image=*) imagename=`echo $1 | sed 's/^image=[rix]*//'`
10030 +                       image=*) imagename=`echo $1 | sed 's/^image=\([^:]*\).*$/\1/'`
10031                                  if [ ! -x "$imagename" ]
10032                                  then
10033                                         fatalerror "invalid imagename specified in input '$1'"
10034                                  fi
10035 -                                perm=`echo $1 | sed -n 's/^image=\([rix]*\).*$/\1/p'`
10036 +                                perm=`echo $1 | sed -n 's/^image=[^:]*:\(.*\)$/\1/p'`
10037                                  if [ -n "$perm" ]
10038                                  then
10039                                         imageperm=$perm
10040
10041 === modified file 'tests/regression/apparmor/pwrite.sh'
10042 --- tests/regression/subdomain/pwrite.sh        2007-12-23 00:58:47 +0000
10043 +++ tests/regression/apparmor/pwrite.sh 2010-08-03 17:27:13 +0000
10044 @@ -27,7 +27,7 @@
10045  
10046  genprofile $file:$okperm
10047  
10048 -runtestbg "PWRITE with w" pass $file
10049 +runtestbg "PREAD/PWRITE with rw" pass $file
10050  
10051  sleep 2
10052  
10053
10054 === modified file 'tests/regression/apparmor/swap.sh'
10055 --- tests/regression/subdomain/swap.sh  2006-05-19 17:32:14 +0000
10056 +++ tests/regression/apparmor/swap.sh   2010-08-03 17:27:13 +0000
10057 @@ -32,7 +32,7 @@
10058  swap_file=$tmpdir/swapfile
10059  
10060  dd if=/dev/zero of=${swap_file} bs=1024 count=512 2> /dev/null
10061 -/sbin/mkswap ${swap_file} > /dev/null
10062 +/sbin/mkswap -f ${swap_file} > /dev/null
10063  
10064  # TEST 1.  Make sure can enable and disable swap unconfined
10065  
10066
10067 === modified file 'tests/regression/apparmor/syscall.sh'
10068 --- tests/regression/subdomain/syscall.sh       2007-12-23 01:02:50 +0000
10069 +++ tests/regression/apparmor/syscall.sh        2010-08-03 17:27:13 +0000
10070 @@ -1,7 +1,7 @@
10071  #! /bin/bash
10072 -# $Id$
10073 -
10074 +#
10075  #      Copyright (C) 2002-2005 Novell/SUSE
10076 +#      Copyright (C) 2010 Canonical, Ltd.
10077  #
10078  #      This program is free software; you can redistribute it and/or
10079  #      modify it under the terms of the GNU General Public License as
10080 @@ -114,9 +114,9 @@
10081  runchecktest "MKNOD sock (permissions)" fail s $mknod_file
10082  
10083  ##
10084 -## D. SETHOSTNAME
10085 +## C. SYSCTL
10086  ##
10087 -sh syscall_sysctl.sh
10088 +bash syscall_sysctl.sh
10089  
10090  ##
10091  ## D. SETHOSTNAME 
10092
10093 === modified file 'tests/regression/apparmor/syscall_mknod.c'
10094 --- tests/regression/subdomain/syscall_mknod.c  2006-05-19 17:32:14 +0000
10095 +++ tests/regression/apparmor/syscall_mknod.c   2010-08-03 17:27:13 +0000
10096 @@ -19,7 +19,7 @@
10097  
10098  int main(int argc, char *argv[])
10099  {
10100 -int fd, mode;
10101 +       int mode;
10102  
10103         if (argc != 3){
10104                 fprintf(stderr, "usage: %s b|c|f|s|r file\n",
10105 @@ -49,8 +49,6 @@
10106                 return 1;
10107         }
10108  
10109 -       close(fd);
10110 -
10111         printf("PASS\n");
10112  
10113         return 0;
10114
10115 === modified file 'tests/regression/apparmor/unix_fd_server.c'
10116 --- tests/regression/subdomain/unix_fd_server.c 2006-05-19 17:32:14 +0000
10117 +++ tests/regression/apparmor/unix_fd_server.c  2010-08-03 17:27:13 +0000
10118 @@ -2,6 +2,7 @@
10119  
10120  /*
10121   *     Copyright (C) 2002-2005 Novell/SUSE
10122 + *     Copyright (C) 2010 Canonical, Ltd.
10123   *
10124   *     This program is free software; you can redistribute it and/or
10125   *     modify it under the terms of the GNU General Public License as
10126 @@ -134,6 +135,7 @@
10127         }
10128  
10129         /* Check for info re: reading the file */
10130 +       memset(inbound_buffer, 0, sizeof(inbound_buffer));
10131         if (recv(in_sock, inbound_buffer, 16,0) == -1 ) {
10132                 fprintf(stderr, "FAIL - recv %s\n",
10133                         strerror(errno));
10134
10135 === modified file 'tests/stress/parser/stress.rb'
10136 --- tests/stress/parser/stress.rb       2008-11-26 22:16:48 +0000
10137 +++ tests/stress/parser/stress.rb       2010-05-31 18:58:40 +0000
10138 @@ -14,10 +14,27 @@
10139    return sprintf("%0#{len}x", rand(2 ** (4 * len)))
10140  end
10141  
10142 +def get_random_regex()
10143 +  case rand(10)
10144 +    when 0..3
10145 +      return "{#{get_random_name(rand(8) + 2)},#{get_random_name(rand(8) + 2)},#{get_random_name(rand(8) + 2)}}"
10146 +    when 4..5
10147 +      return "[#{get_random_name(rand(5) + 1)}]"
10148 +    when 6..7
10149 +      return "*"
10150 +    when 8..9
10151 +      return "**"
10152 +  end
10153 +end
10154 +
10155  def get_random_path()
10156    out = ""
10157 -  0.upto(rand(20)) do
10158 -    out = "#{out}/#{get_random_name(4)}"
10159 +  0.upto(rand(20) + 2) do
10160 +    if rand(4) == 0
10161 +      out = "#{out}/#{get_random_regex}"
10162 +    else
10163 +      out = "#{out}/#{get_random_name(rand(10) + 4)}"
10164 +    end
10165    end
10166    return out
10167  end
10168 @@ -83,7 +100,10 @@
10169      "mknod",
10170      "lease",
10171      "audit_write",
10172 -    "audit_control"
10173 +    "audit_control",
10174 +    "setfcap",
10175 +    "mac_override",
10176 +    "mac_admin"
10177    ]
10178  
10179    def initialize()
10180 @@ -95,6 +115,93 @@
10181    end
10182  end
10183  
10184 +class NetRule < Rule
10185 +  # XXX Fill me in
10186 +end
10187 +
10188 +class RlimitRule < Rule
10189 +  RLIMIT_LIST = [
10190 +#"cpu",                # cpu rlimit not supported
10191 +    "fsize",
10192 +    "data",
10193 +    "stack",
10194 +    "core",
10195 +    "rss",
10196 +    "nofile",
10197 +    "ofile",
10198 +    "as",
10199 +    "nproc",
10200 +    "memlock",
10201 +    "locks",
10202 +    "sigpending",
10203 +    "msgqueue",
10204 +    "nice",
10205 +    "rtprio"
10206 +  ]
10207 +
10208 +  def initialize()
10209 +    @rlimit = RLIMIT_LIST[rand(RLIMIT_LIST.length)]
10210 +    if rand(20) == 0
10211 +      @limit = "infinity"
10212 +    elsif @rlimit == "nice"
10213 +      @limit = rand(40) - 20
10214 +    else
10215 +      @limit = rand(2 ** 31)
10216 +    end
10217 +  end
10218 +
10219 +  def to_s
10220 +    return "  set rlimit #{@rlimit} <= #{@limit},"
10221 +  end
10222 +end
10223 +
10224 +class Flags
10225 +  FLAG_LIST = [
10226 +    "complain",
10227 +    "audit",
10228 +    "chroot_relative",
10229 +    "namespace_relative",
10230 +    "mediate_deleted",
10231 +    "delegate_deleted",
10232 +    "attach_disconnected",
10233 +    "no_attach_disconnected",
10234 +    "chroot_attach",
10235 +    "chroot_no_attach"
10236 +  ]
10237 +
10238 +  FLAG_CONFLICTS = [
10239 +    ["chroot_relative", "namespace_relative"],
10240 +    ["mediate_deleted", "delegate_deleted"],
10241 +    ["attach_disconnected", "no_attach_disconnected"],
10242 +    ["chroot_attach", "chroot_no_attach"]
10243 +  ]
10244 +
10245 +  def initialize()
10246 +    @flags = []
10247 +    if rand(2) == 1
10248 +      return
10249 +    end
10250 +
10251 +    0.upto(4 - Math.log(rand(32) + 1).to_int) do |x|
10252 +      @flags << FLAG_LIST[rand(FLAG_LIST.length)]
10253 +    end
10254 +
10255 +    FLAG_CONFLICTS.each do |c|
10256 +      if @flags.include?(c[0]) and @flags.include?(c[1])
10257 +        @flags.delete(c[rand(2)])
10258 +      end
10259 +    end
10260 +  end
10261 +
10262 +  def to_s
10263 +    if @flags.empty?
10264 +      return ""
10265 +    end
10266 +    out = @flags.join(",")
10267 +    return "flags=(#{out})"
10268 +  end
10269 +end
10270 +
10271  def prefix_to_s(name)
10272    out = []
10273    out << "#"
10274 @@ -112,16 +219,19 @@
10275      @rvalue = get_random_name()
10276      @name = "/does/not/exist/#{@rvalue}"
10277      @rules = []
10278 +    @flags = Flags.new()
10279    end
10280  
10281    def generate_rules
10282 -    @rules << FileRule.new(@name, "rm")
10283 +    @rules << FileRule.new(@name, "rm").to_s
10284      0.upto(rand($max_rules - $min_rules) + $min_rules) do |x|
10285        case rand(100)
10286 -        when 0..19
10287 -          @rules << CapRule.new
10288 -        when 19..100
10289 -          @rules << FileRule.new
10290 +        when 0..14
10291 +          @rules << CapRule.new.to_s
10292 +        when 15..24
10293 +          @rules << RlimitRule.new.to_s
10294 +        when 25..100
10295 +          @rules << FileRule.new.to_s
10296        end
10297      end
10298    end
10299 @@ -132,10 +242,10 @@
10300      out << "# profile for #{@name}"
10301      out << "# generated by #{__FILE__} #{$my_version}"
10302      out << "#"
10303 -    out << "#{@name} {"
10304 +    out << "#{@name} #{@flags} {"
10305      out << "  #include <abstractions/base>"
10306      out << ""
10307 -    @rules.each { |r| out << r.to_s }
10308 +    @rules.sort.each { |r| out << "  #{r}" }
10309      out << "}"
10310      out << ""
10311    end
10312
10313 === modified file 'utils/SubDomain.pm'
10314 --- utils/SubDomain.pm  2010-03-10 23:30:06 +0000
10315 +++ utils/SubDomain.pm  2010-08-03 17:27:13 +0000
10316 @@ -2,6 +2,7 @@
10317  #
10318  # ----------------------------------------------------------------------
10319  #    Copyright (c) 2006 Novell, Inc. All Rights Reserved.
10320 +#    Copyright (c) 2010 Canonical, Ltd.
10321  #
10322  #    This program is free software; you can redistribute it and/or
10323  #    modify it under the terms of version 2 of the GNU General Public
10324 @@ -2413,10 +2414,13 @@
10325  our $seenmark;
10326  my $RE_LOG_v2_0_syslog = qr/SubDomain/;
10327  my $RE_LOG_v2_1_syslog = qr/kernel:\s+(\[[\d\.\s]+\]\s+)?(audit\([\d\.\:]+\):\s+)?type=150[1-6]/;
10328 +my $RE_LOG_v2_6_syslog = qr/kernel:\s+(\[[\d\.\s]+\]\s+)?type=\d+\s+audit\([\d\.\:]+\):\s+apparmor=/;
10329  my $RE_LOG_v2_0_audit  =
10330      qr/type=(APPARMOR|UNKNOWN\[1500\]) msg=audit\([\d\.\:]+\):/;
10331  my $RE_LOG_v2_1_audit  =
10332      qr/type=(UNKNOWN\[150[1-6]\]|APPARMOR_(AUDIT|ALLOWED|DENIED|HINT|STATUS|ERROR))/;
10333 +my $RE_LOG_v2_6_audit =
10334 +    qr/type=AVC\s+audit\([\d\.\:]+\):\s+apparmor=/;
10335  
10336  sub prefetch_next_log_entry {
10337      # if we already have an existing cache entry, something's broken
10338 @@ -2434,6 +2438,8 @@
10339          $RE_LOG_v2_0_audit  |
10340          $RE_LOG_v2_1_audit  |
10341          $RE_LOG_v2_1_syslog |
10342 +        $RE_LOG_v2_6_syslog |
10343 +        $RE_LOG_v2_6_audit  |
10344          $logmark
10345      }x);
10346  }
10347 @@ -6612,10 +6618,14 @@
10348      LibAppArmor::free_record($event);
10349  
10350      #map new c and d to w as logprof doesn't support them yet
10351 -    $rmask =~ s/c/w/g;
10352 -    $rmask =~ s/d/w/g;
10353 -    $dmask =~ s/c/w/g;
10354 -    $dmask =~ s/d/w/g;
10355 +    if ($rmask) {
10356 +        $rmask =~ s/c/w/g;
10357 +        $rmask =~ s/d/w/g;
10358 +    }
10359 +    if ($dmask) {
10360 +        $dmask =~ s/c/w/g;
10361 +        $dmask =~ s/d/w/g;
10362 +    }
10363  
10364      if ($rmask && !validate_log_mode(hide_log_mode($rmask))) {
10365          fatal_error(sprintf(gettext('Log contains unknown mode %s.'),
10366
10367 === modified file 'utils/apparmor_notify'
10368 --- utils/apparmor_notify       2010-03-10 16:11:26 +0000
10369 +++ utils/apparmor_notify       2010-05-31 18:58:40 +0000
10370 @@ -30,8 +30,7 @@
10371  require Time::Local;
10372  require File::Basename;
10373  
10374 -use vars qw($opt_p $opt_s $opt_l $opt_h $opt_v $opt_d $opt_w);
10375 -use Getopt::Std;
10376 +use Getopt::Long;
10377  
10378  my %prefs;
10379  my $conf = "/etc/apparmor/notify.conf";
10380 @@ -67,7 +66,6 @@
10381  $ENV{SHELL} = "/bin/sh";
10382  defined($ENV{IFS}) and $ENV{IFS} = ' \t\n';
10383  
10384 -print $0 . "\n";
10385  my $prog = File::Basename::basename($0);
10386  
10387  if ($prog !~ /^[a-zA-Z0-9_\-]+$/) {
10388 @@ -75,32 +73,66 @@
10389      exitscript(1);
10390  }
10391  
10392 -my $logfile = "/var/log/kern.log";
10393 --e "/var/run/auditd.pid" and $logfile = "/var/log/audit/audit.log";
10394 -
10395  $> == $< or die "Cannot be suid\n";
10396  $) == $( or die "Cannot be sgid\n";
10397  
10398  my $login;
10399 +our $orig_euid = $>;
10400  
10401 -getopts('dhlpvs:w:');
10402 +my $opt_d = '';
10403 +my $opt_h = '';
10404 +my $opt_l = '';
10405 +my $opt_p = '';
10406 +my $opt_v = '';
10407 +my $opt_f = '';
10408 +my $opt_s = 0;
10409 +my $opt_u = '';
10410 +my $opt_w = 0;
10411 +GetOptions(
10412 +    'debug|d'        => \$opt_d,
10413 +    'help|h'         => \$opt_h,
10414 +    'since-last|l'   => \$opt_l,
10415 +    'poll|p'         => \$opt_p,
10416 +    'verbose|v'      => \$opt_v,
10417 +    'file|f=s'       => \$opt_f,
10418 +    'since-days|s=n' => \$opt_s,
10419 +    'user|u=s'       => \$opt_u,
10420 +    'wait|w=n'       => \$opt_w,
10421 +);
10422  if ($opt_h) {
10423      usage;
10424      exitscript(0);
10425  }
10426  
10427 +# monitor file specified with -f, else use audit.log if auditd is running,
10428 +# otherwise kern.log
10429 +our $logfile = "/var/log/kern.log";
10430 +if ($opt_f) {
10431 +    -f $opt_f or die "'$opt_f' does not exist. Aborting\n";
10432 +    $logfile = $opt_f;
10433 +} else {
10434 +    -e "/var/run/auditd.pid" and $logfile = "/var/log/audit/audit.log";
10435 +}
10436 +
10437 +-r $logfile or die "Cannot read '$logfile'\n";
10438 +our $logfile_inode = get_logfile_inode($logfile);
10439 +our $logfile_size = get_logfile_size($logfile);
10440  open (LOGFILE, "<$logfile") or die "Could not open '$logfile'\n";
10441  # Drop priviliges, if running as root
10442  if ($< == 0) {
10443      $login = "root";
10444      if (defined($ENV{SUDO_UID}) and defined($ENV{SUDO_GID})) {
10445          POSIX::setgid($ENV{SUDO_GID}) or _error("Could not change gid");
10446 -        POSIX::setuid($ENV{SUDO_UID}) or _error("Could not change uid");
10447 +        $> = $ENV{SUDO_UID} or _error("Could not change euid");
10448          defined($ENV{SUDO_USER}) and $login = $ENV{SUDO_USER};
10449      } else {
10450 +        my $drop_to = $nobody_user;
10451 +        if ($opt_u) {
10452 +            $drop_to = $opt_u;
10453 +        }
10454          # nobody/nogroup
10455 -        POSIX::setgid(scalar(getpwnam($nobody_group))) or _error("Could not change gid to '$nobody_group'");
10456 -        POSIX::setuid(scalar(getpwnam($nobody_user))) or _error("Could not change uid to '$nobody_user'");
10457 +        POSIX::setgid(scalar(getgrnam($nobody_group))) or _error("Could not change gid to '$nobody_group'");
10458 +        $> = scalar(getpwnam($drop_to)) or _error("Could not change euid to '$drop_to'");
10459      }
10460  } else {
10461      $login = getlogin();
10462 @@ -111,7 +143,7 @@
10463      readconf($conf);
10464      if (defined($prefs{use_group})) {
10465          my ($name, $passwd, $gid, $members) = getgrnam($prefs{use_group});
10466 -        if (not defined($members) or not defined($login) or not grep { $_ eq $login } split(/ /, $members)) {
10467 +        if (not defined($members) or not defined($login) or (not grep { $_ eq $login } split(/ /, $members) and $login ne "root")) {
10468              _error("'$login' must be in '$prefs{use_group}' group. Aborting");
10469          }
10470      }
10471 @@ -220,7 +252,6 @@
10472      defined($name) and $formatted .= "Name: $name\n";
10473      defined($denied) and $formatted .= "Denied: $denied\n";
10474      defined($family) and defined ($sock_type) and $formatted .= "Family: $family\nSocket type: $sock_type\n";
10475 -    #defined($date) and $since > 0 and $formatted .= "Date: ". scalar(localtime($date)) ."\n";
10476      $formatted .= "Logfile: $logfile\n";
10477  
10478      return $formatted;
10479 @@ -259,6 +290,26 @@
10480      close(PS);
10481  }
10482  
10483 +sub send_message {
10484 +    my $msg = $_[0];
10485 +
10486 +    my $pid = fork();
10487 +    if ($pid == 0) {   # child
10488 +        # notify-send needs $< to be the unprivileged user
10489 +        $< = $>;
10490 +
10491 +        # 'system' uses execvp() so no shell metacharacters here.
10492 +        # $notify_exe is an absolute path so execvp won't search PATH.
10493 +        system "$notify_exe", "-i", "gtk-dialog-warning", "-u", "critical", "--", "AppArmor Message", "$msg";
10494 +        my $exit_code = $? >> 8;
10495 +        exit($exit_code);
10496 +    }
10497 +
10498 +    # parent
10499 +    waitpid($pid, 0);
10500 +    return $?;
10501 +}
10502 +
10503  sub do_notify {
10504      my %seen;
10505      my $seconds = 5;
10506 @@ -273,7 +324,7 @@
10507          umask 0;
10508          open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
10509          open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!";
10510 -        open STDERR, '>/dev/null' or die "Can't write to /dev/null: $!";
10511 +        #open STDERR, '>/dev/null' or die "Can't write to /dev/null: $!";
10512          my $pid = fork();
10513          exit if $pid;
10514          die "Couldn't fork: $!" unless defined($pid);
10515 @@ -293,12 +344,24 @@
10516      my $count = 0;
10517      my $footer = "For more information, please see:\n$url";
10518      my $first_run = 1;
10519 -    my $since = $now - (int($opt_s) * 60 * 60 * 24);
10520 +    my $since = $now;
10521 +    if ($opt_s and int($opt_s) > 0) {
10522 +       $since = $since - (int($opt_s) * 60 * 60 * 24);
10523 +    }
10524      for (my $i=0; $time_to_die == 0; $i++) {
10525 +        if ($logfile_inode != get_logfile_inode($logfile)) {
10526 +            _warn("$logfile changed inodes, reopening");
10527 +            reopen_logfile();
10528 +        } elsif (get_logfile_size($logfile) < $logfile_size) {
10529 +            _warn("$logfile is smaller, reopening");
10530 +            reopen_logfile();
10531 +        }
10532          while(my $msg = <LOGFILE>) {
10533              my @attrib;
10534 -            if ($first_run == 1 and $opt_s) {
10535 -                @attrib = parse_message($msg, $since);
10536 +            if ($first_run == 1) {
10537 +                if ($since != $now) {
10538 +                    @attrib = parse_message($msg, $since);
10539 +                }
10540              } else {
10541                  @attrib = parse_message($msg);
10542              }
10543 @@ -340,12 +403,9 @@
10544  
10545              $m .= $footer;
10546  
10547 -           # 'system' uses execvp() so no shell metacharacters here.
10548 -            # $notify_exe is an absolute path so execvp won't search PATH.
10549 -            system "$notify_exe", "-i", "gtk-dialog-warning", "-u", "critical", "--", "AppArmor Message", "$m";
10550 -            my $exit_code = $? >> 8;
10551 -            if ($exit_code != 0) {
10552 -                _warn("'$notify_exe' exited with '$exit_code'");
10553 +            my $rc = send_message($m);
10554 +            if ($rc != 0) {
10555 +                _warn("'$notify_exe' exited with error '$rc'");
10556                  $time_to_die = 1;
10557                  last;
10558              }
10559 @@ -356,7 +416,7 @@
10560  
10561          if ($first_run) {
10562              if ($count > 0) {
10563 -                my $m = "$logfile contains $count existing denied message";
10564 +                my $m = "$logfile contains $count denied message";
10565                  $count > 1 and $m .= "s";
10566                  if ($opt_s) {
10567                      $m .= " in the last ";
10568 @@ -368,7 +428,7 @@
10569                  }
10570                  $m .= ". ";
10571                  $m .= $footer;
10572 -                system "$notify_exe", "-i", "gtk-dialog-warning", "-u", "critical", "--", "AppArmor Message", "$m";
10573 +                send_message($m);
10574              }
10575              $first_run = 0;
10576          }
10577 @@ -390,6 +450,9 @@
10578  }
10579  
10580  sub show_since {
10581 +    my %msg_hash;
10582 +    my %last_date;
10583 +    my @msg_list;
10584      my $count = 0;
10585      while(my $msg = <LOGFILE>) {
10586          my @attrib = parse_message($msg, $_[0]);
10587 @@ -397,10 +460,31 @@
10588  
10589          my $m = format_message(@attrib);
10590          $m ne "" or next;
10591 -
10592 -        $opt_v and print "$m\n";
10593 +        my $date = $attrib[6];
10594 +        if ($opt_v) {
10595 +            if (exists($msg_hash{$m})) {
10596 +                $msg_hash{$m}++;
10597 +                defined($date) and $last_date{$m} = scalar(localtime($date));
10598 +            } else {
10599 +                $msg_hash{$m} = 1;
10600 +                push(@msg_list, $m);
10601 +            }
10602 +        }
10603          $count++;
10604      }
10605 +    if ($opt_v) {
10606 +        foreach my $m (@msg_list) {
10607 +            print "$m";
10608 +            if ($msg_hash{$m} gt 1) {
10609 +                print "($msg_hash{$m} found";
10610 +                if (exists($last_date{$m})) {
10611 +                    print ", most recent from '$last_date{$m}'";
10612 +                }
10613 +                print ")\n";
10614 +            }
10615 +            print "\n";
10616 +        }
10617 +    }
10618      return $count;
10619  }
10620  
10621 @@ -452,19 +536,63 @@
10622  sub usage {
10623      my $s = <<'EOF';
10624  USAGE: apparmor_notify [OPTIONS]
10625 +
10626  Display AppArmor notifications or messages for DENIED entries.
10627  
10628  OPTIONS:
10629 -  -p           poll AppArmor logs and display notifications
10630 -  -l           display stats since last login
10631 -  -s NUM       show stats for last NUM days (can be used alone or with -p)
10632 -  -v           show messages with stats
10633 -  -h           display this help
10634 -  -w NUM       wait NUM seconds before displaying notifications (with -p)
10635 +  -p, --poll                   poll AppArmor logs and display notifications
10636 +  -f FILE, --file=FILE         search FILE for AppArmor messages
10637 +  -l, --since-last             display stats since last login
10638 +  -s NUM, --since-days=NUM     show stats for last NUM days (can be used alone
10639 +                               or with -p)
10640 +  -v, --verbose                        show messages with stats
10641 +  -h, --help                   display this help
10642 +  -u USER, --user=USER         user to drop privileges to when not using sudo
10643 +  -w NUM, --wait=NUM           wait NUM seconds before displaying
10644 +                               notifications (with -p)
10645  EOF
10646      print $s;
10647  }
10648  
10649 +sub reopen_logfile {
10650 +    # reopen the logfile, temporarily switching back to starting euid for
10651 +    # file permissions.
10652 +    close(LOGFILE);
10653 +
10654 +    my $old_euid = $>;
10655 +    my $change_euid = 0;
10656 +    if ($> != $<) {
10657 +        _debug("raising privileges to '$orig_euid' in reopen_logfile()");
10658 +        $change_euid = 1;
10659 +        $> = $orig_euid;
10660 +        $> == $orig_euid or die "Could not raise privileges\n";
10661 +    }
10662 +
10663 +    $logfile_inode = get_logfile_inode($logfile);
10664 +    $logfile_size = get_logfile_size($logfile);
10665 +    open (LOGFILE, "<$logfile") or die "Could not open '$logfile'\n";
10666 +
10667 +    if ($change_euid) {
10668 +        _debug("dropping privileges to '$old_euid' in reopen_logfile()");
10669 +        $> = $old_euid;
10670 +        $> == $old_euid or die "Could not drop privileges\n";
10671 +    }
10672 +}
10673 +
10674 +sub get_logfile_size {
10675 +    my $fn = $_[0];
10676 +    my $size;
10677 +    defined(($size = (stat($fn))[7])) or (sleep(10) and defined(($size = (stat($fn))[7])) or die "'$fn' disappeared. Aborting\n");
10678 +    return $size;
10679 +}
10680 +
10681 +sub get_logfile_inode {
10682 +    my $fn = $_[0];
10683 +    my $inode;
10684 +    defined(($inode = (stat($fn))[1])) or (sleep(10) and defined(($inode = (stat($fn))[1])) or die "'$fn' disappeared. Aborting\n");
10685 +    return $inode;
10686 +}
10687 +
10688  #
10689  # end Subroutines
10690  #
10691
10692 === modified file 'utils/apparmor_notify.pod'
10693 --- utils/apparmor_notify.pod   2010-02-12 16:25:02 +0000
10694 +++ utils/apparmor_notify.pod   2010-05-31 18:58:40 +0000
10695 @@ -40,24 +40,37 @@
10696  
10697  =over 4
10698  
10699 -=item -p
10700 +=item -p, --poll
10701  
10702  poll AppArmor logs and display desktop notifications. Can be used with '-s'
10703  option to display a summary on startup.
10704  
10705 -=item -l
10706 +=item -f FILE, --file=FILE
10707 +
10708 +search FILE for AppArmor messages
10709 +
10710 +=item -l, --since-last
10711  
10712  show summary since last login.
10713  
10714 -=item -s NUM
10715 +=item -s NUM, --since-days=NUM
10716  
10717  show summary for last NUM of days.
10718  
10719 -=item -v
10720 +=item -u USER, --user=USER
10721 +
10722 +user to drop privileges to when running privileged. This has no effect when
10723 +running under sudo.
10724 +
10725 +=item -w NUM, --wait=NUM
10726 +
10727 +wait NUM seconds before displaying notifications (for use with -p)
10728 +
10729 +=item -v, --verbose
10730  
10731  show messages with summaries.
10732  
10733 -=item -h
10734 +=item -h, --help
10735  
10736  displays a short usage statement.
10737  
10738
This page took 0.954756 seconds and 3 git commands to generate.