1 === added file '.bzrignore'
2 --- .bzrignore 1970-01-01 00:00:00 +0000
3 +++ .bzrignore 2010-08-03 17:27:13 +0000
13 +parser/parser_version.h
24 +parser/apparmor_parser
25 +parser/libapparmor_re/regexp.cc
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
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
171 === added file 'README'
172 --- README 1970-01-01 00:00:00 +0000
173 +++ README 2010-08-03 17:27:13 +0000
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.
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).
193 +For more information, you can read the techdoc.pdf (available after
194 +building the parser) and http://apparmor.wiki.kernel.org.
201 +AppArmor consists of several different parts:
203 +changehat/ source for using changehat with Apache, PAM and Tomcat
204 +common/ common makefile rules
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
214 +------------------------------------------
215 +Building and Installing AppArmor Userspace
216 +------------------------------------------
218 +To build and install AppArmor userspace on your system, build and install in
219 +the following order.
223 +$ cd ./libraries/libapparmor
225 +$ sh ./configure --prefix=/usr --with-perl
239 +$ make tests # not strictly necessary as they are run during the
244 +Apache mod_apparmor:
245 +$ cd changehat/mod_apparmor
246 +$ LIBS="-lapparmor" make
251 +$ cd changehat/pam_apparmor
252 +$ LIBS="-lapparmor -lpam" make
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.
274 +For details on structure and adding tests, see
275 +tests/regression/apparmor/README.
278 +$ cd tests/regression/apparmor (requires root)
281 +$ sudo bash open.sh -r # runs and saves the last testcase from open.sh
286 +For details on structure and adding tests, see parser/tst/README.
296 +For details on structure and adding tests, see libraries/libapparmor/README.
297 +$ cd libraries/libapparmor
303 +To run AppArmor stress tests:
316 +Please note that the above will stress the system so much it may end up
317 +invoking the OOM killer.
319 +To run parser stress tests (requires /usr/bin/ruby):
322 +(see stress.sh -h for options)
324 +-----------------------------------------------
325 +Building and Installing AppArmor Kernel Patches
326 +-----------------------------------------------
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
335 echo "/tmp/${NAME}" ; \
338 -RPMHOSTVENDOR=$(shell rpm --eval "%{_host_vendor}")
339 +RPMHOSTVENDOR=$(shell which rpm && rpm --eval "%{_host_vendor}")
341 DISTRO=$(shell if [ -f /etc/slackware-version ] ; then \
345 SPECFILE = $(NAME).spec
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
355 -CVSPKG_VERSION=$(shell rpm -q --specfile --define "_sourcedir ." ${RPMARG} ${SPECFILE} | head -1 | tr "." "_")
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))
363 - cvs tag IMMUNIX-${CVSPKG_VERSION}
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; \
373 ifdef EXTERNAL_PACKAGE
375 rpm: clean $(BUILDRPMSUBDIRS)
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
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 */
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
393 /* setup command string which is of the form
394 * changehat <token>^hat1\0hat2\0hat3\0..\0
396 - sprintf(buf, "%s %016x^", cmd, token);
397 + sprintf(buf, "%s %016lx^", cmd, token);
398 pos = buf + strlen(buf);
400 for (hats = subprofiles; *hats; hats++) {
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
407 * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
408 * NOVELL (All rights reserved)
409 + * Copyright (c) 2010, Canonical, Ltd.
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
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
431 +%token TOK_KEY_APPARMOR
434 %token TOK_KEY_OPERATION
441 %token TOK_SYSLOG_KERNEL
443 @@ -168,13 +178,14 @@
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
463 other_audit: TOK_TYPE_OTHER audit_msg TOK_MSG_REST
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
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);
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
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; }
492 key_pid: TOK_KEY_PID TOK_EQUALS TOK_DIGITS { ret_record->pid = $3; }
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
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)
505 if (record->name2 != NULL)
507 if (current->protocol_name) {
508 ret = strdup(current->protocol_name);
510 - asprintf(&ret, "unknown(%u)", proto);
511 + if (!asprintf(&ret, "unknown(%u)", proto))
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
522 * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
523 * NOVELL (All rights reserved)
524 + * Copyright (c) 2010, Canonical, Ltd.
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
534 unsigned int string_buf_alloc = 0;
535 unsigned int string_buf_len = 0;
536 char *string_buf = NULL;
538 modes ({mode_chars}+)|({mode_chars}+::{mode_chars}*)|(::{mode_chars}*)
539 /* New message types */
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\""
560 unknown_type UNKNOWN\[{digits}+\]
561 other_audit_type [[:alnum:]\[\]_-]+
567 +key_apparmor "apparmor"
570 key_operation "operation"
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 != '[')
594 {key_attribute} { BEGIN(sub_id); return(TOK_KEY_ATTRIBUTE); }
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); }
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); }
607 {syslog_kernel} { BEGIN(dmesg_timestamp); return(TOK_SYSLOG_KERNEL); }
608 {syslog_month} { yylval->t_str = strdup(yytext); return(TOK_DATE_MONTH); }
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
614 EXTRA_DIST =Makefile.PL libapparmor_wrap.c LibAppArmor.pm examples/*.pl
617 noinst_DATA =LibAppArmor.so
620 libapparmor_wrap.c: $(srcdir)/../SWIG/libapparmor.i
621 $(SWIG) -perl -I$(srcdir)/../../src -module LibAppArmor -o $@ $(srcdir)/../SWIG/libapparmor.i
624 #rm -f Makefile.perl Makefile.perl.old
628 \ No newline at end of file
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
636 printf("Name: %s\n", record->name);
638 + if (record->comm != NULL)
640 + printf("Command: %s\n", record->comm);
642 if (record->name2 != NULL)
644 printf("Name2: %s\n", record->name2);
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
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
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
657 +File: test_multi/avc_audit_01.in
658 +Event type: AA_RECORD_DENIED
659 +Audit ID: 1279948288.415:39
665 +Profile: /usr/sbin/cupsd
666 +Name: /home/user/.ssh/
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
677 +type=AVC msg=audit(1279948227.175:27): apparmor="STATUS" operation="profile_replace" name="/sbin/dhclient3" pid=12291 comm="apparmor_parser"
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
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
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
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
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
705 +File: test_multi/avc_audit_03.in
706 +Event type: AA_RECORD_ALLOWED
707 +Audit ID: 1279968846.035:77
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
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
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
732 +File: test_multi/avc_syslog_01.in
733 +Event type: AA_RECORD_DENIED
734 +Audit ID: 1279967133.365:54
740 +Profile: /usr/sbin/cupsd
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
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"
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
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
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
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
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
780 +File: test_multi/avc_syslog_03.in
781 +Event type: AA_RECORD_ALLOWED
782 +Audit ID: 1279968846.035:77
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
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.
805 GNU GENERAL PUBLIC LICENSE
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
812 AAREDIR= libapparmor_re
813 AAREOBJECTS = ${AAREDIR}/libapparmor_re.a
816 -PCREOBJECTS = ${PCREDIR}/pcre.o
818 LEX_C_FILES = parser_lex.c
819 YACC_C_FILES = parser_yacc.c parser_yacc.h
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})))
830 @@ -125,14 +122,25 @@
831 techdoc.txt: techdoc/index.html
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.
841 -apparmor_parser: $(OBJECTS) $(PCREOBJECTS) $(AAREOBJECTS)
843 +manpages: $(MANPAGES)
845 +htmlmanpages: $(HTMLMANPAGES)
849 +docs: manpages htmlmanpages pdf
851 +all: main docs tests
853 +apparmor_parser: $(OBJECTS) $(AAREOBJECTS)
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.
860 parser_yacc.c parser_yacc.h: parser_yacc.y parser.h
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" $< >> $@
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" $< > $@
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)
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)
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
894 -.SILENT: $(PCREOBJECTS)
895 -.PHONY: $(PCREOBJECTS)
897 - make -C $(PCREDIR) "CFLAGS=$(EXTRA_CFLAGS)"
899 .PHONY: install-rhel4
900 install-rhel4: install-redhat
905 -rm -rf techdoc.{aux,log,pdf,toc,txt} techdoc/
906 - make -s -C $(PCREDIR) clean
907 make -s -C $(AAREDIR) clean
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
915 where we will attempt to conform to the RFP vulnerability disclosure
916 protocol: http://www.wiretrip.net/rfp/policy.html
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/>
925 -- The AppArmor development team
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
932 Writes a binary (cached) profile to stdout (implies -K and -T).
934 +=item -o file, --ofile file
936 +Writes a binary (cached) profile to the specified file (implies -K and -T)
940 Set the base directory for resolving #include directives
941 @@ -149,11 +153,43 @@
943 Print the version number and exit.
945 +=item -p, --preprocess
947 +Dump the input profile to stdout out applying preprocessing flattening
948 +includes into the output profile.
952 Given once, only checks the profiles to ensure syntactic correctness.
953 Given twice, dumps its interpretation of the profile for checking.
955 +=item -D n, --dump=n
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.
962 + apparmor_parser --dump=dfa-stats --dump=trans-stats <file>
964 +Use --help=dump to see a full list of which dump flags are supported
966 +=item -O n, --optimize=n
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).
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.
979 +Use --help=optimize to see a full list of which optimization flags are
984 Give a quick reference guide.
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
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,
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);
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
1014 /* child 0 is left, child 1 is right */
1017 + unsigned int label; /* unique number for debug etc */
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.
1025 -map<Node *, int> node_label;
1026 void label_nodes(Node *root)
1029 for (depth_first_traversal i(root); i; i++)
1030 - node_label.insert(make_pair(*i, nodes++));
1031 + i->label = nodes++;
1035 @@ -1225,7 +1225,7 @@
1036 if (!state.empty()) {
1037 State::iterator i = state.begin();
1039 - os << node_label[*i];
1040 + os << (*i)->label;
1041 if (++i == state.end())
1044 @@ -1240,15 +1240,15 @@
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;
1053 if ((*i)->child[1] == 0)
1054 - os << node_label[(*i)->child[0]] << **i;
1055 + os << (*i)->child[0]->label << **i;
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;
1064 @@ -1256,22 +1256,17 @@
1068 -/* Comparison operator for sets of <State *>. */
1070 -class deref_less_than {
1072 - deref_less_than() { }
1073 - bool operator()(T a, T b)
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.
1082 +struct deref_less_than {
1083 + bool operator()(State * const & lhs, State * const & rhs) const
1084 + { return *lhs < *rhs; }
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.
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);
1101 + for (depth_first_traversal i(root); i; i++) {
1102 + (*i)->firstpos.clear();
1103 + (*i)->lastpos.clear();
1104 + (*i)->followpos.clear();
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);
1110 @@ -1715,7 +1717,9 @@
1111 Trans::iterator j = trans.find(*i);
1112 if (j != trans.end())
1120 @@ -2097,24 +2101,11 @@
1121 /* if it overflows the next_check array it fits in as we will
1123 if (c >= next_check.size())
1126 if (next_check[c].second)
1132 - next_check.resize(base + cases.cases.rbegin()->first + 1);
1133 - size_t prev = pos;
1135 - /* find last free list entry */
1138 - x = free_list[x].second;
1140 - x = free_list. size();
1141 - free_list.resize(base + cases.cases.rbegin()->first + 1);
1142 - init_free_list(free_list, prev, x);
1146 @@ -2126,6 +2117,7 @@
1148 State *default_state = dfa.nonmatching;
1152 Trans::iterator i = dfa.trans.find(from);
1153 if (i == dfa.trans.end()) {
1154 @@ -2142,6 +2134,7 @@
1159 /* get the first free entry that won't underflow */
1160 while (x && (x < c)) {
1162 @@ -2154,15 +2147,24 @@
1163 x = free_list[x].second;
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)
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);
1188 + first_free = old_size;;
1189 + if (x == old_size)
1194 @@ -2194,8 +2196,9 @@
1195 st.insert(make_pair(i->second, i->first));
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++) {
1202 os << "(" << accept[i] << ", "
1203 << num[default_base[i].first] << ", "
1204 << default_base[i].second << ")";
1205 @@ -2206,7 +2209,7 @@
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)
1214 @@ -2565,9 +2568,9 @@
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)
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);
1225 #define FLAGS_WIDTH 2
1226 @@ -2598,7 +2601,8 @@
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,
1234 Node *tree = NULL, *accept;
1236 @@ -2715,6 +2719,18 @@
1240 + if (flags & DFA_DUMP_RULE_EXPR) {
1243 + for (int i = 1; i < count; i++) {
1253 rules->root = new AltNode(rules->root, new CatNode(tree, accept));
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
1260 * Copyright (c) 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007
1261 * NOVELL (All rights reserved)
1263 + * Copyright (c) 2010
1264 + * Canonical, Ltd. (All rights reserved)
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.
1270 * GNU General Public License for more details.
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
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"
1286 struct cod_pattern {
1287 char *regex; // posix regex
1288 - pcre *compiled; // compiled regex, size is compiled->size
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
1299 -#define AARE_PCRE 1
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;
1310 +extern int preprocess_only;
1311 +extern FILE *ofile;
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);
1318 /* parser_symtab.c */
1319 +struct set_value {;
1321 + struct set_value *next;
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);
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);
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
1351 * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
1352 * NOVELL (All rights reserved)
1353 + * Copyright (c) 2010
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
1359 * GNU General Public License for more details.
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.
1366 /* Handle subdomain includes, as a straight forward preprocessing phase.
1367 @@ -270,3 +270,63 @@
1372 +struct include_stack_t {
1375 + struct include_stack_t *next;
1378 +struct include_stack_t *include_stack_head = NULL;
1380 +static void start_include_position(char *filename)
1382 + if (current_filename)
1383 + free(current_filename);
1384 + current_filename = strdup(filename ? filename : "stdin");
1385 + current_lineno = 1;
1388 +void push_include_stack(char *filename)
1390 + struct include_stack_t *include = NULL;
1392 + include = malloc(sizeof(*include));
1394 + perror("malloc of included file stack tracker");
1395 + /* failures in this area are non-fatal */
1399 + include->filename = strdup(current_filename);
1400 + include->lineno = current_lineno;
1401 + include->next = include_stack_head;
1402 + include_stack_head = include;
1404 + start_include_position(filename);
1407 +void pop_include_stack(void)
1409 + struct include_stack_t *include = NULL;
1411 + if (!include_stack_head)
1414 + include = include_stack_head;
1415 + include_stack_head = include->next;
1417 + if (current_filename)
1418 + free(current_filename);
1419 + current_filename = include->filename;
1420 + current_lineno = include->lineno;
1424 +void reset_include_stack(char *filename)
1426 + while (include_stack_head)
1427 + pop_include_stack();
1429 + start_include_position(filename);
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
1439 * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
1440 * NOVELL (All rights reserved)
1441 + * Copyright (c) 2010
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
1447 * GNU General Public License for more details.
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.
1454 #ifndef PARSER_INCLUDE_H
1455 #define PARSER_INCLUDE_H
1457 extern int preprocess_only;
1458 +extern int current_lineno;
1459 +extern char *current_filename;
1461 extern int add_search_dir(char *dir);
1462 extern void init_base_dir(void);
1464 extern int do_include_preprocessing(char *profilename);
1465 FILE *search_path(char *filename, char **fullpath);
1467 +extern void push_include_stack(char *filename);
1468 +extern void pop_include_stack(void);
1469 +extern void reset_include_stack(char *filename);
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
1477 PERROR(_("%s: Unable to write to stdout\n"),
1480 + case OPTION_OFILE:
1481 + PERROR(_("%s: Unable to write to output file\n"),
1484 PERROR(_("%s: ASSERT: Invalid option: %d\n"),
1490 + case OPTION_OFILE:
1493 PERROR(_("%s: ASSERT: Invalid option: %d\n"),
1494 @@ -451,57 +455,6 @@
1498 -int sd_serialize_pattern(sd_serialize *p, pcre *pat)
1500 - if (!sd_write_struct(p, "pcre"))
1502 - if (!sd_write32(p, pat->size - sizeof(pcre)))
1504 - if (!sd_write32(p, pat->magic_number))
1506 - if (!sd_write32(p, pat->options))
1508 - if (!sd_write16(p, pat->top_bracket))
1510 - if (!sd_write16(p, pat->top_backref))
1512 - if (!sd_write8(p, pat->first_char))
1514 - if (!sd_write8(p, pat->req_char))
1516 - if (!sd_write8(p, pat->code[0]))
1518 - if (!sd_write_blob(p, &pat->code[1], pat->size - sizeof(pcre), NULL))
1520 - if (!sd_write_structend(p))
1526 -int sd_serialize_file_entry(sd_serialize *p, struct cod_entry *file_entry)
1528 - PDEBUG("Writing file entry. name '%s'\n", file_entry->name);
1529 - if (!sd_write_struct(p, "fe"))
1531 - if (!sd_write_string(p, file_entry->name, NULL))
1533 - if (!sd_write32(p, file_entry->mode))
1535 - if (!sd_write32(p, file_entry->pattern_type))
1537 - if (file_entry->pattern_type == ePatternRegex) {
1538 - if (!sd_write_string(p, file_entry->pat.regex, NULL))
1540 - if (!sd_serialize_pattern(p, file_entry->pat.compiled))
1543 - if (!sd_write_structend(p))
1549 int sd_serialize_dfa(sd_serialize *p, void *dfa, size_t size)
1551 if (dfa && !sd_write_aligned_blob(p, dfa, size, "aadfa"))
1552 @@ -594,18 +547,6 @@
1556 -int count_pcre_ents(struct cod_entry *list)
1558 - struct cod_entry *entry;
1560 - list_for_each(list, entry) {
1561 - if (entry->pattern_type == ePatternRegex) {
1568 int sd_serialize_profile(sd_serialize *p, struct codomain *profile,
1571 @@ -724,47 +665,8 @@
1572 if (!sd_serialize_xtable(p, profile->exec_table))
1575 - /* pcre globbing entries */
1576 - if (count_pcre_ents(profile->entries)) {
1577 - if (!sd_write_list(p, "pgent"))
1579 - list_for_each(profile->entries, entry) {
1580 - if (entry->pattern_type == ePatternRegex) {
1581 - if (!sd_serialize_file_entry(p, entry))
1585 - if (!sd_write_listend(p))
1589 - /* simple globbing entries */
1590 - if (count_tailglob_ents(profile->entries)) {
1591 - if (!sd_write_list(p, "sgent"))
1593 - list_for_each(profile->entries, entry) {
1594 - if (entry->pattern_type == ePatternTailGlob) {
1595 - if (!sd_serialize_file_entry(p, entry))
1599 - if (!sd_write_listend(p))
1603 - /* basic file entries */
1604 - if (count_file_ents(profile->entries)) {
1605 - if (!sd_write_list(p, "fent"))
1607 - list_for_each(profile->entries, entry) {
1608 - if (entry->pattern_type == ePatternBasic) {
1609 - if (!sd_serialize_file_entry(p, entry))
1613 - if (!sd_write_listend(p))
1616 + PERROR(_("Unknown pattern type\n"));
1620 if (profile->hat_table && regex_type != AARE_DFA) {
1623 int sd_serialize_codomain(int option, struct codomain *cod)
1627 int error = -ENOMEM, size, wsize;
1628 sd_serialize *work_area;
1629 char *filename = NULL;
1630 @@ -837,22 +739,29 @@
1631 filename = "stdout";
1634 + case OPTION_OFILE:
1635 + fd = dup(fileno(ofile));
1643 - if (kernel_load && fd < 0) {
1644 - PERROR(_("Unable to open %s - %s\n"), filename,
1648 + PERROR(_("Unable to open %s - %s\n"), filename,
1651 + PERROR(_("Unable to open output file - %s\n"),
1659 - if (option != OPTION_STDOUT)
1660 + if (option != OPTION_STDOUT && option != OPTION_OFILE)
1663 if (option == OPTION_REMOVE) {
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);
1674 free_sd_serial(work_area);
1677 - if (kernel_load) close(fd);
1680 if (cod->hat_table && regex_type == AARE_DFA && option != OPTION_REMOVE) {
1681 if (load_flattened_hats(cod) != 0)
1684 int sd_load_buffer(int option, char *buffer, int size)
1688 int error = -ENOMEM, wsize, bsize;
1689 char *filename = NULL;
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
1699 * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
1700 * NOVELL (All rights reserved)
1701 + * Copyright (c) 2010
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
1707 * GNU General Public License for more details.
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.
1714 /* Definitions section */
1717 #define NPDEBUG(fmt, args...) /* Do nothing */
1719 -int current_lineno = 1;
1720 +#define DUMP_PREPROCESS do { if (preprocess_only) ECHO; } while (0)
1722 +#define YY_NO_INPUT
1724 +int current_lineno = 1;
1725 +char *current_filename = NULL;
1727 struct ignored_suffix_t {
1730 char *fullpath = NULL;
1733 + if (preprocess_only)
1734 + fprintf(yyout, "\n\n##included <%s>\n", filename);
1735 include_file = search_path(filename, &fullpath);
1737 + if (preprocess_only)
1738 + fprintf(yyout, "\n\n##included \"%s\"\n", filename);
1739 fullpath = strdup(filename);
1740 include_file = fopen(fullpath, "r");
1744 - yyerror(_("Could not open '%s'"), fullpath);
1745 + yyerror(_("Could not open '%s'"),
1746 + fullpath ? fullpath: filename);
1748 if (fstat(fileno(include_file), &my_stat))
1749 yyerror(_("fstat failed for '%s'"), fullpath);
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 ));
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));
1775 + pop_include_stack();
1776 yypop_buffer_state();
1777 if ( !YY_CURRENT_BUFFER ) yyterminate();
1780 * a longer match). So now, when I want to
1781 * match any random string, I go into a
1782 * separate state. */
1784 yylval.id = processunquoted(yytext, yyleng);
1785 PDEBUG("Found sub name: \"%s\"\n", yylval.id);
1788 * a longer match). So now, when I want to
1789 * match any random string, I go into a
1790 * separate state. */
1792 yylval.id = processquoted(yytext, yyleng);
1793 PDEBUG("Found sub name: \"%s\"\n", yylval.id);
1800 /* Something we didn't expect */
1801 yyerror(_("Found unexpected character: '%s'"), yytext);
1804 * a longer match). So now, when I want to
1805 * match any random string, I go into a
1806 * separate state. */
1808 yylval.id = processunquoted(yytext, yyleng);
1809 PDEBUG("Found sub name: \"%s\"\n", yylval.id);
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. */
1816 yylval.id = processquoted(yytext, yyleng);
1817 PDEBUG("Found sub name: \"%s\"\n", yylval.id);
1822 - {WS}+ { /* Ignoring whitespace */ }
1823 + {WS}+ { DUMP_PREPROCESS; /* Ignoring whitespace */ }
1826 /* Something we didn't expect */
1827 yyerror(_("Found unexpected character: '%s'"), yytext);
1829 @@ -302,85 +322,99 @@
1835 return TOK_FLAG_OPENPAREN;
1841 return TOK_FLAG_CLOSEPAREN;
1844 - {WS}+ { /* Eat whitespace */ }
1845 + {WS}+ { DUMP_PREPROCESS; /* Eat whitespace */ }
1849 PDEBUG("Flag , \n");
1850 return TOK_FLAG_SEP;
1855 PDEBUG("Flag = \n");
1860 yylval.flag_id = strdup(yytext);
1861 PDEBUG("Found flag: \"%s\"\n", yylval.flag_id);
1867 /* Something we didn't expect */
1868 yyerror(_("Found unexpected character: '%s'"), yytext);
1873 - {WS}+ { /* Eat whitespace */ }
1874 + {WS}+ { DUMP_PREPROCESS; /* Eat whitespace */ }
1878 yylval.var_val = processunquoted(yytext, yyleng);
1879 PDEBUG("Found assignment value: \"%s\"\n", yylval.var_val);
1885 yylval.var_val = processquoted(yytext, yyleng);
1886 PDEBUG("Found assignment value: \"%s\"\n", yylval.var_val);
1890 - \\\n { current_lineno++ ; }
1891 + \\\n { DUMP_PREPROCESS; current_lineno++ ; }
1901 - {WS}+ { /* Eat whitespace */ }
1902 + {WS}+ { DUMP_PREPROCESS; /* Eat whitespace */ }
1906 yylval.id = strdup(yytext);
1912 return TOK_END_OF_RULE;
1916 /* Something we didn't expect */
1917 yylval.id = strdup(yytext);
1918 yyerror(_("(network_mode) Found unexpected character: '%s'"), yylval.id);
1927 <CHANGE_PROFILE_MODE>{
1930 PDEBUG("Matched a change profile arrow\n");
1934 * a longer match). So now, when I want to
1935 * match any random string, I go into a
1936 * separate state. */
1938 yylval.id = processunquoted(yytext, yyleng);
1939 PDEBUG("Found change profile name: \"%s\"\n", yylval.id);
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. */
1946 yylval.id = processquoted(yytext, yyleng);
1947 PDEBUG("Found change profile quoted name: \"%s\"\n", yylval.id);
1952 - {WS}+ { /* Ignoring whitespace */ }
1953 + {WS}+ { DUMP_PREPROCESS; /* Ignoring whitespace */ }
1956 /* Something we didn't expect */
1957 yyerror(_("Found unexpected character: '%s'"), yytext);
1959 @@ -421,127 +458,147 @@
1961 #include/.*\r?\n { /* include */
1962 PDEBUG("Matched #include\n");
1967 #.*\r?\n { /* normal comment */
1969 PDEBUG("comment(%d): %s\n", current_lineno, yytext);
1974 -{END_OF_RULE} { return TOK_END_OF_RULE; }
1975 +{END_OF_RULE} { DUMP_PREPROCESS; return TOK_END_OF_RULE; }
1979 PDEBUG("Matched a separator\n");
1985 PDEBUG("Matched a arrow\n");
1990 PDEBUG("Matched equals for assignment\n");
1996 PDEBUG("Matched additive value assignment\n");
1998 return TOK_ADD_ASSIGN;
2001 - {WS}+ { /* Eat whitespace */ }
2002 + {WS}+ { DUMP_PREPROCESS; /* Eat whitespace */ }
2007 yylval.var_val = strdup(yytext);
2013 yylval.id = strdup(yytext);
2014 if (strcmp(yytext, "infinity") == 0)
2019 - {LT_EQUAL} { return TOK_LE; }
2020 + {LT_EQUAL} { DUMP_PREPROCESS; return TOK_LE; }
2025 return TOK_END_OF_RULE;
2043 yylval.set_var = strdup(yytext);
2044 PDEBUG("Found set variable %s\n", yylval.set_var);
2050 yylval.bool_var = strdup(yytext);
2051 PDEBUG("Found boolean variable %s\n", yylval.bool_var);
2052 return TOK_BOOL_VAR;
2057 PDEBUG("Open Brace\n");
2062 PDEBUG("Close Brace\n");
2068 yylval.id = processunquoted(yytext, yyleng);
2069 PDEBUG("Found id: \"%s\"\n", yylval.id);
2075 yylval.id = processquoted(yytext, yyleng);
2076 PDEBUG("Found id: \"%s\"\n", yylval.id);
2082 yylval.mode = strdup(yytext);
2083 PDEBUG("Found modes: %s\n", yylval.mode);
2095 PDEBUG("Found a colon\n");
2103 return TOK_FLAG_OPENPAREN;
2108 int token = get_keyword_token(yytext);
2111 @@ -573,11 +630,13 @@
2115 -{WS}+ { /* Ignoring whitespace */ }
2116 +{WS}+ { DUMP_PREPROCESS; /* Ignoring whitespace */ }
2118 -\r?\n { current_lineno++ ; }
2119 +\r?\n { DUMP_PREPROCESS; current_lineno++ ; }
2124 /* Something we didn't expect */
2125 yyerror(_("Found unexpected character: '%s'"), yytext);
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
2132 * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
2133 * NOVELL (All rights reserved)
2135 + * Copyright (c) 2010
2136 + * Canonical, Ltd. (All rights reserved)
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.
2142 * GNU General Public License for more details.
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,
2154 #include <libintl.h>
2155 +#include <linux/limits.h>
2157 #define _(s) gettext(s)
2162 #include <sys/sysctl.h>
2163 +#include <sys/types.h>
2164 +#include <sys/stat.h>
2167 #include "parser_version.h"
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"
2175 #define PRIVILEGED_OPS (write_cache || kernel_load)
2178 int read_implies_exec = 0;
2180 +int preprocess_only = 0;
2181 +int skip_mode_force = 0;
2183 char *subdomainbase = NULL;
2184 char *match_string = NULL;
2186 int perms_create = 0; /* perms contain create flag */
2187 char *profile_namespace = NULL;
2188 int flag_changehat_version = FLAG_CHANGEHAT_1_5;
2190 -extern int current_lineno;
2191 +FILE *ofile = NULL;
2193 /* per-profile settings */
2194 int force_complain = 0;
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'},
2204 {"Dump", 1, 0, 'D'},
2205 {"optimize", 1, 0, 'O'},
2206 {"Optimize", 1, 0, 'O'},
2207 + {"preprocess", 0, 0, 'p'},
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"
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)
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 ? " " : "",
2253 option = OPTION_ADD;
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)
2265 + skip_read_cache = 1;
2272 option = OPTION_REMOVE;
2277 @@ -297,10 +312,12 @@
2278 set_base_dir(optarg);
2286 opt_force_complain = 1;
2291 @@ -312,17 +329,31 @@
2292 skip_read_cache = 1;
2297 + option = OPTION_OFILE;
2298 + skip_read_cache = 1;
2300 + ofile = fopen(optarg, "w");
2302 + PERROR("%s: Could not open file %s\n",
2303 + progname, optarg);
2308 subdomainbase = strndup(optarg, PATH_MAX);
2312 + skip_read_cache = 1;
2315 } else if (strcmp(optarg, "variables") == 0) {
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) {
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 @@
2341 + preprocess_only = 1;
2342 + skip_mode_force = 1;
2345 display_usage(progname);
2351 - if (strstr(match_string, PCRE))
2352 - regex_type = AARE_PCRE;
2354 if (strstr(match_string, AADFA))
2355 regex_type = AARE_DFA;
2357 @@ -620,20 +655,6 @@
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
2366 - if (!match_string)
2369 - if (regex_type != AARE_NONE)
2375 int process_binary(int option, char *profilename)
2377 char *buffer = NULL;
2378 @@ -695,12 +716,33 @@
2382 -void reset_parser(void)
2383 +void reset_parser(char *filename)
2389 + reset_include_stack(filename);
2392 +int test_for_dir_mode(const char *basename, const char *linkdir)
2396 + if (!skip_mode_force) {
2397 + char *target = NULL;
2398 + if (asprintf(&target, "%s/%s/%s", basedir, linkdir, basename) < 0) {
2399 + perror("asprintf");
2403 + if (access(target, R_OK) == 0)
2412 int process_profile(int option, char *profilename)
2413 @@ -727,37 +769,22 @@
2415 if (profilename && option != OPTION_REMOVE) {
2416 /* make decisions about disabled or complain-mode profiles */
2417 - char *target = NULL;
2418 char *basename = strrchr(profilename, '/');
2422 basename = profilename;
2424 - if (asprintf(&target, "%s/%s/%s", basedir, "disable", basename) < 0) {
2425 - perror("asprintf");
2429 - if (access(target, R_OK) == 0) {
2431 - PERROR("Skipping profile in %s/disable: %s\n", basedir, basename);
2433 + if (test_for_dir_mode(basename, "disable")) {
2435 + PERROR("Skipping profile in %s/disable: %s\n", basedir, basename);
2440 - if (asprintf(&target, "%s/%s/%s", basedir, "force-complain", basename)<0) {
2441 - perror("asprintf");
2445 - if (access(target, R_OK) == 0) {
2447 - PERROR("Warning: found %s in %s/force-complain, forcing complain mode\n", basename, basedir);
2448 - force_complain = 1;
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;
2457 if (!force_complain && !skip_cache) {
2458 fstat(fileno(yyin), &stat_text);
2459 @@ -796,12 +823,15 @@
2464 + reset_parser(profilename);
2470 + if (preprocess_only)
2474 dump_policy_names();
2480 - retval = post_process_policy();
2481 + retval = post_process_policy(debug);
2483 PERROR(_("%s: Errors found in file. Aborting.\n"), progname);
2485 @@ -829,10 +859,6 @@
2489 - if (!regex_support()) {
2490 - die_if_any_regex();
2493 retval = load_policy(option);
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
2511 /* assistance routines */
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>
2530 #define PDEBUG(fmt, args...) printf("Lexer: " fmt, ## args)
2533 #define PDEBUG(fmt, args...) /* Do nothing */
2535 #define NPDEBUG(fmt, args...) /* Do nothing */
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)
2545 @@ -142,42 +146,6 @@
2546 return get_table_token("rlimit", rlimit_table, name);
2549 -static struct keyword_table address_family[] = {
2550 -/* {"unix", AF_UNIX},
2551 - {"local", AF_LOCAL}, */
2552 - {"inet", AF_INET},
2553 -/* {"ax25", AF_AX25},
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},
2566 - {"netlink", AF_NETLINK},
2567 - {"route", AF_ROUTE},
2568 - {"packet", AF_PACKET},
2570 - {"econet", AF_ECONET},
2571 - {"atmsvc", AF_ATMSVC},
2573 - {"irda", AF_IRDA},
2574 - {"pppox", AF_PPPOX},
2575 - {"wanpipe", AF_WANPIPE},
2577 - {"tipc", AF_TIPC},
2578 - {"bluetooth", AF_BLUETOOTH},
2579 - {"iucv", AF_IUCV},
2580 - {"rxrpc", AF_RXRPC}, */
2585 struct network_tuple {
2587 unsigned int family;
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)
2596 #define IS_DIFF_QUAL(mode, q) (((mode) & AA_MAY_EXEC) && (((mode) & AA_EXEC_TYPE) != ((q) & AA_EXEC_TYPE)))
2599 entry->pattern_type = ePatternInvalid;
2600 entry->pat.regex = NULL;
2601 - entry->pat.compiled = NULL;
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;
2611 entry->next = orig->next;
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);
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
2627 * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
2628 * NOVELL (All rights reserved)
2630 + * Copyright (c) 2010
2631 + * Canonical, Ltd. (All rights reserved)
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.
2637 * GNU General Public License for more details.
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,
2650 -int post_process_policy(void)
2651 +int post_process_policy(int debug_only)
2655 @@ -696,11 +700,13 @@
2659 - retval = post_process_regex();
2660 - if (retval != 0) {
2661 - PERROR(_("%s: Errors found during regex postprocess. Aborting.\n"),
2664 + if (!debug_only) {
2665 + retval = post_process_regex();
2666 + if (retval != 0) {
2667 + PERROR(_("%s: Errors found during regex postprocess. Aborting.\n"),
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
2681 #include <libintl.h>
2682 +#include <linux/limits.h>
2683 #define _(s) gettext(s)
2689 BOOL seen_slash = 0;
2692 if (!path || (strlen(path) < 2))
2694 @@ -106,19 +106,6 @@
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
2706 - len = strlen(path);
2707 - if (len > 2 && path[len -1] == '/') {
2708 - path[len - 1] = 0;
2713 static pattern_t convert_aaregex_to_pcre(const char *aare, int anchor,
2718 + if (dfaflags & DFA_DUMP_RULE_EXPR)
2719 + fprintf(stderr, "aare: %s -> ", aare);
2722 /* anchor beginning of regular expression */
2724 @@ -406,85 +396,13 @@
2727 ptype = ePatternInvalid;
2729 + if (dfaflags & DFA_DUMP_RULE_EXPR)
2730 + fprintf(stderr, "%s\n", pcre);
2735 -static int process_pcre_entry(struct cod_entry *entry)
2737 - char tbuf[PATH_MAX + 3]; /* +3 for ^, $ and \0 */
2741 - if (!entry) /* shouldn't happen */
2744 - ptype = convert_aaregex_to_pcre(entry->name, 1, tbuf, PATH_MAX+3, &pos);
2745 - if (ptype == ePatternInvalid)
2748 - entry->pattern_type = ptype;
2751 - * Only use buffer (tbuf) that we built above, if we
2752 - * identified a pattern requiring full regex support.
2754 - if (ptype == ePatternRegex) {
2755 - int pattlen = strlen(tbuf);
2757 - if ((entry->pat.regex = malloc(pattlen + 1))) {
2758 - const char *errorreason;
2761 - strcpy(entry->pat.regex, tbuf);
2763 - if ((entry->pat.compiled =
2764 - pcre_compile(entry->pat.regex, 0,
2765 - &errorreason, &errpos,
2767 - /* NULL out tables, kernel will use a
2770 - entry->pat.compiled->tables = NULL;
2774 - PERROR(_("%s: Failed to compile regex '%s' [original: '%s']\n"),
2775 - progname, entry->pat.regex,
2778 - PERROR(_("%s: error near "),
2781 - for (i = 0; i < errpos; i++) {
2782 - fputc('.', stderr);
2785 - fputc('^', stderr);
2786 - fputc('\n', stderr);
2788 - PERROR(_("%s: error reason: '%s'\n"),
2789 - progname, errorreason);
2791 - free(entry->pat.regex);
2792 - entry->pat.regex = NULL;
2797 - PERROR(_("%s: Failed to compile regex '%s' [original: '%s'] - malloc failed\n"),
2798 - progname, entry->pat.regex, entry->name);
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 */
2811 static const char *local_name(const char *name)
2815 aare_ruleset_t *rule = aare_new_ruleset(0);
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);
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);
2833 cod->xmatch = aare_create_dfa(rule, &cod->xmatch_size,
2835 aare_delete_ruleset(rule);
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))
2848 } else if (entry->mode & ~AA_CHANGE_PROFILE) {
2849 if (!aare_add_rule(dfarules, tbuf, entry->deny, entry->mode,
2851 + entry->audit, dfaflags))
2856 perms |= LINK_TO_LINK_SUBSET(perms);
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))
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);
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))
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))
2877 @@ -631,10 +549,10 @@
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))
2885 - if (!aare_add_rule(dfarules, entry->name, 0, mode, 0))
2886 + if (!aare_add_rule(dfarules, entry->name, 0, mode, 0, dfaflags))
2890 @@ -643,18 +561,13 @@
2892 int post_process_entries(struct codomain *cod)
2894 - int ret = TRUE, rc;
2896 struct cod_entry *entry;
2899 list_for_each(cod->entries, entry) {
2900 - if (regex_type == AARE_DFA) {
2901 - rc = process_dfa_entry(cod->dfarules, entry);
2903 - filter_slashes(entry->name);
2904 - rc = process_pcre_entry(entry);
2907 + if (regex_type == AARE_DFA &&
2908 + !process_dfa_entry(cod->dfarules, entry))
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");
2919 test_string = strdup("/foo/f/oo");
2920 filter_slashes(test_string);
2921 @@ -802,13 +715,11 @@
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/");
2931 -int regex_type = AARE_PCRE;
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
2943 #include <libintl.h>
2944 +#include <linux/limits.h>
2945 #define _(s) gettext(s)
2947 #include "immunix.h"
2954 - struct set_value *next;
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)
2967 struct symtab *result;
2968 struct set_value *valuelist = NULL;
2969 @@ -321,16 +317,17 @@
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)
2976 - struct set_value **valuelist = (struct set_value **) list;
2977 + struct set_value *next;
2980 - if (!valuelist || !(*valuelist))
2981 + if (!list || !(*list))
2984 - ret = (*valuelist)->val;
2985 - (*valuelist) = (*valuelist)->next;
2986 + ret = (*list)->val;
2987 + next = (*list)->next;
2992 @@ -429,10 +426,13 @@
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 : "",
3000 - split->suffix ? split->suffix : "");
3001 + split->suffix ? split->suffix : "")) {
3002 + PERROR("Out of memory\n");
3005 add_to_set(&work_list, expanded_string);
3006 free(expanded_string);
3013 + struct set_value *retptr;
3014 struct symtab *a, *b;
3016 a = new_symtab_entry("blah");
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
3022 * along with this program; if not, contact Novell, Inc.
3026 +#include <stdlib.h>
3030 #include <libintl.h>
3031 +#include <linux/limits.h>
3033 #define _(s) gettext(s)
3038 static int expand_entry_variables(struct cod_entry *entry)
3041 + struct set_value *valuelist;
3044 struct var_string *split_var;
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
3054 * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
3055 * NOVELL (All rights reserved)
3056 + * Copyright (c) 2010
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
3062 * GNU General Public License for more details.
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.
3069 #define YYERROR_VERBOSE 1
3074 +#include "parser_include.h"
3076 #include <netinet/in.h>
3077 #include <arpa/inet.h>
3080 #define CAP_TO_MASK(x) (1ull << (x))
3082 -/* from lex_config, for nice error messages */
3083 -/* extern char *current_file; */
3084 -extern int current_lineno;
3088 struct value_list *next;
3091 flagval: TOK_FLAG_ID
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 @@
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"),
3106 + current_filename ? " in " : "",
3107 + current_filename ? current_filename : "",
3108 + current_lineno, buf);
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);
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
3126 - $(CC) -c $(CFLAGS) $<
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
3135 -/*************************************************
3136 -* Perl-Compatible Regular Expressions *
3137 -*************************************************/
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.
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
3147 -static unsigned char pcre_default_tables[] = {
3149 -/* This table is a lower casing table. */
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,
3184 -/* This table is a case flipping table. */
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,
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. */
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
3275 -/* This table identifies various classes of character by individual bits:
3276 - 0x01 white space character
3278 - 0x04 decimal digit
3279 - 0x08 hexadecimal digit
3280 - 0x10 alphanumeric or '_'
3281 - 0x80 regular expression metacharacter or binary zero
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 */
3317 -/* End of chartables.c */
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
3323 -/* config.h. Generated automatically by configure. */
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.
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. */
3337 -/* Define to empty if the keyword does not work. */
3341 -/* Define to `unsigned' if <stddef.h> doesn't define size_t. */
3343 -/* #undef size_t */
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
3353 -#define HAVE_STRERROR 1
3354 -#define HAVE_MEMMOVE 1
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. */
3360 -#define HAVE_BCOPY 1
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. */
3367 -#define NEWLINE '\n'
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
3376 -/*************************************************
3377 -* Perl-Compatible Regular Expressions *
3378 -*************************************************/
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.
3385 -Written by: Philip Hazel <ph10@cam.ac.uk>
3387 - Copyright (c) 1997-2001 University of Cambridge
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
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.
3398 -2. The origin of this software must not be misrepresented, either by
3399 - explicit claim or by omission.
3401 -3. Altered versions must be plainly marked as such, and must not be
3402 - misrepresented as being the original software.
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 ------------------------------------------------------------------------------
3410 -/* This header contains definitions that are shared between the different
3411 -modules, but which are not relevant to the outside. */
3413 -/* Get the definitions provided by running "configure" */
3415 -#include "config.h"
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
3425 -#undef memmove /* some systems may have a macro */
3427 -#define memmove(a, b, c) bcopy(b, a, c)
3430 -pcre_memmove(unsigned char *dest, const unsigned char *src, size_t n)
3435 -for (i = 0; i < n; ++i) *(--dest) = *(--src);
3437 -#define memmove(a, b, c) pcre_memmove(a, b, c)
3441 -/* Standard C headers plus the external interface definition */
3444 -#include <limits.h>
3445 -#include <stddef.h>
3447 -#include <stdlib.h>
3448 -#include <string.h>
3451 -/* In case there is no definition of offsetof() provided - though any proper
3452 -Standard C system should have one. */
3455 -#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field))
3458 -/* These are the public options that can change during matching. */
3460 -#define PCRE_IMS (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL)
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. */
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 */
3474 -/* Options for the "extra" block produced by pcre_study(). */
3476 -#define PCRE_STUDY_MAPPED 0x01 /* a map of starting chars exists */
3478 -/* Masks for identifying the public options which are permitted at compile
3479 -time, run time or study time, respectively. */
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)
3485 -#define PUBLIC_EXEC_OPTIONS \
3486 - (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY)
3488 -#define PUBLIC_STUDY_OPTIONS 0 /* None defined */
3490 -/* Magic number to provide a small check against being handed junk. */
3492 -#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */
3494 -/* Miscellaneous definitions */
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). */
3514 -#define ESC_N NEWLINE
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. */
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 };
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. */
3542 - OP_END, /* End of pattern */
3544 - /* Values corresponding to backslashed metacharacters */
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 */
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 */
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 */
3571 - OP_UPTO, /* From 0 to n matches */
3573 - OP_EXACT, /* Exactly n matches */
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 */
3581 - OP_NOTUPTO, /* From 0 to n matches */
3583 - OP_NOTEXACT, /* Exactly n matches */
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 */
3591 - OP_TYPEUPTO, /* From 0 to n matches */
3593 - OP_TYPEEXACT, /* Exactly n matches */
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 */
3601 - OP_CRRANGE, /* These are different to the three seta above. */
3604 - OP_CLASS, /* Match a character class */
3605 - OP_REF, /* Match a back reference */
3606 - OP_RECURSE, /* Match this pattern recursively */
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. */
3613 - /* The assertions must come before ONCE and COND */
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 */
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. */
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) */
3628 - OP_BRAZERO, /* These two must remain together and in this */
3629 - OP_BRAMINZERO, /* order. */
3631 - OP_BRANUMBER, /* Used for extracting brackets whose number is greater
3632 - than can fit into an opcode. */
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. */
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
3645 -#define EXTRACT_BASIC_MAX 150
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. */
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)"
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. */
3695 -typedef unsigned char uschar;
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. */
3700 -typedef struct real_pcre {
3701 - unsigned long int magic_number;
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;
3712 -/* The real format of the extra block returned by pcre_study(). */
3714 -typedef struct real_pcre_extra {
3716 - uschar start_bits[32];
3720 -/* Structure for passing "static" information around between the functions
3721 -doing the compiling, so that they are thread-safe. */
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 */
3730 -/* Structure for passing "static" information around between the functions
3731 -doing the matching, so that they are thread-safe. */
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 */
3754 -/* Bit definitions for entries in the pcre_ctypes table. */
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) */
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. */
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 */
3778 -/* Offsets of the various tables from the base tables pointer, and
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)
3787 -/* End of internal.h */
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
3793 -/*************************************************
3794 -* Perl-Compatible Regular Expressions *
3795 -*************************************************/
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.
3802 -Written by: Philip Hazel <ph10@cam.ac.uk>
3804 - Copyright (c) 1997-2001 University of Cambridge
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
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.
3815 -2. The origin of this software must not be misrepresented, either by
3816 - explicit claim or by omission.
3818 -3. Altered versions must be plainly marked as such, and must not be
3819 - misrepresented as being the original software.
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 ------------------------------------------------------------------------------
3828 -/* Define DEBUG to get debugging output on stdout. */
3830 -/* #define DEBUG */
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... */
3837 -#define DPRINTF(p) printf p
3839 -#define DPRINTF(p) /*nothing*/
3842 -/* Include the internals header, which itself includes Standard C headers plus
3843 -the external pcre header. */
3845 -#include "internal.h"
3848 -/* Allow compilation as C++ source code, should anybody want to do that. */
3851 -#define class pcre_class
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
3861 -#define BRASTACK_SIZE 200
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. */
3867 -#ifdef SUPPORT_UTF8
3874 -/* Min and max values for the common repeats; for the maxima, 0 => infinity */
3876 -static const char rep_min[] = { 0, 0, 1, 1, 0, 0 };
3877 -static const char rep_max[] = { 0, 0, 0, 0, 1, 1 };
3879 -/* Text forms of OP_ values and things, for debugging (not all used) */
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"
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
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 */
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. */
3919 -static const char *posix_names[] = {
3920 - "alpha", "lower", "upper",
3921 - "alnum", "ascii", "cntrl", "digit", "graph",
3922 - "print", "punct", "space", "word", "xdigit" };
3924 -static const uschar posix_name_lengths[] = {
3925 - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 };
3927 -/* Table of class bit maps for each POSIX class; up to three may be combined
3928 -to form the class. */
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 */
3947 -/* Definition to allow mutual recursion */
3950 - compile_regex(int, int, int *, uschar **, const uschar **, const char **,
3951 - BOOL, int, int *, int *, compile_data *);
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. */
3958 -typedef struct eptrblock {
3959 - struct eptrblock *prev;
3960 - const uschar *saved_eptr;
3963 -/* Flag bits for the match() function */
3965 -#define match_condassert 0x01 /* Called to check a condition assertion */
3966 -#define match_isgroup 0x02 /* Set if start of bracketed group */
3970 -/*************************************************
3971 -* Global variables *
3972 -*************************************************/
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. */
3979 -void *(*pcre_malloc)(size_t) = malloc;
3980 -void (*pcre_free)(void *) = free;
3984 -/*************************************************
3985 -* Macros and tables for character handling *
3986 -*************************************************/
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. */
3992 -#ifndef SUPPORT_UTF8
3993 -#define GETCHARINC(c, eptr) c = *eptr++;
3994 -#define GETCHARLEN(c, eptr, len) c = *eptr;
3995 -#define BACKCHAR(eptr)
3997 -#else /* SUPPORT_UTF8 */
3999 -/* Get the next UTF-8 character, advancing the pointer */
4001 -#define GETCHARINC(c, eptr) \
4003 - if (md->utf8 && (c & 0xc0) == 0xc0) \
4005 - int a = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \
4007 - c = (c & utf8_table3[a]) << s; \
4011 - c |= (*eptr++ & 0x3f) << s; \
4015 -/* Get the next UTF-8 character, not advancing the pointer, setting length */
4017 -#define GETCHARLEN(c, eptr, len) \
4020 - if (md->utf8 && (c & 0xc0) == 0xc0) \
4023 - int a = utf8_table4[c & 0x3f]; /* Number of additional bytes */ \
4025 - c = (c & utf8_table3[a]) << s; \
4026 - for (i = 1; i <= a; i++) \
4029 - c |= (eptr[i] & 0x3f) << s; \
4034 -/* If the pointer is not at the start of a character, move it back until
4037 -#define BACKCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr--;
4043 -/*************************************************
4044 -* Default character tables *
4045 -*************************************************/
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
4053 -#include "chartables.c"
4057 -#ifdef SUPPORT_UTF8
4058 -/*************************************************
4059 -* Tables for UTF-8 support *
4060 -*************************************************/
4062 -/* These are the breakpoints for different numbers of bytes in a UTF-8
4065 -static int utf8_table1[] = { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
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. */
4070 -static int utf8_table2[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
4071 -static int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
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
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 };
4084 -/*************************************************
4085 -* Convert character value to UTF-8 *
4086 -*************************************************/
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.
4092 - cvalue the character value
4093 - buffer pointer to buffer for result - at least 6 bytes long
4095 -Returns: number of characters placed in the buffer
4099 -ord2utf8(int cvalue, uschar *buffer)
4102 -for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++)
4103 - if (cvalue <= utf8_table1[i]) break;
4105 -for (j = i; j > 0; j--)
4107 - *buffer-- = 0x80 | (cvalue & 0x3f);
4110 -*buffer = utf8_table2[i] | cvalue;
4117 -/*************************************************
4118 -* Return version string *
4119 -*************************************************/
4121 -#define STRING(a) # a
4122 -#define XSTRING(s) STRING(s)
4127 -return XSTRING(PCRE_MAJOR) "." XSTRING(PCRE_MINOR) " " XSTRING(PCRE_DATE);
4133 -/*************************************************
4134 -* (Obsolete) Return info about compiled pattern *
4135 -*************************************************/
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().
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 ^,
4151 -Returns: number of capturing subpatterns
4152 - or negative values on error
4156 -pcre_info(const pcre *external_re, int *optptr, int *first_char)
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;
4170 -/*************************************************
4171 -* Return info about compiled pattern *
4172 -*************************************************/
4174 -/* This is a newer "info" function which has an extensible interface so
4175 -that additional items can be added compatibly.
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
4183 -Returns: 0 if data returned, negative on error
4187 -pcre_fullinfo(const pcre *external_re, const pcre_extra *study_data, int what,
4190 -const real_pcre *re = (const real_pcre *)external_re;
4191 -const real_pcre_extra *study = (const real_pcre_extra *)study_data;
4193 -if (re == NULL || where == NULL) return PCRE_ERROR_NULL;
4194 -if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
4198 - case PCRE_INFO_OPTIONS:
4199 - *((unsigned long int *)where) = re->options & PUBLIC_OPTIONS;
4202 - case PCRE_INFO_SIZE:
4203 - *((size_t *)where) = re->size;
4206 - case PCRE_INFO_CAPTURECOUNT:
4207 - *((int *)where) = re->top_bracket;
4210 - case PCRE_INFO_BACKREFMAX:
4211 - *((int *)where) = re->top_backref;
4214 - case PCRE_INFO_FIRSTCHAR:
4216 - ((re->options & PCRE_FIRSTSET) != 0)? re->first_char :
4217 - ((re->options & PCRE_STARTLINE) != 0)? -1 : -2;
4220 - case PCRE_INFO_FIRSTTABLE:
4221 - *((const uschar **)where) =
4222 - (study != NULL && (study->options & PCRE_STUDY_MAPPED) != 0)?
4223 - study->start_bits : NULL;
4226 - case PCRE_INFO_LASTLITERAL:
4228 - ((re->options & PCRE_REQCHSET) != 0)? re->req_char : -1;
4231 - default: return PCRE_ERROR_BADOPTION;
4240 -/*************************************************
4241 -* Debugging function to print chars *
4242 -*************************************************/
4244 -/* Print a sequence of chars in printable format, stopping at the end of the
4245 -subject if the requested.
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
4257 -pchars(const uschar *p, int length, BOOL is_subject, match_data *md)
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);
4269 -/*************************************************
4271 -*************************************************/
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.
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
4287 -Returns: zero or positive => a data character
4288 - negative => a special escape sequence
4289 - on error, errorptr is set
4293 -check_escape(const uschar **ptrptr, const char **errorptr, int bracount,
4294 - int options, BOOL isclass, compile_data *cd)
4296 -const uschar *ptr = *ptrptr;
4299 -/* If backslash is at the end of the pattern, it's an error. */
4302 -if (c == 0) *errorptr = ERR1;
4304 -/* Digits or letters may have special meaning; all others are literals. */
4306 -else if (c < '0' || c > 'z') {}
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. */
4311 -else if ((i = escapes[c - '0']) != 0) c = i;
4313 -/* Escapes that need further processing, or are illegal. */
4317 - const uschar *oldptr;
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:
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. */
4332 - case '1': case '2': case '3': case '4': case '5':
4333 - case '6': case '7': case '8': case '9':
4339 - while ((cd->ctypes[ptr[1]] & ctype_digit) != 0)
4340 - c = c * 10 + *(++ptr) - '0';
4341 - if (c < 10 || c <= bracount)
4343 - c = -(ESC_REF + c);
4346 - ptr = oldptr; /* Put the pointer back and fall through */
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. */
4353 - if ((c = *ptr) >= '8')
4360 - /* \0 always starts an octal number, but we may drop through to here with a
4361 - larger first octal digit. */
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 */
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. */
4375 -#ifdef SUPPORT_UTF8
4376 - if (ptr[1] == '{' && (options & PCRE_UTF8) != 0)
4378 - const uschar *pt = ptr + 2;
4379 - register int count = 0;
4381 - while ((cd->ctypes[*pt] & ctype_xdigit) != 0)
4384 - c = c * 16 + cd->lcc[*pt] -
4385 - (((cd->ctypes[*pt] & ctype_digit) != 0)? '0' : 'W');
4390 - if (c < 0 || count > 8) *errorptr = ERR34;
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. */
4399 - /* Read just a single hex char */
4402 - while (i++ < 2 && (cd->ctypes[ptr[1]] & ctype_xdigit) != 0)
4405 - c = c * 16 + cd->lcc[*ptr] -
4406 - (((cd->ctypes[*ptr] & ctype_digit) != 0)? '0' : 'W');
4410 - /* Other special escapes not starting with a digit are straightforward */
4420 - /* A letter is upper-cased; then the 0x40 bit is flipped */
4422 - if (c >= 'a' && c <= 'z') c = cd->fcc[c];
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. */
4433 - if ((options & PCRE_EXTRA) != 0) switch(c)
4449 -/*************************************************
4450 -* Check for counted repeat *
4451 -*************************************************/
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.
4459 - p pointer to the first char after '{'
4460 - cd pointer to char tables block
4462 -Returns: TRUE or FALSE
4466 -is_counted_repeat(const uschar *p, compile_data *cd)
4468 -if ((cd->ctypes[*p++] & ctype_digit) == 0) return FALSE;
4469 -while ((cd->ctypes[*p] & ctype_digit) != 0) p++;
4470 -if (*p == '}') return TRUE;
4472 -if (*p++ != ',') return FALSE;
4473 -if (*p == '}') return TRUE;
4475 -if ((cd->ctypes[*p++] & ctype_digit) == 0) return FALSE;
4476 -while ((cd->ctypes[*p] & ctype_digit) != 0) p++;
4477 -return (*p == '}');
4482 -/*************************************************
4483 -* Read repeat counts *
4484 -*************************************************/
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.
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
4498 -Returns: pointer to '}' on success;
4499 - current ptr on error, with errorptr set
4502 -static const uschar *
4503 -read_repeat_counts(const uschar *p, int *minp, int *maxp,
4504 - const char **errorptr, compile_data *cd)
4509 -/* Read the minimum value and do a paranoid check: a negative value indicates
4510 -an integer overflow. */
4512 -while ((cd->ctypes[*p] & ctype_digit) != 0) min = min * 10 + *p++ - '0';
4514 -if (min < 0 || min > 65535) {
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. */
4521 -if (*p == '}') max = min; else
4523 - if (*(++p) != '}')
4526 - while((cd->ctypes[*p] & ctype_digit) != 0) max = max * 10 + *p++ - '0';
4527 - if (max < 0 || max > 65535)
4540 -/* Fill in the required variables, and pass back the pointer to the terminating
4550 -/*************************************************
4551 -* Find the fixed length of a pattern *
4552 -*************************************************/
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.
4558 - code points to the start of the pattern (the bracket)
4559 - options the compiling options
4561 -Returns: the fixed length, or -1 if there is no fixed length
4565 -find_fixedlength(uschar *code, int options)
4569 -register int branchlength = 0;
4570 -register uschar *cc = code + 3;
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. */
4578 - register int op = *cc;
4579 - if (op >= OP_BRA) op = OP_BRA;
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);
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. */
4602 - if (length < 0) length = branchlength;
4603 - else if (length != branchlength) return -1;
4604 - if (*cc != OP_ALT) return length;
4609 - /* Skip over assertive subpatterns */
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);
4619 - /* Skip over things that don't match chars */
4622 - case OP_BRANUMBER:
4625 - /* Fall through */
4629 - /* Fall through */
4636 - case OP_NOT_WORD_BOUNDARY:
4637 - case OP_WORD_BOUNDARY:
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
4647 - branchlength += *(++cc);
4648 -#ifdef SUPPORT_UTF8
4649 - for (d = 1; d <= *cc; d++)
4650 - if ((cc[d] & 0xc0) == 0x80) branchlength--;
4655 - /* Handle exact repetitions */
4658 - case OP_TYPEEXACT:
4659 - branchlength += (cc[1] << 8) + cc[2];
4663 - /* Handle single-char matchers */
4665 - case OP_NOT_DIGIT:
4667 - case OP_NOT_WHITESPACE:
4668 - case OP_WHITESPACE:
4669 - case OP_NOT_WORDCHAR:
4677 - /* Check a class for variable quantification */
4685 - case OP_CRMINSTAR:
4687 - case OP_CRMINQUERY:
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];
4702 - /* Anything else is variable length */
4708 -/* Control never gets here */
4714 -/*************************************************
4715 -* Check for POSIX class syntax *
4716 -*************************************************/
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
4724 - ptr pointer to the initial [
4725 - endptr where to return the end pointer
4726 - cd pointer to compile data
4728 -Returns: TRUE or FALSE
4732 -check_posix_syntax(const uschar *ptr, const uschar **endptr, compile_data *cd)
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] == ']')
4749 -/*************************************************
4750 -* Check POSIX class name *
4751 -*************************************************/
4753 -/* This function is called to check the name given in a POSIX-style class entry
4757 - ptr points to the first letter
4758 - len the length of the name
4760 -Returns: a value representing the name, or -1 if unknown
4764 -check_posix_name(const uschar *ptr, int len)
4766 -register int yield = 0;
4767 -while (posix_name_lengths[yield] != 0)
4769 - if (len == posix_name_lengths[yield] &&
4770 - strncmp((const char *)ptr, posix_names[yield], len) == 0) return yield;
4779 -/*************************************************
4780 -* Compile one branch *
4781 -*************************************************/
4783 -/* Scan the pattern, compiling it into the code vector.
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
4796 -Returns: TRUE on success
4797 - FALSE, with *errorptr set on error
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)
4805 -int repeat_type, op_type;
4806 -int repeat_min, repeat_max;
4807 -int bravalue, length;
4808 -int greedy_default, greedy_non_default;
4811 -int subcountlits = 0;
4813 -register uschar *code = *codeptr;
4815 -const uschar *ptr = *ptrptr;
4816 -const uschar *tempptr;
4817 -uschar *previous = NULL;
4820 -/* Set up the default and non-default settings for greediness */
4822 -greedy_default = ((options & PCRE_UNGREEDY) != 0);
4823 -greedy_non_default = greedy_default ^ 1;
4825 -/* Initialize no required char, and count of literals */
4827 -*reqchar = prevreqchar = -1;
4830 -/* Switch on next character until the end of the branch */
4834 - BOOL negate_class;
4835 - int class_charcount;
4836 - int class_lastchar;
4842 - if ((options & PCRE_EXTENDED) != 0)
4844 - if ((cd->ctypes[c] & ctype_space) != 0) continue;
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) ;
4856 - /* The branch terminates at end of string, |, or ). */
4865 - /* Handle single-character metacharacters */
4869 - *code++ = OP_CIRC;
4874 - *code++ = OP_DOLL;
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.
4889 - *code++ = OP_CLASS;
4891 - /* If the first character is '^', set the negation flag and skip it. */
4893 - if ((c = *(++ptr)) == '^')
4895 - negate_class = TRUE;
4898 - else negate_class = FALSE;
4900 - /* Keep a count of chars so that we can optimize the case of just a single
4903 - class_charcount = 0;
4904 - class_lastchar = -1;
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
4911 - memset(class, 0, 32 * sizeof(uschar));
4913 - /* Process characters until ] is reached. By writing this as a "do" it
4914 - means that an initial ] is taken as a data character. */
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
4931 - (ptr[1] == ':' || ptr[1] == '.' || ptr[1] == '=') &&
4932 - check_posix_syntax(ptr, &tempptr, cd))
4934 - BOOL local_negate = FALSE;
4935 - int posix_class, i;
4936 - register const uschar *cbits = cd->cbits;
4938 - if (ptr[1] != ':')
4940 - *errorptr = ERR31;
4947 - local_negate = TRUE;
4951 - posix_class = check_posix_name(ptr, tempptr - ptr);
4952 - if (posix_class < 0)
4954 - *errorptr = ERR30;
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. */
4962 - if ((options & PCRE_CASELESS) != 0 && posix_class <= 2)
4965 - /* Or into the map we are building up to 3 of the static class
4966 - tables, or their negations. */
4969 - for (i = 0; i < 3; i++)
4971 - int taboffset = posix_class_maps[posix_class + i];
4972 - if (taboffset < 0) break;
4974 - for (c = 0; c < 32; c++) class[c] |= ~cbits[c+taboffset];
4976 - for (c = 0; c < 32; c++) class[c] |= cbits[c+taboffset];
4979 - ptr = tempptr + 1;
4980 - class_charcount = 10; /* Set > 1; assumes more than 1 per class */
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. */
4994 - c = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd);
4995 - if (-c == ESC_b) c = '\b';
4998 - register const uschar *cbits = cd->cbits;
4999 - class_charcount = 10;
5003 - for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_digit];
5007 - for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_digit];
5011 - for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_word];
5015 - for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_word];
5019 - for (c = 0; c < 32; c++) class[c] |= cbits[c+cbit_space];
5023 - for (c = 0; c < 32; c++) class[c] |= ~cbits[c+cbit_space];
5032 - /* Fall through if single character, but don't at present allow
5033 - chars > 255 in UTF-8 mode. */
5035 -#ifdef SUPPORT_UTF8
5038 - *errorptr = ERR33;
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. */
5048 - if (ptr[1] == '-' && ptr[2] != ']')
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. */
5066 - const uschar *oldptr = ptr;
5067 - d = check_escape(&ptr, errorptr, *brackets, options, TRUE, cd);
5069 -#ifdef SUPPORT_UTF8
5072 - *errorptr = ERR33;
5076 - /* \b is backslash; any other special means the '-' was literal */
5080 - if (d == -ESC_b) d = '\b'; else
5083 - goto SINGLE_CHARACTER; /* A few lines below */
5094 - for (; c <= d; c++)
5096 - class[c/8] |= (1 << (c&7));
5097 - if ((options & PCRE_CASELESS) != 0)
5099 - int uc = cd->fcc[c]; /* flip case */
5100 - class[uc/8] |= (1 << (uc&7));
5102 - class_charcount++; /* in case a one-char range */
5103 - class_lastchar = c;
5105 - continue; /* Go get the next char in the class */
5108 - /* Handle a lone single character - we can get here for a normal
5109 - non-escape char, or after \ that introduces a single character. */
5113 - class [c/8] |= (1 << (c&7));
5114 - if ((options & PCRE_CASELESS) != 0)
5116 - c = cd->fcc[c]; /* flip case */
5117 - class[c/8] |= (1 << (c&7));
5119 - class_charcount++;
5120 - class_lastchar = c;
5123 - /* Loop until ']' reached; the check for end of string happens inside the
5124 - loop. This "while" is the end of the "do" above. */
5126 - while ((c = *(++ptr)) != ']');
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
5133 - if (class_charcount == 1 && class_lastchar >= 0)
5137 - code[-1] = OP_NOT;
5141 - code[-1] = OP_CHARS;
5144 - *code++ = class_lastchar;
5147 - /* Otherwise, negate the 32-byte map if necessary, and copy it into
5148 - the code vector. */
5153 - for (c = 0; c < 32; c++) code[c] = ~class[c];
5155 - memcpy(code, class, 32);
5160 - /* Various kinds of repeat */
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;
5183 - if (previous == NULL)
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. */
5193 - if (ptr[1] == '?')
5194 - { repeat_type = greedy_non_default; ptr++; }
5195 - else repeat_type = greedy_default;
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. */
5203 - if (*previous == OP_CHARS)
5205 - int len = previous[1];
5207 - if (repeat_min == 0) *reqchar = prevreqchar;
5208 - *countlits += repeat_min - 1;
5217 - c = previous[len+1];
5221 - op_type = 0; /* Use single-char op codes */
5222 - goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */
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. */
5229 - else if ((int)*previous == OP_NOT)
5231 - op_type = OP_NOTSTAR - OP_STAR; /* Use "not" opcodes */
5234 - goto OUTPUT_SINGLE_REPEAT;
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. */
5241 - else if ((int)*previous < OP_EODN || *previous == OP_ANY)
5243 - op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */
5247 - OUTPUT_SINGLE_REPEAT:
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. */
5252 - if (repeat_max == 0) goto END_REPEAT;
5254 - /* Combine the op_type with the repeat_type */
5256 - repeat_type += op_type;
5258 - /* A minimum of zero is handled either as the special case * or ?, or as
5259 - an UPTO, with the maximum given. */
5261 - if (repeat_min == 0)
5263 - if (repeat_max == -1) *code++ = OP_STAR + repeat_type;
5264 - else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type;
5267 - *code++ = OP_UPTO + repeat_type;
5268 - *code++ = repeat_max >> 8;
5269 - *code++ = (repeat_max & 255);
5273 - /* The case {1,} is handled as the special case + */
5275 - else if (repeat_min == 1 && repeat_max == -1)
5276 - *code++ = OP_PLUS + repeat_type;
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. */
5283 - if (repeat_min != 1)
5285 - *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */
5286 - *code++ = repeat_min >> 8;
5287 - *code++ = (repeat_min & 255);
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. */
5297 - else if (*previous == OP_CHARS)
5299 - if (code == previous) code += 2; else previous[1]++;
5302 - /* For a single negated character we also have to put back the
5303 - item that got cancelled. */
5305 - else if (*previous == OP_NOT) code++;
5307 - /* If the maximum is unlimited, insert an OP_STAR. */
5309 - if (repeat_max < 0)
5312 - *code++ = OP_STAR + repeat_type;
5315 - /* Else insert an UPTO if the max is greater than the min. */
5317 - else if (repeat_max != repeat_min)
5320 - repeat_max -= repeat_min;
5321 - *code++ = OP_UPTO + repeat_type;
5322 - *code++ = repeat_max >> 8;
5323 - *code++ = (repeat_max & 255);
5327 - /* The character or character type itself comes last in all cases. */
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}. */
5335 - else if (*previous == OP_CLASS || *previous == OP_REF)
5337 - if (repeat_max == 0)
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;
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;
5359 - /* If previous was a bracket group, we may have to replicate it in certain
5362 - else if ((int)*previous >= OP_BRA || (int)*previous == OP_ONCE ||
5363 - (int)*previous == OP_COND)
5366 - int ketoffset = 0;
5367 - int len = code - previous;
5368 - uschar *bralink = NULL;
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
5376 - if (repeat_max == -1)
5378 - register uschar *ket = previous;
5379 - do ket += (ket[1] << 8) + ket[2]; while (*ket != OP_KET);
5380 - ketoffset = code - ket;
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. */
5390 - if (repeat_min == 0)
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. */
5395 - if (subcountlits > 0)
5397 - *reqchar = prevreqchar;
5398 - *countlits -= subcountlits;
5401 - /* If the maximum is also zero, we just omit the group from the output
5404 - if (repeat_max == 0)
5410 - /* If the maximum is 1 or unlimited, we just have to stick in the
5411 - BRAZERO and do no more at this point. */
5413 - if (repeat_max <= 1)
5415 - memmove(previous+1, previous, len);
5417 - *previous++ = OP_BRAZERO + repeat_type;
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. */
5430 - memmove(previous+4, previous, len);
5432 - *previous++ = OP_BRAZERO + repeat_type;
5433 - *previous++ = OP_BRA;
5435 - /* We chain together the bracket offset fields that have to be
5436 - filled in later when the ends of the brackets are reached. */
5438 - offset = (bralink == NULL)? 0 : previous - bralink;
5439 - bralink = previous;
5440 - *previous++ = offset >> 8;
5441 - *previous++ = offset & 255;
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. */
5453 - for (i = 1; i < repeat_min; i++)
5455 - memcpy(code, previous, len);
5458 - if (repeat_max > 0) repeat_max -= repeat_min;
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. */
5467 - if (repeat_max >= 0)
5469 - for (i = repeat_max - 1; i >= 0; i--)
5471 - *code++ = OP_BRAZERO + repeat_type;
5473 - /* All but the final copy start a new nesting, maintaining the
5474 - chain of brackets outstanding. */
5480 - offset = (bralink == NULL)? 0 : code - bralink;
5482 - *code++ = offset >> 8;
5483 - *code++ = offset & 255;
5486 - memcpy(code, previous, len);
5490 - /* Now chain through the pending brackets, and fill in their length
5491 - fields (which are holding the chain links pro tem). */
5493 - while (bralink != NULL)
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;
5501 - *code++ = bra[1] = offset >> 8;
5502 - *code++ = bra[2] = (offset & 255);
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. */
5511 - else code[-ketoffset] = OP_KETRMAX + repeat_type;
5514 - /* Else there's some kind of shambles */
5518 - *errorptr = ERR11;
5522 - /* In all case we no longer have a previous item. */
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. */
5537 - newoptions = options;
5540 - if (*(++ptr) == '?')
5547 - case '#': /* Comment; skip to ket */
5549 - while (*ptr != ')') ptr++;
5552 - case ':': /* Non-extracting bracket */
5553 - bravalue = OP_BRA;
5558 - bravalue = OP_COND; /* Conditional group */
5559 - if ((cd->ctypes[*(++ptr)] & ctype_digit) != 0)
5561 - int condref = *ptr - '0';
5562 - while (*(++ptr) != ')') condref = condref*10 + *ptr - '0';
5565 - *errorptr = ERR35;
5569 - code[3] = OP_CREF;
5570 - code[4] = condref >> 8;
5571 - code[5] = condref & 255;
5577 - case '=': /* Positive lookahead */
5578 - bravalue = OP_ASSERT;
5582 - case '!': /* Negative lookahead */
5583 - bravalue = OP_ASSERT_NOT;
5587 - case '<': /* Lookbehinds */
5590 - case '=': /* Positive lookbehind */
5591 - bravalue = OP_ASSERTBACK;
5595 - case '!': /* Negative lookbehind */
5596 - bravalue = OP_ASSERTBACK_NOT;
5600 - default: /* Syntax error */
5601 - *errorptr = ERR24;
5606 - case '>': /* One-time brackets */
5607 - bravalue = OP_ONCE;
5611 - case 'R': /* Pattern recursion */
5612 - *code++ = OP_RECURSE;
5616 - default: /* Option setting */
5620 - while (*ptr != ')' && *ptr != ':')
5624 - case '-': optset = &unset; break;
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;
5634 - *errorptr = ERR12;
5639 - /* Set up the changed option bits, but don't change anything yet. */
5641 - newoptions = (options | set) & (~unset);
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. */
5654 - if ((options & PCRE_INGROUP) != 0 &&
5655 - (options & PCRE_IMS) != (newoptions & PCRE_IMS))
5658 - *code++ = *optchanged = newoptions & PCRE_IMS;
5660 - options = newoptions; /* Change options at this level */
5661 - previous = NULL; /* This item can't be repeated */
5662 - continue; /* It is complete */
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. */
5670 - bravalue = OP_BRA;
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. */
5681 - if (++(*brackets) > EXTRACT_BASIC_MAX)
5683 - bravalue = OP_BRA + EXTRACT_BASIC_MAX + 1;
5684 - code[3] = OP_BRANUMBER;
5685 - code[4] = *brackets >> 8;
5686 - code[5] = *brackets & 255;
5689 - else bravalue = OP_BRA + *brackets;
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. */
5697 - previous = (bravalue >= OP_ONCE)? code : NULL;
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 */
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. */
5722 - /* If this is a conditional bracket, check that there are no more than
5723 - two branches in the group. */
5725 - else if (bravalue == OP_COND)
5727 - uschar *tc = code;
5732 - tc += (tc[1] << 8) | tc[2];
5734 - while (*tc != OP_KET);
5736 - if (condcount > 2)
5738 - *errorptr = ERR27;
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. */
5751 - if (subreqchar > 0 &&
5752 - (bravalue >= OP_BRA || bravalue == OP_ONCE || bravalue == OP_ASSERT ||
5753 - (bravalue == OP_COND && condcount == 2)))
5755 - prevreqchar = *reqchar;
5756 - *reqchar = subreqchar;
5757 - if (bravalue != OP_ASSERT) *countlits += subcountlits;
5760 - /* Now update the main code pointer to the end of the group. */
5764 - /* Error if hit end of pattern */
5768 - *errorptr = ERR14;
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. */
5779 - c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd);
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. */
5790 - if (-c >= ESC_REF)
5792 - int number = -c - ESC_REF;
5795 - *code++ = number >> 8;
5796 - *code++ = number & 255;
5800 - previous = (-c > ESC_b && -c < ESC_Z)? code : NULL;
5806 - /* Data character: reset and fall through */
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. */
5824 - if ((options & PCRE_EXTENDED) != 0)
5826 - if ((cd->ctypes[c] & ctype_space) != 0) continue;
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;
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. */
5844 - c = check_escape(&ptr, errorptr, *brackets, options, FALSE, cd);
5845 - if (c < 0) { ptr = tempptr; break; }
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. */
5850 -#ifdef SUPPORT_UTF8
5851 - if (c > 127 && (options & PCRE_UTF8) != 0)
5854 - int len = ord2utf8(c, buffer);
5855 - for (c = 0; c < len; c++) *code++ = buffer[c];
5862 - /* Ordinary character or single-char escape */
5868 - /* This "while" is the end of the "do" above. */
5870 - while (length < MAXLIT && (cd->ctypes[c = *(++ptr)] & ctype_meta) == 0);
5872 - /* Update the last character and the count of literals */
5874 - prevreqchar = (length > 1)? code[-2] : *reqchar;
5875 - *reqchar = code[-1];
5876 - *countlits += length;
5878 - /* Compute the length and set it in the data vector, and advance to
5879 - the next state. */
5881 - previous[1] = length;
5882 - if (length < MAXLIT) ptr--;
5885 - } /* end of big loop */
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. */
5899 -/*************************************************
5900 -* Compile sequence of alternatives *
5901 -*************************************************/
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.
5912 - options the option bits
5913 - optchanged new ims options to set as if (?ims) were at the start, or -1
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
5925 -Returns: TRUE on success
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)
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;
5942 -*countlits = INT_MAX;
5943 -code += 3 + skipbytes;
5945 -/* Loop for each alternative branch */
5951 - /* Handle change of options */
5953 - if (optchanged >= 0)
5956 - *code++ = optchanged;
5957 - options = (options & ~PCRE_IMS) | optchanged;
5960 - /* Set up dummy OP_REVERSE if lookbehind assertion */
5964 - *code++ = OP_REVERSE;
5965 - reverse_count = code;
5970 - /* Now compile the branch */
5972 - if (!compile_branch(options, brackets, &code, &ptr, errorptr, &optchanged,
5973 - &branchreqchar, &branchcountlits, cd))
5979 - /* Fill in the length of the last branch */
5981 - length = code - last_branch;
5982 - last_branch[1] = length >> 8;
5983 - last_branch[2] = length & 255;
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
5989 - if (*reqchar != -2)
5991 - if (branchreqchar >= 0)
5993 - if (*reqchar == -1) *reqchar = branchreqchar;
5994 - else if (*reqchar != branchreqchar) *reqchar = -2;
5996 - else *reqchar = -2;
5999 - /* Keep the shortest literal count */
6001 - if (branchcountlits < *countlits) *countlits = branchcountlits;
6002 - DPRINTF(("literal count = %d min=%d\n", branchcountlits, *countlits));
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. */
6011 - length = find_fixedlength(last_branch, options);
6012 - DPRINTF(("fixed length = %d\n", length));
6015 - *errorptr = ERR25;
6019 - reverse_count[0] = (length >> 8);
6020 - reverse_count[1] = length & 255;
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. */
6030 - length = code - start_bracket;
6032 - *code++ = length >> 8;
6033 - *code++ = length & 255;
6034 - if (optchanged >= 0)
6037 - *code++ = oldoptions;
6044 - /* Another branch follows; insert an "or" node and advance the pointer. */
6047 - last_branch = code;
6051 -/* Control never reaches here */
6057 -/*************************************************
6058 -* Find first significant op code *
6059 -*************************************************/
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
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
6071 - optstop TRUE to return on option change, otherwise change the options
6072 - value and continue
6074 -Returns: pointer to the first significant opcode
6077 -static const uschar*
6078 -first_significant_code(const uschar *code, int *options, int optbit,
6083 - switch ((int)*code)
6086 - if (optbit > 0 && ((int)code[1] & optbit) != (*options & optbit))
6088 - if (optstop) return code;
6089 - *options = (int)code[1];
6095 - case OP_BRANUMBER:
6099 - case OP_WORD_BOUNDARY:
6100 - case OP_NOT_WORD_BOUNDARY:
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);
6115 -/* Control never reaches here */
6121 -/*************************************************
6122 -* Check for anchored expression *
6123 -*************************************************/
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.
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.
6136 - code points to start of expression (the bracket)
6137 - options points to the options setting
6139 -Returns: TRUE or FALSE
6143 -is_anchored(register const uschar *code, int *options)
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))
6157 - code += (code[1] << 8) + code[2];
6159 -while (*code == OP_ALT);
6165 -/*************************************************
6166 -* Check for starting with ^ or .* *
6167 -*************************************************/
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).
6174 -Argument: points to start of expression (the bracket)
6175 -Returns: TRUE or FALSE
6179 -is_startline(const uschar *code)
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];
6191 -while (*code == OP_ALT);
6197 -/*************************************************
6198 -* Check for fixed first char *
6199 -*************************************************/
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.
6208 - code points to start of expression (the bracket)
6209 - options pointer to the options (used to check casing changes)
6211 -Returns: -1 or the fixed first char
6215 -find_firstchar(const uschar *code, int *options)
6217 -register int c = -1;
6220 - const uschar *scode = first_significant_code(code + 3, options,
6221 - PCRE_CASELESS, TRUE);
6222 - register int op = *scode;
6224 - if (op >= OP_BRA) op = OP_BRA;
6235 - if ((d = find_firstchar(scode, options)) < 0) return -1;
6236 - if (c < 0) c = d; else if (c != d) return -1;
6239 - case OP_EXACT: /* Fall through */
6242 - case OP_CHARS: /* Fall through */
6247 - if (c < 0) c = scode[1]; else if (c != scode[1]) return -1;
6251 - code += (code[1] << 8) + code[2];
6253 -while (*code == OP_ALT);
6261 -/*************************************************
6262 -* Compile a Regular Expression *
6263 -*************************************************/
6265 -/* This function takes a string and returns a pointer to a block of store
6266 -holding a compiled version of the expression.
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
6275 -Returns: pointer to compiled data block, or NULL on error,
6276 - with errorptr and erroroffset set
6280 -pcre_compile(const char *pattern, int options, const char **errorptr,
6281 - int *erroroffset, const unsigned char *tables)
6284 -int length = 3; /* For initial BRA plus length */
6286 -int c, reqchar, countlits;
6288 -int top_backref = 0;
6289 -int branch_extra = 0;
6290 -int branch_newextra;
6291 -unsigned int brastackptr = 0;
6295 -compile_data compile_block;
6296 -int brastack[BRASTACK_SIZE];
6297 -uschar bralenstack[BRASTACK_SIZE];
6300 -uschar *code_base, *code_end;
6303 -/* Can't support UTF8 unless PCRE has been compiled to include the code. */
6305 -#ifndef SUPPORT_UTF8
6306 -if ((options & PCRE_UTF8) != 0)
6308 - *errorptr = ERR32;
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. */
6316 -if (errorptr == NULL) return NULL;
6319 -/* However, we can give a message for this error */
6321 -if (erroroffset == NULL)
6323 - *errorptr = ERR16;
6328 -if ((options & ~PUBLIC_OPTIONS) != 0)
6330 - *errorptr = ERR17;
6334 -/* Set up pointers to the individual character tables */
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;
6342 -/* Reflect pattern for debugging output */
6344 -DPRINTF(("------------------------------------------------------------------\n"));
6345 -DPRINTF(("%s\n", pattern));
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. */
6354 -ptr = (const uschar *)(pattern - 1);
6355 -while ((c = *(++ptr)) != 0)
6358 - int class_charcount;
6359 - int bracket_length;
6361 - if ((options & PCRE_EXTENDED) != 0)
6363 - if ((compile_block.ctypes[c] & ctype_space) != 0) continue;
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) ;
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. */
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;
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. */
6398 - if (c <= -ESC_REF)
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))
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))
6411 - if (ptr[1] == '?') ptr++;
6419 - case '*': /* These repeats won't be after brackets; */
6420 - case '+': /* those are handled separately */
6425 - /* This covers the cases of repeats after a single char, metachar, class,
6426 - or back reference. */
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))
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;
6441 - if (ptr[1] == '?') ptr++;
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. */
6450 - length += 3 + branch_extra;
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. */
6459 - class_charcount = 0;
6460 - if (*(++ptr) == '^') ptr++;
6465 - int ch = check_escape(&ptr, errorptr, bracount, options, TRUE,
6467 - if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
6468 - if (-ch == ESC_b) class_charcount++; else class_charcount = 10;
6470 - else class_charcount++;
6473 - while (*ptr != 0 && *ptr != ']');
6475 - /* Repeats for negated single chars are handled by the general code */
6477 - if (class_charcount == 1) length += 3; else
6481 - /* A repeat needs either 1 or 5 bytes. */
6483 - if (*ptr != 0 && ptr[1] == '{' && is_counted_repeat(ptr+2, &compile_block))
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))
6491 - if (ptr[1] == '?') ptr++;
6496 - /* Brackets may be genuine groups or special things */
6499 - branch_newextra = 0;
6500 - bracket_length = 3;
6502 - /* Handle special forms of bracket, which all start (? */
6504 - if (ptr[1] == '?')
6509 - switch (c = ptr[2])
6511 - /* Skip over comments entirely */
6514 - while (*ptr != 0 && *ptr != ')') ptr++;
6517 - *errorptr = ERR18;
6518 - goto PCRE_ERROR_RETURN;
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. */
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. */
6538 - if (ptr[3] != ')')
6540 - *errorptr = ERR29;
6541 - goto PCRE_ERROR_RETURN;
6547 - /* Lookbehinds are in Perl from version 5.005 */
6550 - if (ptr[3] == '=' || ptr[3] == '!')
6553 - branch_newextra = 3;
6554 - length += 3; /* For the first branch */
6557 - *errorptr = ERR24;
6558 - goto PCRE_ERROR_RETURN;
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
6565 - if ((compile_block.ctypes[ptr[3]] & ctype_digit) != 0)
6569 - while ((compile_block.ctypes[*ptr] & ctype_digit) != 0) ptr++;
6572 - *errorptr = ERR26;
6573 - goto PCRE_ERROR_RETURN;
6576 - else /* An assertion must follow */
6578 - ptr++; /* Can treat like ':' as far as spacing is concerned */
6579 - if (ptr[2] != '?' ||
6580 - (ptr[3] != '=' && ptr[3] != '!' && ptr[3] != '<') )
6582 - ptr += 2; /* To get right offset in message */
6583 - *errorptr = ERR28;
6584 - goto PCRE_ERROR_RETURN;
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. */
6605 - *optset |= PCRE_CASELESS;
6609 - *optset |= PCRE_MULTILINE;
6613 - *optset |= PCRE_DOTALL;
6617 - *optset |= PCRE_EXTENDED;
6621 - *optset |= PCRE_EXTRA;
6625 - *optset |= PCRE_UNGREEDY;
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
6638 - if (brastackptr == 0)
6640 - options = (options | set) & (~unset);
6641 - set = unset = 0; /* To save length */
6643 - /* Fall through */
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. */
6659 - if (((set|unset) & PCRE_IMS) != 0)
6662 - branch_newextra = 2;
6663 - if (((set|unset) & PCRE_CASELESS) != 0) options |= PCRE_ICHANGED;
6667 - /* Unrecognized option character */
6670 - *errorptr = ERR12;
6671 - goto PCRE_ERROR_RETURN;
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. */
6684 - if (branch_newextra == 2 && (branch_extra == 0 || branch_extra == 3))
6685 - branch_extra += branch_newextra;
6689 - /* If options were terminated by ':' control comes here. Fall through
6690 - to handle the group below. */
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. */
6701 - if (bracount > EXTRACT_BASIC_MAX) bracket_length += 3;
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. */
6709 - if (brastackptr >= sizeof(brastack)/sizeof(int))
6711 - *errorptr = ERR19;
6712 - goto PCRE_ERROR_RETURN;
6715 - bralenstack[brastackptr] = branch_extra;
6716 - branch_extra = branch_newextra;
6718 - brastack[brastackptr++] = length;
6719 - length += bracket_length;
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. */
6735 - if (brastackptr > 0)
6737 - duplength = length - brastack[--brastackptr];
6738 - branch_extra = bralenstack[brastackptr];
6740 - else duplength = 0;
6742 - /* Leave ptr at the final char; for read_repeat_counts this happens
6743 - automatically; for the others we need an increment. */
6745 - if ((c = ptr[1]) == '{' && is_counted_repeat(ptr+2, &compile_block))
6747 - ptr = read_repeat_counts(ptr+2, &minval, &maxval, errorptr,
6749 - if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
6751 - else if (c == '*') { minval = 0; maxval = -1; ptr++; }
6752 - else if (c == '+') { maxval = -1; ptr++; }
6753 - else if (c == '?') { minval = 0; ptr++; }
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. */
6763 - if (maxval > 0) length += (maxval - 1) * (duplength + 7);
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. */
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;
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. */
6792 - if ((options & PCRE_EXTENDED) != 0)
6794 - if ((compile_block.ctypes[c] & ctype_space) != 0) continue;
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) ;
6804 - /* Backslash may introduce a data char or a metacharacter; stop the
6805 - string before the latter. */
6809 - const uschar *saveptr = ptr;
6810 - c = check_escape(&ptr, errorptr, bracount, options, FALSE,
6812 - if (*errorptr != NULL) goto PCRE_ERROR_RETURN;
6813 - if (c < 0) { ptr = saveptr; break; }
6815 -#ifdef SUPPORT_UTF8
6816 - if (c > 127 && (options & PCRE_UTF8) != 0)
6819 - for (i = 0; i < sizeof(utf8_table1)/sizeof(int); i++)
6820 - if (c <= utf8_table1[i]) break;
6826 - /* Ordinary character or single-char escape */
6831 - /* This "while" is the end of the "do" above. */
6833 - while (runlength < MAXLIT &&
6834 - (compile_block.ctypes[c = *(++ptr)] & ctype_meta) == 0);
6837 - length += runlength;
6842 -length += 4; /* For final KET and END */
6844 -if (length > 65539)
6846 - *errorptr = ERR20;
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(). */
6856 -size = length + offsetof(real_pcre, code[0]);
6857 -re = (real_pcre *)(pcre_malloc)(size);
6861 - *errorptr = ERR21;
6865 -/* size of re is sloppily computed, memset to get consistent output */
6866 -memset(re, 0, size);
6868 -/* Put in the magic number, and save the size, options, and table pointer */
6870 -re->magic_number = MAGIC_NUMBER;
6872 -re->options = options;
6873 -re->tables = tables;
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. */
6879 -ptr = (const uschar *)pattern;
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;
6888 -/* If not reached end of pattern on success, there's an excess bracket. */
6890 -if (*errorptr == NULL && *ptr != 0) *errorptr = ERR22;
6892 -/* Fill in the terminating state and check for disastrous overflow, but
6893 -if debugging, leave the test till after things are printed out. */
6898 -if (code - re->code > length) *errorptr = ERR23;
6901 -/* Give an error if there's back reference to a non-existent capturing
6904 -if (top_backref > re->top_bracket) *errorptr = ERR15;
6906 -/* Failed to compile */
6908 -if (*errorptr != NULL)
6911 - PCRE_ERROR_RETURN:
6912 - *erroroffset = ptr - (const uschar *)pattern;
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).
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.
6926 -if ((options & PCRE_ANCHORED) == 0)
6928 - int temp_options = options;
6929 - if (is_anchored(re->code, &temp_options))
6930 - re->options |= PCRE_ANCHORED;
6933 - int ch = find_firstchar(re->code, &temp_options);
6936 - re->first_char = ch;
6937 - re->options |= PCRE_FIRSTSET;
6939 - else if (is_startline(re->code))
6940 - re->options |= PCRE_STARTLINE;
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. */
6947 -if (reqchar >= 0 && (countlits > 1 || (re->options & PCRE_FIRSTSET) == 0))
6949 - re->req_char = reqchar;
6950 - re->options |= PCRE_REQCHSET;
6953 -/* Print out the compiled data for debugging */
6957 -printf("Length = %d top_bracket = %d top_backref = %d\n",
6958 - length, re->top_bracket, re->top_backref);
6960 -if (re->options != 0)
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 " : "");
6974 -if ((re->options & PCRE_FIRSTSET) != 0)
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);
6980 -if ((re->options & PCRE_REQCHSET) != 0)
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);
6987 -code_base = code = re->code;
6989 -while (code < code_end)
6993 - printf("%3d ", code - code_base);
6995 - if (*code >= OP_BRA)
6997 - if (*code - OP_BRA > EXTRACT_BASIC_MAX)
6998 - printf("%3d Bra extra", (code[1] << 8) + code[2]);
7000 - printf("%3d Bra %d", (code[1] << 8) + code[2], *code - OP_BRA);
7004 - else switch(*code)
7007 - printf(" %.2x %s", code[1], OP_names[*code]);
7012 - charlength = *(++code);
7013 - printf("%3d ", charlength);
7014 - while (charlength-- > 0)
7015 - if (isprint(c = *(++code))) printf("%c", c); else printf("\\x%02x", c);
7023 - case OP_ASSERT_NOT:
7024 - case OP_ASSERTBACK:
7025 - case OP_ASSERTBACK_NOT:
7028 - case OP_BRANUMBER:
7031 - printf("%3d %s", (code[1] << 8) + code[2], OP_names[*code]);
7042 - case OP_TYPEMINSTAR:
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++]);
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("?");
7065 - case OP_TYPEEXACT:
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("?");
7076 - if (isprint(c = *(++code))) printf(" [^%c]", c);
7077 - else printf(" [^\\x%02x]", c);
7081 - case OP_NOTMINSTAR:
7083 - case OP_NOTMINPLUS:
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++]);
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("?");
7103 - printf(" \\%d", (code[1] << 8) | code[2]);
7105 - goto CLASS_REF_REPEAT;
7113 - for (i = 0; i < 256; i++)
7115 - if ((code[i/8] & (1 << (i&7))) != 0)
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);
7125 - if (j == '-' || j == ']') printf("\\");
7126 - if (isprint(j)) printf("%c", j); else printf("\\x%02x", j);
7139 - case OP_CRMINSTAR:
7141 - case OP_CRMINPLUS:
7143 - case OP_CRMINQUERY:
7144 - printf("%s", OP_names[*code]);
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("?");
7163 - /* Anything else is just a one-node item */
7166 - printf(" %s", OP_names[*code]);
7173 -printf("------------------------------------------------------------------\n");
7175 -/* This check is done here in the debugging case so that the code that
7176 -was compiled can be seen. */
7178 -if (code - re->code > length)
7180 - *errorptr = ERR23;
7182 - *erroroffset = ptr - (uschar *)pattern;
7192 -/*************************************************
7193 -* Match a back-reference *
7194 -*************************************************/
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.
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
7206 -Returns: TRUE if matched
7210 -match_ref(int offset, register const uschar *eptr, int length, match_data *md,
7211 - unsigned long int ims)
7213 -const uschar *p = md->start_subject + md->offset_vector[offset];
7216 -if (eptr >= md->end_subject)
7217 - printf("matching subject <null>");
7220 - printf("matching subject ");
7221 - pchars(eptr, length, TRUE, md);
7223 -printf(" against backref ");
7224 -pchars(p, length, FALSE, md);
7228 -/* Always fail if not enough characters left */
7230 -if (length > md->end_subject - eptr) return FALSE;
7232 -/* Separate the caselesss case for speed */
7234 -if ((ims & PCRE_CASELESS) != 0)
7236 - while (length-- > 0)
7237 - if (md->lcc[*p++] != md->lcc[*eptr++]) return FALSE;
7240 - { while (length-- > 0) if (*p++ != *eptr++) return FALSE; }
7247 -/*************************************************
7248 -* Match from current position *
7249 -*************************************************/
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
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
7265 - match_condassert - this is an assertion condition
7266 - match_isgroup - this is the start of a bracketed group
7268 -Returns: TRUE if matched
7272 -match(register const uschar *eptr, register const uschar *ecode,
7273 - int offset_top, match_data *md, unsigned long int ims, eptrblock *eptrb,
7276 -unsigned long int original_ims = ims; /* Save for resetting on ')' */
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
7284 -if ((flags & match_isgroup) != 0)
7286 - newptrb.prev = eptrb;
7287 - newptrb.saved_eptr = eptr;
7291 -/* Now start processing the operations. */
7295 - int op = (int)*ecode;
7296 - int min, max, ctype;
7299 - BOOL minimize = FALSE;
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
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
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. */
7318 - int number = op - OP_BRA;
7320 - /* For extended extraction brackets (large number), we have to fish out the
7321 - number from a dummy opcode at the start. */
7323 - if (number > EXTRACT_BASIC_MAX) number = (ecode[4] << 8) | ecode[5];
7324 - offset = number << 1;
7327 - printf("start bracket %d subject=", number);
7328 - pchars(eptr, 16, TRUE, md);
7332 - if (offset < md->offset_max)
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];
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;
7343 - if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
7345 - ecode += (ecode[1] << 8) + ecode[2];
7347 - while (*ecode == OP_ALT);
7349 - DPRINTF(("bracket %d failed\n", number));
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;
7358 - /* Insufficient room for saving captured contents */
7363 - /* Other types of node can be handled by a switch */
7367 - case OP_BRA: /* Non-capturing bracket: optimized */
7368 - DPRINTF(("start bracket 0\n"));
7371 - if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
7373 - ecode += (ecode[1] << 8) + ecode[2];
7375 - while (*ecode == OP_ALT);
7376 - DPRINTF(("bracket 0 failed\n"));
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. */
7385 - if (ecode[3] == OP_CREF) /* Condition is extraction test */
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);
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. */
7399 - if (match(eptr, ecode+3, offset_top, md, ims, NULL,
7400 - match_condassert | match_isgroup))
7402 - ecode += 3 + (ecode[4] << 8) + ecode[5];
7403 - while (*ecode == OP_ALT) ecode += (ecode[1] << 8) + ecode[2];
7405 - else ecode += (ecode[1] << 8) + ecode[2];
7406 - return match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup);
7408 - /* Control never reaches here */
7410 - /* Skip over conditional reference or large extraction number data if
7414 - case OP_BRANUMBER:
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. */
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 */
7427 - /* Change option settings */
7432 - DPRINTF(("ims set to %02lx\n", ims));
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. */
7442 - case OP_ASSERTBACK:
7445 - if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup)) break;
7446 - ecode += (ecode[1] << 8) + ecode[2];
7448 - while (*ecode == OP_ALT);
7449 - if (*ecode == OP_KET) return FALSE;
7451 - /* If checking an assertion for a condition, return TRUE. */
7453 - if ((flags & match_condassert) != 0) return TRUE;
7455 - /* Continue from after the assertion, updating the offsets high water
7456 - mark, since extracts may have been taken during the assertion. */
7458 - do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
7460 - offset_top = md->end_offset_top;
7463 - /* Negative assertion: all branches must fail to match */
7465 - case OP_ASSERT_NOT:
7466 - case OP_ASSERTBACK_NOT:
7469 - if (match(eptr, ecode+3, offset_top, md, ims, NULL, match_isgroup))
7471 - ecode += (ecode[1] << 8) + ecode[2];
7473 - while (*ecode == OP_ALT);
7475 - if ((flags & match_condassert) != 0) return TRUE;
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. */
7486 -#ifdef SUPPORT_UTF8
7487 - c = (ecode[1] << 8) + ecode[2];
7488 - for (i = 0; i < c; i++)
7494 - eptr -= (ecode[1] << 8) + ecode[2];
7497 - if (eptr < md->start_subject) return FALSE;
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
7517 - int stacksave[15];
7519 - c = md->offset_max;
7521 - if (c < 16) save = stacksave; else
7523 - save = (int *)(pcre_malloc)((c+1) * sizeof(int));
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,
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;
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. */
7544 - offset_top = md->end_offset_top;
7545 - eptr = md->end_match_ptr;
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
7559 - const uschar *prev = ecode;
7560 - const uschar *saved_eptr = eptr;
7564 - if (match(eptr, ecode+3, offset_top, md, ims, eptrb, match_isgroup))
7566 - ecode += (ecode[1] << 8) + ecode[2];
7568 - while (*ecode == OP_ALT);
7570 - /* If hit the end of the group (which could be repeated), fail */
7572 - if (*ecode != OP_ONCE && *ecode != OP_ALT) return FALSE;
7574 - /* Continue as from after the assertion, updating the offsets high water
7575 - mark, since extracts may have been taken. */
7577 - do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
7579 - offset_top = md->end_offset_top;
7580 - eptr = md->end_match_ptr;
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. */
7588 - if (*ecode == OP_KET || eptr == saved_eptr)
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
7599 - if (ecode[3] == OP_OPT)
7601 - ims = (ims & ~PCRE_IMS) | ecode[4];
7602 - DPRINTF(("ims set to %02lx at group repeat\n", ims));
7605 - if (*ecode == OP_KETRMIN)
7607 - if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
7608 - match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
7611 - else /* OP_KETRMAX */
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;
7619 - /* An alternation is the end of a branch; scan along to find the end of the
7620 - bracketed group and go to there. */
7623 - do ecode += (ecode[1] << 8) + ecode[2]; while (*ecode == OP_ALT);
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. */
7634 - const uschar *next = ecode+1;
7635 - if (match(eptr, next, offset_top, md, ims, eptrb, match_isgroup))
7637 - do next += (next[1] << 8) + next[2]; while (*next == OP_ALT);
7642 - case OP_BRAMINZERO:
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))
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. */
7661 - const uschar *prev = ecode - (ecode[1] << 8) - ecode[2];
7662 - const uschar *saved_eptr = eptrb->saved_eptr;
7664 - eptrb = eptrb->prev; /* Back up the stack of bracket start pointers */
7666 - if (*prev == OP_ASSERT || *prev == OP_ASSERT_NOT ||
7667 - *prev == OP_ASSERTBACK || *prev == OP_ASSERTBACK_NOT ||
7670 - md->end_match_ptr = eptr; /* For ONCE */
7671 - md->end_offset_top = offset_top;
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. */
7679 - if (*prev != OP_COND)
7682 - int number = *prev - OP_BRA;
7684 - /* For extended extraction brackets (large number), we have to fish out
7685 - the number from a dummy opcode at the start. */
7687 - if (number > EXTRACT_BASIC_MAX) number = (prev[4] << 8) | prev[5];
7688 - offset = number << 1;
7691 - printf("end bracket %d", number);
7697 - if (offset >= md->offset_max) md->offset_overflow = TRUE; else
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;
7707 - /* Reset the value of the ims flags, in case they got changed during
7710 - ims = original_ims;
7711 - DPRINTF(("ims reset to %02lx\n", ims));
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. */
7719 - if (*ecode == OP_KET || eptr == saved_eptr)
7725 - /* The repeating kets try the rest of the pattern or restart from the
7726 - preceding bracket, in the appropriate order. */
7728 - if (*ecode == OP_KETRMIN)
7730 - if (match(eptr, ecode+3, offset_top, md, ims, eptrb, 0) ||
7731 - match(eptr, prev, offset_top, md, ims, eptrb, match_isgroup))
7734 - else /* OP_KETRMAX */
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;
7742 - /* Start of subject unless notbol, or after internal newline if multiline */
7745 - if (md->notbol && eptr == md->start_subject) return FALSE;
7746 - if ((ims & PCRE_MULTILINE) != 0)
7748 - if (eptr != md->start_subject && eptr[-1] != NEWLINE) return FALSE;
7752 - /* ... else fall through */
7754 - /* Start of subject assertion */
7757 - if (eptr != md->start_subject) return FALSE;
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. */
7765 - if ((ims & PCRE_MULTILINE) != 0)
7767 - if (eptr < md->end_subject) { if (*eptr != NEWLINE) return FALSE; }
7768 - else { if (md->noteol) return FALSE; }
7774 - if (md->noteol) return FALSE;
7777 - if (eptr < md->end_subject - 1 ||
7778 - (eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE;
7784 - /* ... else fall through */
7786 - /* End of subject assertion (\z) */
7789 - if (eptr < md->end_subject) return FALSE;
7793 - /* End of subject or ending \n assertion (\Z) */
7796 - if (eptr < md->end_subject - 1 ||
7797 - (eptr == md->end_subject - 1 && *eptr != NEWLINE)) return FALSE;
7801 - /* Word boundary assertions */
7803 - case OP_NOT_WORD_BOUNDARY:
7804 - case OP_WORD_BOUNDARY:
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)
7816 - /* Match a single character type; inline for speed */
7819 - if ((ims & PCRE_DOTALL) == 0 && eptr < md->end_subject && *eptr == NEWLINE)
7821 - if (eptr++ >= md->end_subject) return FALSE;
7822 -#ifdef SUPPORT_UTF8
7824 - while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
7829 - case OP_NOT_DIGIT:
7830 - if (eptr >= md->end_subject ||
7831 - (md->ctypes[*eptr++] & ctype_digit) != 0)
7837 - if (eptr >= md->end_subject ||
7838 - (md->ctypes[*eptr++] & ctype_digit) == 0)
7843 - case OP_NOT_WHITESPACE:
7844 - if (eptr >= md->end_subject ||
7845 - (md->ctypes[*eptr++] & ctype_space) != 0)
7850 - case OP_WHITESPACE:
7851 - if (eptr >= md->end_subject ||
7852 - (md->ctypes[*eptr++] & ctype_space) == 0)
7857 - case OP_NOT_WORDCHAR:
7858 - if (eptr >= md->end_subject ||
7859 - (md->ctypes[*eptr++] & ctype_word) != 0)
7865 - if (eptr >= md->end_subject ||
7866 - (md->ctypes[*eptr++] & ctype_word) == 0)
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
7882 - int offset = (ecode[1] << 9) | (ecode[2] << 1); /* Doubled ref number */
7883 - ecode += 3; /* Advance past item */
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
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];
7894 - /* Set up for repetition, or handle the non-repeated case */
7899 - case OP_CRMINSTAR:
7901 - case OP_CRMINPLUS:
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;
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;
7920 - default: /* No repeat follows */
7921 - if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
7923 - continue; /* With the main loop */
7926 - /* If the length of the reference is zero, just continue with the
7929 - if (length == 0) continue;
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. */
7935 - for (i = 1; i <= min; i++)
7937 - if (!match_ref(offset, eptr, length, md, ims)) return FALSE;
7941 - /* If min = max, continue at the same level without recursion.
7942 - They are not both allowed to be zero. */
7944 - if (min == max) continue;
7946 - /* If minimizing, keep trying and advancing the pointer */
7950 - for (i = min;; i++)
7952 - if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
7954 - if (i >= max || !match_ref(offset, eptr, length, md, ims))
7958 - /* Control never gets here */
7961 - /* If maximizing, find the longest string and work backwards */
7965 - const uschar *pp = eptr;
7966 - for (i = min; i < max; i++)
7968 - if (!match_ref(offset, eptr, length, md, ims)) break;
7971 - while (eptr >= pp)
7973 - if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
7980 - /* Control never gets here */
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. */
7990 - const uschar *data = ecode + 1; /* Save for matching */
7991 - ecode += 33; /* Advance past the item */
7996 - case OP_CRMINSTAR:
7998 - case OP_CRMINPLUS:
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;
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;
8017 - default: /* No repeat follows */
8022 - /* First, ensure the minimum number of matches are present. */
8024 - for (i = 1; i <= min; i++)
8026 - if (eptr >= md->end_subject) return FALSE;
8027 - GETCHARINC(c, eptr) /* Get character; increment eptr */
8029 -#ifdef SUPPORT_UTF8
8030 - /* We do not yet support class members > 255 */
8031 - if (c > 255) return FALSE;
8034 - if ((data[c/8] & (1 << (c&7))) != 0) continue;
8038 - /* If max == min we can continue with the main loop without the
8039 - need to recurse. */
8041 - if (min == max) continue;
8043 - /* If minimizing, keep testing the rest of the expression and advancing
8044 - the pointer while it matches the class. */
8048 - for (i = min;; i++)
8050 - if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
8052 - if (i >= max || eptr >= md->end_subject) return FALSE;
8053 - GETCHARINC(c, eptr) /* Get character; increment eptr */
8055 -#ifdef SUPPORT_UTF8
8056 - /* We do not yet support class members > 255 */
8057 - if (c > 255) return FALSE;
8059 - if ((data[c/8] & (1 << (c&7))) != 0) continue;
8062 - /* Control never gets here */
8065 - /* If maximizing, find the longest possible run, then work backwards. */
8069 - const uschar *pp = eptr;
8071 - for (i = min; i < max; i++)
8073 - if (eptr >= md->end_subject) break;
8074 - GETCHARLEN(c, eptr, len) /* Get character, set length if UTF-8 */
8076 -#ifdef SUPPORT_UTF8
8077 - /* We do not yet support class members > 255 */
8078 - if (c > 255) break;
8080 - if ((data[c/8] & (1 << (c&7))) == 0) break;
8084 - while (eptr >= pp)
8086 - if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
8089 -#ifdef SUPPORT_UTF8
8096 - /* Control never gets here */
8098 - /* Match a run of characters */
8102 - register int length = ecode[1];
8105 -#ifdef DEBUG /* Sigh. Some compilers never learn. */
8106 - if (eptr >= md->end_subject)
8107 - printf("matching subject <null> against pattern ");
8110 - printf("matching subject ");
8111 - pchars(eptr, length, TRUE, md);
8112 - printf(" against pattern ");
8114 - pchars(ecode, length, FALSE, md);
8118 - if (length > md->end_subject - eptr) return FALSE;
8119 - if ((ims & PCRE_CASELESS) != 0)
8121 - while (length-- > 0)
8122 - if (md->lcc[*ecode++] != md->lcc[*eptr++])
8127 - while (length-- > 0) if (*ecode++ != *eptr++) return FALSE;
8132 - /* Match a single character repeatedly; different opcodes share code. */
8135 - min = max = (ecode[1] << 8) + ecode[2];
8142 - max = (ecode[1] << 8) + ecode[2];
8143 - minimize = *ecode == OP_MINUPTO;
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;
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
8164 - if (min > md->end_subject - eptr) return FALSE;
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. */
8175 - DPRINTF(("matching %c{%d,%d} against subject %.*s\n", c, min, max,
8178 - if ((ims & PCRE_CASELESS) != 0)
8181 - for (i = 1; i <= min; i++)
8182 - if (c != md->lcc[*eptr++]) return FALSE;
8183 - if (min == max) continue;
8186 - for (i = min;; i++)
8188 - if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
8190 - if (i >= max || eptr >= md->end_subject ||
8191 - c != md->lcc[*eptr++])
8194 - /* Control never gets here */
8198 - const uschar *pp = eptr;
8199 - for (i = min; i < max; i++)
8201 - if (eptr >= md->end_subject || c != md->lcc[*eptr]) break;
8204 - while (eptr >= pp)
8205 - if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
8209 - /* Control never gets here */
8212 - /* Caseful comparisons */
8216 - for (i = 1; i <= min; i++) if (c != *eptr++) return FALSE;
8217 - if (min == max) continue;
8220 - for (i = min;; i++)
8222 - if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
8224 - if (i >= max || eptr >= md->end_subject || c != *eptr++) return FALSE;
8226 - /* Control never gets here */
8230 - const uschar *pp = eptr;
8231 - for (i = min; i < max; i++)
8233 - if (eptr >= md->end_subject || c != *eptr) break;
8236 - while (eptr >= pp)
8237 - if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
8242 - /* Control never gets here */
8244 - /* Match a negated single character */
8247 - if (eptr >= md->end_subject) return FALSE;
8249 - if ((ims & PCRE_CASELESS) != 0)
8251 - if (md->lcc[*ecode++] == md->lcc[*eptr++]) return FALSE;
8255 - if (*ecode++ == *eptr++) return FALSE;
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... */
8266 - min = max = (ecode[1] << 8) + ecode[2];
8268 - goto REPEATNOTCHAR;
8271 - case OP_NOTMINUPTO:
8273 - max = (ecode[1] << 8) + ecode[2];
8274 - minimize = *ecode == OP_NOTMINUPTO;
8276 - goto REPEATNOTCHAR;
8279 - case OP_NOTMINSTAR:
8281 - case OP_NOTMINPLUS:
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;
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
8295 - if (min > md->end_subject - eptr) return FALSE;
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. */
8306 - DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", c, min, max,
8309 - if ((ims & PCRE_CASELESS) != 0)
8312 - for (i = 1; i <= min; i++)
8313 - if (c == md->lcc[*eptr++]) return FALSE;
8314 - if (min == max) continue;
8317 - for (i = min;; i++)
8319 - if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
8321 - if (i >= max || eptr >= md->end_subject ||
8322 - c == md->lcc[*eptr++])
8325 - /* Control never gets here */
8329 - const uschar *pp = eptr;
8330 - for (i = min; i < max; i++)
8332 - if (eptr >= md->end_subject || c == md->lcc[*eptr]) break;
8335 - while (eptr >= pp)
8336 - if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
8340 - /* Control never gets here */
8343 - /* Caseful comparisons */
8347 - for (i = 1; i <= min; i++) if (c == *eptr++) return FALSE;
8348 - if (min == max) continue;
8351 - for (i = min;; i++)
8353 - if (match(eptr, ecode, offset_top, md, ims, eptrb, 0))
8355 - if (i >= max || eptr >= md->end_subject || c == *eptr++) return FALSE;
8357 - /* Control never gets here */
8361 - const uschar *pp = eptr;
8362 - for (i = min; i < max; i++)
8364 - if (eptr >= md->end_subject || c == *eptr) break;
8367 - while (eptr >= pp)
8368 - if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
8373 - /* Control never gets here */
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. */
8379 - case OP_TYPEEXACT:
8380 - min = max = (ecode[1] << 8) + ecode[2];
8386 - case OP_TYPEMINUPTO:
8388 - max = (ecode[1] << 8) + ecode[2];
8389 - minimize = *ecode == OP_TYPEMINUPTO;
8394 - case OP_TYPEMINSTAR:
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;
8405 - /* Common code for all repeated single character type matches */
8408 - ctype = *ecode++; /* Code for the character type */
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. */
8417 - if (min > md->end_subject - eptr) return FALSE;
8418 - if (min > 0) switch(ctype)
8421 -#ifdef SUPPORT_UTF8
8424 - for (i = 1; i <= min; i++)
8426 - if (eptr >= md->end_subject ||
8427 - (*eptr++ == NEWLINE && (ims & PCRE_DOTALL) == 0))
8429 - while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
8434 - /* Non-UTF8 can be faster */
8435 - if ((ims & PCRE_DOTALL) == 0)
8436 - { for (i = 1; i <= min; i++) if (*eptr++ == NEWLINE) return FALSE; }
8440 - case OP_NOT_DIGIT:
8441 - for (i = 1; i <= min; i++)
8442 - if ((md->ctypes[*eptr++] & ctype_digit) != 0) return FALSE;
8446 - for (i = 1; i <= min; i++)
8447 - if ((md->ctypes[*eptr++] & ctype_digit) == 0) return FALSE;
8450 - case OP_NOT_WHITESPACE:
8451 - for (i = 1; i <= min; i++)
8452 - if ((md->ctypes[*eptr++] & ctype_space) != 0) return FALSE;
8455 - case OP_WHITESPACE:
8456 - for (i = 1; i <= min; i++)
8457 - if ((md->ctypes[*eptr++] & ctype_space) == 0) return FALSE;
8460 - case OP_NOT_WORDCHAR:
8461 - for (i = 1; i <= min; i++)
8462 - if ((md->ctypes[*eptr++] & ctype_word) != 0)
8467 - for (i = 1; i <= min; i++)
8468 - if ((md->ctypes[*eptr++] & ctype_word) == 0)
8473 - /* If min = max, continue at the same level without recursing */
8475 - if (min == max) continue;
8477 - /* If minimizing, we have to test the rest of the pattern before each
8478 - subsequent match. */
8482 - for (i = min;; i++)
8484 - if (match(eptr, ecode, offset_top, md, ims, eptrb, 0)) return TRUE;
8485 - if (i >= max || eptr >= md->end_subject) return FALSE;
8491 - if ((ims & PCRE_DOTALL) == 0 && c == NEWLINE) return FALSE;
8492 -#ifdef SUPPORT_UTF8
8494 - while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
8498 - case OP_NOT_DIGIT:
8499 - if ((md->ctypes[c] & ctype_digit) != 0) return FALSE;
8503 - if ((md->ctypes[c] & ctype_digit) == 0) return FALSE;
8506 - case OP_NOT_WHITESPACE:
8507 - if ((md->ctypes[c] & ctype_space) != 0) return FALSE;
8510 - case OP_WHITESPACE:
8511 - if ((md->ctypes[c] & ctype_space) == 0) return FALSE;
8514 - case OP_NOT_WORDCHAR:
8515 - if ((md->ctypes[c] & ctype_word) != 0) return FALSE;
8519 - if ((md->ctypes[c] & ctype_word) == 0) return FALSE;
8523 - /* Control never gets here */
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). */
8531 - const uschar *pp = eptr;
8536 - /* Special code is required for UTF8, but when the maximum is unlimited
8537 - we don't need it. */
8539 -#ifdef SUPPORT_UTF8
8540 - if (md->utf8 && max < INT_MAX)
8542 - if ((ims & PCRE_DOTALL) == 0)
8544 - for (i = min; i < max; i++)
8546 - if (eptr >= md->end_subject || *eptr++ == NEWLINE) break;
8547 - while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
8552 - for (i = min; i < max; i++)
8555 - while (eptr < md->end_subject && (*eptr & 0xc0) == 0x80) eptr++;
8561 - /* Non-UTF8 can be faster */
8562 - if ((ims & PCRE_DOTALL) == 0)
8564 - for (i = min; i < max; i++)
8566 - if (eptr >= md->end_subject || *eptr == NEWLINE) break;
8573 - if (c > md->end_subject - eptr) c = md->end_subject - eptr;
8578 - case OP_NOT_DIGIT:
8579 - for (i = min; i < max; i++)
8581 - if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) != 0)
8588 - for (i = min; i < max; i++)
8590 - if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_digit) == 0)
8596 - case OP_NOT_WHITESPACE:
8597 - for (i = min; i < max; i++)
8599 - if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) != 0)
8605 - case OP_WHITESPACE:
8606 - for (i = min; i < max; i++)
8608 - if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_space) == 0)
8614 - case OP_NOT_WORDCHAR:
8615 - for (i = min; i < max; i++)
8617 - if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) != 0)
8624 - for (i = min; i < max; i++)
8626 - if (eptr >= md->end_subject || (md->ctypes[*eptr] & ctype_word) == 0)
8633 - while (eptr >= pp)
8635 - if (match(eptr--, ecode, offset_top, md, ims, eptrb, 0))
8637 -#ifdef SUPPORT_UTF8
8639 - while (eptr > pp && (*eptr & 0xc0) == 0x80) eptr--;
8644 - /* Control never gets here */
8646 - /* There's been some horrible disaster. */
8649 - DPRINTF(("Unknown opcode %d\n", *ecode));
8650 - md->errorcode = PCRE_ERROR_UNKNOWN_NODE;
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
8658 - } /* End of main loop */
8659 -/* Control never reaches here */
8665 -/*************************************************
8666 -* Execute a Regular Expression *
8667 -*************************************************/
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.
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
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
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,
8694 -int resetcount, ocount;
8695 -int first_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;
8710 -if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION;
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;
8716 -anchored = ((re->options | options) & PCRE_ANCHORED) != 0;
8717 -startline = (re->options & PCRE_STARTLINE) != 0;
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;
8724 -match_block.endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
8725 -match_block.utf8 = (re->options & PCRE_UTF8) != 0;
8727 -match_block.notbol = (options & PCRE_NOTBOL) != 0;
8728 -match_block.noteol = (options & PCRE_NOTEOL) != 0;
8729 -match_block.notempty = (options & PCRE_NOTEMPTY) != 0;
8731 -match_block.errorcode = PCRE_ERROR_NOMATCH; /* Default error */
8733 -match_block.lcc = re->tables + lcc_offset;
8734 -match_block.ctypes = re->tables + ctypes_offset;
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. */
8740 -ims = re->options & (PCRE_CASELESS|PCRE_MULTILINE|PCRE_DOTALL);
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
8747 -ocount = offsetcount - (offsetcount % 3);
8749 -if (re->top_backref > 0 && re->top_backref >= ocount/3)
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"));
8757 -else match_block.offset_vector = offsets;
8759 -match_block.offset_end = ocount;
8760 -match_block.offset_max = (2*ocount)/3;
8761 -match_block.offset_overflow = FALSE;
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
8767 -resetcount = 2 + re->top_bracket * 2;
8768 -if (resetcount > offsetcount) resetcount = ocount;
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. */
8774 -if (match_block.offset_vector != NULL)
8776 - register int *iptr = match_block.offset_vector + ocount;
8777 - register int *iend = iptr - resetcount/2 + 1;
8778 - while (--iptr >= iend) *iptr = -1;
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. */
8789 - if ((re->options & PCRE_FIRSTSET) != 0)
8791 - first_char = re->first_char;
8792 - if ((ims & PCRE_CASELESS) != 0) first_char = match_block.lcc[first_char];
8795 - if (!startline && extra != NULL &&
8796 - (extra->options & PCRE_STUDY_MAPPED) != 0)
8797 - start_bits = extra->start_bits;
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. */
8808 -if ((re->options & PCRE_REQCHSET) != 0)
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;
8815 -/* Loop for handling unanchored repeated matching attempts; for anchored regexs
8816 -the loop runs just once. */
8821 - register int *iptr = match_block.offset_vector;
8822 - register int *iend = iptr + resetcount;
8824 - /* Reset the maximum number of extractions we might see. */
8826 - while (iptr < iend) *iptr++ = -1;
8828 - /* Advance to a unique first char if possible */
8830 - if (first_char >= 0)
8832 - if ((ims & PCRE_CASELESS) != 0)
8833 - while (start_match < end_subject &&
8834 - match_block.lcc[*start_match] != first_char)
8837 - while (start_match < end_subject && *start_match != first_char)
8841 - /* Or to just after \n for a multiline match if possible */
8843 - else if (startline)
8845 - if (start_match > match_block.start_subject + start_offset)
8847 - while (start_match < end_subject && start_match[-1] != NEWLINE)
8852 - /* Or to a non-unique first char after study */
8854 - else if (start_bits != NULL)
8856 - while (start_match < end_subject)
8858 - register int c = *start_match;
8859 - if ((start_bits[c/8] & (1 << (c&7))) == 0) start_match++; else break;
8863 -#ifdef DEBUG /* Sigh. Some compilers never learn. */
8864 - printf(">>>> Match against: ");
8865 - pchars(start_match, end_subject - start_match, TRUE, &match_block);
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. */
8880 - if (req_char >= 0)
8882 - register const uschar *p = start_match + ((first_char >= 0)? 1 : 0);
8884 - /* We don't need to repeat the search if we haven't yet reached the
8885 - place we found it at last time. */
8887 - if (p > req_char_ptr)
8889 - /* Do a single test if no case difference is set up */
8891 - if (req_char == req_char2)
8893 - while (p < end_subject)
8895 - if (*p++ == req_char) { p--; break; }
8899 - /* Otherwise test for either case */
8903 - while (p < end_subject)
8905 - register int pp = *p++;
8906 - if (pp == req_char || pp == req_char2) { p--; break; }
8910 - /* If we can't find the required character, break the matching loop */
8912 - if (p >= end_subject) break;
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. */
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. */
8929 - match_block.start_match = start_match;
8930 - if (!match(start_match, re->code, 2, &match_block, ims, NULL, match_isgroup))
8933 - /* Copy the offset information from temporary store if necessary */
8935 - if (using_temporary_offsets)
8937 - if (offsetcount >= 4)
8939 - memcpy(offsets + 2, match_block.offset_vector + 2,
8940 - (offsetcount - 2) * sizeof(int));
8941 - DPRINTF(("Copied offsets from temporary memory\n"));
8943 - if (match_block.end_offset_top > offsetcount)
8944 - match_block.offset_overflow = TRUE;
8946 - DPRINTF(("Freeing temporary memory\n"));
8947 - (pcre_free)(match_block.offset_vector);
8950 - rc = match_block.offset_overflow? 0 : match_block.end_offset_top/2;
8952 - if (offsetcount < 2) rc = 0; else
8954 - offsets[0] = start_match - match_block.start_subject;
8955 - offsets[1] = match_block.end_match_ptr - match_block.start_subject;
8958 - DPRINTF((">>>> returning %d\n", rc));
8962 -/* This "while" is the end of the "do" above */
8964 -while (!anchored &&
8965 - match_block.errorcode == PCRE_ERROR_NOMATCH &&
8966 - start_match++ < end_subject);
8968 -if (using_temporary_offsets)
8970 - DPRINTF(("Freeing temporary memory\n"));
8971 - (pcre_free)(match_block.offset_vector);
8974 -DPRINTF((">>>> returning %d\n", match_block.errorcode));
8976 -return match_block.errorcode;
8979 -/* End of pcre.c */
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
8985 -/*************************************************
8986 -* Perl-Compatible Regular Expressions *
8987 -*************************************************/
8989 -/* Copyright (c) 1997-2001 University of Cambridge */
8994 -/* The file pcre.h is build by "configure". Do not edit it; instead
8995 -make changes to pcre.in. */
8997 -#define PCRE_MAJOR 3
8998 -#define PCRE_MINOR 9
8999 -#define PCRE_DATE 02-Jan-2002
9001 -/* Win32 uses DLL by default */
9005 -# define PCRE_DL_IMPORT
9007 -# define PCRE_DL_IMPORT __declspec(dllimport)
9010 -# define PCRE_DL_IMPORT
9013 -/* Have to include stdlib.h in order to ensure that size_t is defined;
9014 -it is needed here for malloc. */
9016 -#include <stdlib.h>
9018 -/* Allow for C++ users */
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
9039 -/* Exec-time and get-time error codes */
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)
9049 -/* Request types for pcre_fullinfo() */
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
9061 -struct real_pcre; /* declaration; the definition is private */
9062 -struct real_pcre_extra; /* declaration; the definition is private */
9064 -typedef struct real_pcre pcre;
9065 -typedef struct real_pcre_extra pcre_extra;
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
9071 -PCRE_DL_IMPORT extern void *(*pcre_malloc)(size_t);
9072 -PCRE_DL_IMPORT extern void (*pcre_free)(void *);
9074 -#undef PCRE_DL_IMPORT
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);
9097 -#endif /* End of pcre.h */
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
9106 PROVE=/usr/bin/prove
9109 +PARSER_BIN=apparmor_parser
9110 +PARSER=$(PARSER_DIR)/$(PARSER_BIN)
9119 -tests: ../apparmor_parser
9120 +.PHONY: tests error_output parser_sanity
9121 +tests: error_output parser_sanity
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"
9135 +parser_sanity: $(PARSER)
9136 $(Q)${PROVE} ${PROVE_ARG} ${TESTS}
9138 -../apparmor_parser:
9139 - make -C .. apparmor_parser
9141 + make -C $(PARSER_DIR) $(PARSER_BIN)
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
9149 Otherwise, the profile is passed on as-is to the subdomain parser.
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
9160 + #include <includes/base>
9161 + #include <includes/busted>
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
9170 +# ------------------------------------------------------------------
9172 +# Copyright (C) 2002-2005 Novell/SUSE
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.
9178 +# ------------------------------------------------------------------
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.)
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.
9194 + /usr/share/locale/** r,
9195 + /usr/share/zoneinfo/** r,
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,
9204 + # used by glibc when binding to ephemeral ports
9205 + /etc/bindresvport.blacklist r,
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.
9213 + /lib64/ld-*.so px,
9214 + /opt/*-linux-uclibc/lib/ld-uClibc*so* px,
9216 + # we might as well allow everything to use common libraries
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,
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,
9235 + # /dev/null is pretty harmless and frequently used
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,
9246 + # glibc's sysconf(3) routine to determine free memory, etc
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
9256 +# ------------------------------------------------------------------
9258 +# Copyright (C) 2002-2005 Novell/SUSE
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.
9264 +# ------------------------------------------------------------------
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.)
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.
9280 + /usr/share/locale/** r,
9281 + /usr/share/zoneinfo/** r,
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,
9290 + # used by glibc when binding to ephemeral ports
9291 + /etc/bindresvport.blacklist r,
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.
9299 + /lib64/ld-*.so px,
9300 + /opt/*-linux-uclibc/lib/ld-uClibc*so* px,
9302 + # we might as well allow everything to use common libraries
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,
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,
9321 + #include <does-not-exist>
9323 + # /dev/null is pretty harmless and frequently used
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,
9334 + # glibc's sysconf(3) routine to determine free memory, etc
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
9346 +/does/not/exist { # 4
9347 + /lib/lib*.so rm, # 5
9348 + /fail abcdefgh, # 6
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
9359 + #include <includes/base>
9360 + #include <includes/base>
9361 + #include <includes/base>
9362 + #include <includes/base>
9366 + #include <failure>
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
9375 + #include <includes/base>
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
9387 + #include <includes/base>
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
9394 # some applications will display license information
9395 /usr/share/common-licenses/** r,
9398 + @{PROC}/filesystems r,
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
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
9409 # ------------------------------------------------------------------
9411 -# Copyright (C) 2009 Canonical Ltd.
9412 +# Copyright (C) 2009-2010 Canonical Ltd.
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
9418 # ------------------------------------------------------------------
9421 + # System socket. Be careful when including this abstraction.
9422 /var/run/dbus/system_bus_socket w,
9425 - /var/lib/dbus/machine-id r,
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
9431 +# vim:syntax=apparmor
9433 +# ------------------------------------------------------------------
9435 +# Copyright (C) 2010 Canonical Ltd.
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.
9441 +# ------------------------------------------------------------------
9443 + /usr/bin/dbus-launch Pix,
9444 + /var/lib/dbus/machine-id r,
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
9451 /usr/lib/xorg/modules/fonts/**.so* mr,
9453 + /usr/share/fonts/ r,
9454 /usr/share/fonts/** r,
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
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,
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
9474 # ------------------------------------------------------------------
9476 # Copyright (C) 2002-2009 Novell/SUSE
9477 -# Copyright (C) 2009 Canonical Ltd.
9478 +# Copyright (C) 2009-2010 Canonical Ltd.
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
9484 /usr/lib{,32,64}/pango/** mr,
9485 /usr/lib{,32,64}/gtk-*/** mr,
9486 + /usr/lib{,32,64}/gdk-pixbuf-*/** mr,
9488 # per-user gtk configuration
9489 @{HOME}/.gnome/Gnome r,
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
9496 network inet6 dgram,
9498 + # interface details
9499 + @{PROC}/*/net/route r,
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
9505 # ------------------------------------------------------------------
9507 # Copyright (C) 2002-2006 Novell/SUSE
9508 -# Copyright (C) 2009 Canonical, Ltd.
9509 +# Copyright (C) 2009-2010 Canonical Ltd.
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
9514 # ------------------------------------------------------------------
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,
9523 /usr/X11R6/lib{,32,64}/lib*.so* mr,
9525 - /usr/lib{64,}/php5/{libexec,extensions}/*.so mr,
9526 + /usr/lib{64,}/php5/*/*.so mr,
9528 # php5 session mmap socket
9529 /var/lib/php5/session_mm_* rwlk,
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
9536 # ------------------------------------------------------------------
9538 -# Copyright (C) 2009 Canonical Ltd.
9539 +# Copyright (C) 2009-2010 Canonical Ltd.
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
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,
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
9559 /usr/lib/thunderbird/thunderbird Ux,
9561 + /usr/lib/thunderbird-3*/thunderbird Ux,
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
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,
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
9580 # ------------------------------------------------------------------
9582 # Copyright (C) 2002-2009 Novell/SUSE
9583 -# Copyright (C) 2009 Canonical Ltd.
9584 +# Copyright (C) 2009-2010 Canonical Ltd.
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
9589 # ------------------------------------------------------------------
9591 # per-user tmp directories
9592 - @{HOME}/tmp/** rwkl,
9594 + owner @{HOME}/tmp/** rwkl,
9595 + owner @{HOME}/tmp/ rw,
9597 # global tmp directories
9602 + owner /var/tmp/** rwkl,
9603 + owner /var/tmp/ rw,
9604 + owner /tmp/** rwkl,
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
9627 @@ -158,27 +160,39 @@
9629 @if [ `whoami` = "root" ] ;\
9632 for i in $(TESTS) ;\
9635 echo "running $$i" ;\
9637 + if [ $$? -ne 0 ] ; then \
9643 echo "must be root to run tests" ;\
9648 @if [ `whoami` = "root" ] ;\
9651 for i in $(TESTS) $(RISKY_TESTS) ;\
9654 echo "running $$i" ;\
9656 + if [ $$? -ne 0 ] ; then \
9662 echo "must be root to run tests" ;\
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
9675 -Type "make tests" at the shell prompt, this will make the subprograms
9677 +Type "sudo make tests" at the shell prompt, this will make the
9678 +subprograms and run the tests.
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).
9683 (There is also a 'make alltests', which adds a test for bug that, when
9684 triggered, would cause the kernel to crash.)
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
9692 running <testname> for each test.
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
9699 There are three typical failure scenarios:
9700 - Test failed when it was expected to pass
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.
9709 (Note: the tmp directory specified in uservars.inc will have an added
9711 directory will contain the files for the failed subtest.
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
9720 <requirement placed on the shell script author by prologue.inc>
9723 - <prologie.inc must be included before running any tests>
9724 + <prologue.inc must be included before running any tests>
9727 <variable definitions used by this script?
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
9736 <run this test (exec) passing /bin/true as argv[1]>
9737 @@ -183,16 +186,11 @@
9739 <Thats it. Exit status $rc is automatically returned by epilogue.inc>
9741 -Additional documentation
9742 -========================
9744 -See the file 'subdomain_test.txt'
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
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
9761 - Error: open passed. Test 'STRACE OPEN (x confinement)'
9762 - was expected to 'fail'
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.)
9768 - Error: open passed. Test 'OPEN W (create)' was expected to 'fail'
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
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
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
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
9784 # 2. ATTEMPT TO CHANGEHAT OUT WITH BAD TOKEN
9785 settest changehat_fail
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
9795 * Copyright (C) 2002-2005 Novell/SUSE
9796 + * Copyright (C) 2010 Canonical, Ltd
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
9805 +int main(int argc, char *argv[])
9807 printf("This will cause a sigsegv\n");
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
9817 # Copyright (C) 2002-2005 Novell/SUSE
9818 +# Copyright (C) 2010 Canonical, Ltd
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
9824 #=DESCRIPTION coredump test
9833 -_corefilelist=`echo core.*`
9834 -if [ "$_corefilelist" = "core.*" ]
9841 -if [ "$1" = "yes" -a "$_corefile" = "no" ]
9843 - echo "Error: corefile expected but not present - $2"
9844 -elif [ "$1" = "no" -a "$_corefile" = "yes" ]
9846 - echo "Error: corefile present when not expected -- $2"
9849 -unset _corefile _corefilelist
9851 + # global _testdesc _pfmode _known outfile
9852 + if [ ${1:0:1} == "x" ] ; then
9853 + requirement=${1#x}
9854 + _known=" (known problem)"
9860 + _corefilelist=`echo core.*`
9861 + if [ ! -f core ] && [ "$_corefilelist" = "core.*" ]
9868 + if [ "$requirement" = "yes" -a "$_corefile" = "no" ] ; then
9869 + if [ -n $_known ] ; then
9872 + echo "Error: corefile expected but not present - $2"
9873 + if [ -z $_known ] ; then
9877 + elif [ "$requirement" = "no" -a "$_corefile" = "yes" ] ; then
9878 + if [ -n "$_known" ] ; then
9881 + echo "Error: corefile present when not expected -- $2"
9882 + if [ -z "$_known" ] ; then
9888 + unset _corefile _corefilelist
9898 +checkcorefile no "COREDUMP (starting with clean slate)"
9900 # PASS TEST, no confinement
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)"
9906 # PASS TEST, with r confinement
9907 -genprofile $test:$coreperm
9910 +genprofile image=$test:$coreperm
9913 echo "*** A 'Segmentation Fault' message from bash is expected for the following test"
9915 checkcorefile yes "COREDUMP ($coreperm confinement)"
9917 # FAIL TEST, with x confinement
9918 -genprofile $test:$nocoreperm
9921 +genprofile image=$test:$nocoreperm
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)"
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
9934 # Gawd, I hate writing perl. It shows, too.
9936 -my $__VERSION__='$Id$';
9937 +my $__VERSION__=$0;
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
9950 # Test infrastructure support.
9952 +# Copyright 2010 Canonical, Ltd.
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
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.
9964 while [ -h ${link} ]
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})
9973 # I'm sure there's a more perlish way to do this
9974 target=$( perl -e "printf (\"%s\n\", readlink(\"${link}\"));")
9977 echo "Error: ${testname} passed. Test '${_testdesc}' was expected to '${_pfmode}'"
9980 elif [ "$_pfmode" == "pass" -a -n "${_known}" ]
9982 echo "Alert: ${testname} passed. Test '${_testdesc}' was marked as expected pass but known problem (xpass)"
9985 echo "Error: ${testname} failed. Test '${_testdesc}' was expected to '${_pfmode}'. Reason for failure '${ret}'"
9988 elif [ "$_pfmode" == "fail" -a -n "${_known}" ]
9990 echo "Alert: ${testname} failed. Test '${_testdesc}' was marked as expected fail but known problem (xfail)."
9991 @@ -272,16 +281,23 @@
9993 echo "Error: ${testname} failed. Test '${_testdesc}' was expected to terminate with signal ${expectedsig}${_known}. Instead it terminated with signal ${killedsig}"
9998 *) echo "Error: ${testname} failed. Test '${_testdesc}' was expected to '${_pfmode}'${_known}. Reason for failure 'killed by signal ${killedsig}'"
10009 + if [ -n "$VERBOSE" ]; then
10010 + echo "ok: ${_testdesc}"
10015 @@ -399,22 +415,12 @@
10016 # it is most often used after --, in fact it is basically
10017 # mandatory after --
10019 - profile=*) imagename=`echo $1 | sed 's/^profile=[rix]*//'`
10020 - perm=`echo $1 | sed -n 's/^profile=\([rix]*\).*$/\1/p'`
10021 - if [ -n "$perm" ]
10029 - image=*) imagename=`echo $1 | sed 's/^image=[rix]*//'`
10030 + image=*) imagename=`echo $1 | sed 's/^image=\([^:]*\).*$/\1/'`
10031 if [ ! -x "$imagename" ]
10033 fatalerror "invalid imagename specified in input '$1'"
10035 - perm=`echo $1 | sed -n 's/^image=\([rix]*\).*$/\1/p'`
10036 + perm=`echo $1 | sed -n 's/^image=[^:]*:\(.*\)$/\1/p'`
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
10046 genprofile $file:$okperm
10048 -runtestbg "PWRITE with w" pass $file
10049 +runtestbg "PREAD/PWRITE with rw" pass $file
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
10058 swap_file=$tmpdir/swapfile
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
10064 # TEST 1. Make sure can enable and disable swap unconfined
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
10075 # Copyright (C) 2002-2005 Novell/SUSE
10076 +# Copyright (C) 2010 Canonical, Ltd.
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
10087 -sh syscall_sysctl.sh
10088 +bash syscall_sysctl.sh
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
10098 int main(int argc, char *argv[])
10104 fprintf(stderr, "usage: %s b|c|f|s|r file\n",
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
10121 * Copyright (C) 2002-2005 Novell/SUSE
10122 + * Copyright (C) 2010 Canonical, Ltd.
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 @@
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",
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)))
10142 +def get_random_regex()
10145 + return "{#{get_random_name(rand(8) + 2)},#{get_random_name(rand(8) + 2)},#{get_random_name(rand(8) + 2)}}"
10147 + return "[#{get_random_name(rand(5) + 1)}]"
10155 def get_random_path()
10157 - 0.upto(rand(20)) do
10158 - out = "#{out}/#{get_random_name(4)}"
10159 + 0.upto(rand(20) + 2) do
10161 + out = "#{out}/#{get_random_regex}"
10163 + out = "#{out}/#{get_random_name(rand(10) + 4)}"
10168 @@ -83,7 +100,10 @@
10180 @@ -95,6 +115,93 @@
10184 +class NetRule < Rule
10188 +class RlimitRule < Rule
10190 +#"cpu", # cpu rlimit not supported
10209 + @rlimit = RLIMIT_LIST[rand(RLIMIT_LIST.length)]
10211 + @limit = "infinity"
10212 + elsif @rlimit == "nice"
10213 + @limit = rand(40) - 20
10215 + @limit = rand(2 ** 31)
10220 + return " set rlimit #{@rlimit} <= #{@limit},"
10228 + "chroot_relative",
10229 + "namespace_relative",
10230 + "mediate_deleted",
10231 + "delegate_deleted",
10232 + "attach_disconnected",
10233 + "no_attach_disconnected",
10235 + "chroot_no_attach"
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"]
10251 + 0.upto(4 - Math.log(rand(32) + 1).to_int) do |x|
10252 + @flags << FLAG_LIST[rand(FLAG_LIST.length)]
10255 + FLAG_CONFLICTS.each do |c|
10256 + if @flags.include?(c[0]) and @flags.include?(c[1])
10257 + @flags.delete(c[rand(2)])
10266 + out = @flags.join(",")
10267 + return "flags=(#{out})"
10271 def prefix_to_s(name)
10274 @@ -112,16 +219,19 @@
10275 @rvalue = get_random_name()
10276 @name = "/does/not/exist/#{@rvalue}"
10278 + @flags = Flags.new()
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|
10287 - @rules << CapRule.new
10289 - @rules << FileRule.new
10291 + @rules << CapRule.new.to_s
10293 + @rules << RlimitRule.new.to_s
10295 + @rules << FileRule.new.to_s
10299 @@ -132,10 +242,10 @@
10300 out << "# profile for #{@name}"
10301 out << "# generated by #{__FILE__} #{$my_version}"
10303 - out << "#{@name} {"
10304 + out << "#{@name} #{@flags} {"
10305 out << " #include <abstractions/base>"
10307 - @rules.each { |r| out << r.to_s }
10308 + @rules.sort.each { |r| out << " #{r}" }
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
10318 # ----------------------------------------------------------------------
10319 # Copyright (c) 2006 Novell, Inc. All Rights Reserved.
10320 +# Copyright (c) 2010 Canonical, Ltd.
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 @@
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=/;
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 |
10347 @@ -6612,10 +6618,14 @@
10348 LibAppArmor::free_record($event);
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;
10356 + $rmask =~ s/c/w/g;
10357 + $rmask =~ s/d/w/g;
10360 + $dmask =~ s/c/w/g;
10361 + $dmask =~ s/d/w/g;
10364 if ($rmask && !validate_log_mode(hide_log_mode($rmask))) {
10365 fatal_error(sprintf(gettext('Log contains unknown mode %s.'),
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
10371 require Time::Local;
10372 require File::Basename;
10374 -use vars qw($opt_p $opt_s $opt_l $opt_h $opt_v $opt_d $opt_w);
10379 my $conf = "/etc/apparmor/notify.conf";
10381 $ENV{SHELL} = "/bin/sh";
10382 defined($ENV{IFS}) and $ENV{IFS} = ' \t\n';
10385 my $prog = File::Basename::basename($0);
10387 if ($prog !~ /^[a-zA-Z0-9_\-]+$/) {
10388 @@ -75,32 +73,66 @@
10392 -my $logfile = "/var/log/kern.log";
10393 --e "/var/run/auditd.pid" and $logfile = "/var/log/audit/audit.log";
10395 $> == $< or die "Cannot be suid\n";
10396 $) == $( or die "Cannot be sgid\n";
10399 +our $orig_euid = $>;
10401 -getopts('dhlpvs:w:');
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,
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";
10431 + -f $opt_f or die "'$opt_f' does not exist. Aborting\n";
10432 + $logfile = $opt_f;
10434 + -e "/var/run/auditd.pid" and $logfile = "/var/log/audit/audit.log";
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
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};
10450 + my $drop_to = $nobody_user;
10452 + $drop_to = $opt_u;
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'");
10461 $login = getlogin();
10462 @@ -111,7 +143,7 @@
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");
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";
10479 @@ -259,6 +290,26 @@
10483 +sub send_message {
10486 + my $pid = fork();
10487 + if ($pid == 0) { # child
10488 + # notify-send needs $< to be the unprivileged user
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);
10499 + waitpid($pid, 0);
10506 @@ -273,7 +324,7 @@
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: $!";
10514 die "Couldn't fork: $!" unless defined($pid);
10515 @@ -293,12 +344,24 @@
10517 my $footer = "For more information, please see:\n$url";
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);
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();
10532 while(my $msg = <LOGFILE>) {
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);
10541 @attrib = parse_message($msg);
10543 @@ -340,12 +403,9 @@
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);
10555 + _warn("'$notify_exe' exited with error '$rc'");
10559 @@ -356,7 +416,7 @@
10563 - my $m = "$logfile contains $count existing denied message";
10564 + my $m = "$logfile contains $count denied message";
10565 $count > 1 and $m .= "s";
10567 $m .= " in the last ";
10568 @@ -368,7 +428,7 @@
10572 - system "$notify_exe", "-i", "gtk-dialog-warning", "-u", "critical", "--", "AppArmor Message", "$m";
10573 + send_message($m);
10577 @@ -390,6 +450,9 @@
10585 while(my $msg = <LOGFILE>) {
10586 my @attrib = parse_message($msg, $_[0]);
10587 @@ -397,10 +460,31 @@
10589 my $m = format_message(@attrib);
10592 - $opt_v and print "$m\n";
10593 + my $date = $attrib[6];
10595 + if (exists($msg_hash{$m})) {
10597 + defined($date) and $last_date{$m} = scalar(localtime($date));
10599 + $msg_hash{$m} = 1;
10600 + push(@msg_list, $m);
10606 + foreach my $m (@msg_list) {
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}'";
10621 @@ -452,19 +536,63 @@
10624 USAGE: apparmor_notify [OPTIONS]
10626 Display AppArmor notifications or messages for DENIED entries.
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
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)
10649 +sub reopen_logfile {
10650 + # reopen the logfile, temporarily switching back to starting euid for
10651 + # file permissions.
10654 + my $old_euid = $>;
10655 + my $change_euid = 0;
10657 + _debug("raising privileges to '$orig_euid' in reopen_logfile()");
10658 + $change_euid = 1;
10660 + $> == $orig_euid or die "Could not raise privileges\n";
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";
10667 + if ($change_euid) {
10668 + _debug("dropping privileges to '$old_euid' in reopen_logfile()");
10670 + $> == $old_euid or die "Could not drop privileges\n";
10674 +sub get_logfile_size {
10677 + defined(($size = (stat($fn))[7])) or (sleep(10) and defined(($size = (stat($fn))[7])) or die "'$fn' disappeared. Aborting\n");
10681 +sub get_logfile_inode {
10684 + defined(($inode = (stat($fn))[1])) or (sleep(10) and defined(($inode = (stat($fn))[1])) or die "'$fn' disappeared. Aborting\n");
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 @@
10702 poll AppArmor logs and display desktop notifications. Can be used with '-s'
10703 option to display a summary on startup.
10706 +=item -f FILE, --file=FILE
10708 +search FILE for AppArmor messages
10710 +=item -l, --since-last
10712 show summary since last login.
10715 +=item -s NUM, --since-days=NUM
10717 show summary for last NUM of days.
10720 +=item -u USER, --user=USER
10722 +user to drop privileges to when running privileged. This has no effect when
10723 +running under sudo.
10725 +=item -w NUM, --wait=NUM
10727 +wait NUM seconds before displaying notifications (for use with -p)
10729 +=item -v, --verbose
10731 show messages with summaries.
10736 displays a short usage statement.