From 13bea70190a35217a25f42ade4d29272fbe74ffd Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Thu, 12 Nov 2015 12:24:15 +0000 Subject: [PATCH] libpcre: updated to 8.37 --- libpcre/.footprint | 119 +- libpcre/.md5sum | 5 +- libpcre/01-seven-security-patches.patch | 1250 ++++++++++++++++++++++ libpcre/Pkgfile | 15 +- libpcre/libpcre-8.37-CVE-2015-5073.patch | 72 ++ libpcre/libpcre-8.37-CVE-2015-XXXX.patch | 170 +++ 6 files changed, 1565 insertions(+), 66 deletions(-) create mode 100644 libpcre/01-seven-security-patches.patch create mode 100644 libpcre/libpcre-8.37-CVE-2015-5073.patch create mode 100644 libpcre/libpcre-8.37-CVE-2015-XXXX.patch diff --git a/libpcre/.footprint b/libpcre/.footprint index dc3ea5b..70497da 100644 --- a/libpcre/.footprint +++ b/libpcre/.footprint @@ -1,6 +1,6 @@ drwxr-xr-x root/root lib/ -lrwxrwxrwx root/root lib/libpcre.so.1 -> libpcre.so.1.2.3 --rwxr-xr-x root/root lib/libpcre.so.1.2.3 +lrwxrwxrwx root/root lib/libpcre.so.1 -> libpcre.so.1.2.5 +-rwxr-xr-x root/root lib/libpcre.so.1.2.5 drwxr-xr-x root/root usr/ drwxr-xr-x root/root usr/bin/ -rwxr-xr-x root/root usr/bin/pcre-config @@ -16,68 +16,69 @@ drwxr-xr-x root/root usr/include/ drwxr-xr-x root/root usr/lib/ -rw-r--r-- root/root usr/lib/libpcre.a -rwxr-xr-x root/root usr/lib/libpcre.la -lrwxrwxrwx root/root usr/lib/libpcre.so -> ../../lib/libpcre.so.1.2.3 +lrwxrwxrwx root/root usr/lib/libpcre.so -> ../../lib/libpcre.so.1.2.5 -rw-r--r-- root/root usr/lib/libpcrecpp.a -rwxr-xr-x root/root usr/lib/libpcrecpp.la -lrwxrwxrwx root/root usr/lib/libpcrecpp.so -> libpcrecpp.so.0.0.0 -lrwxrwxrwx root/root usr/lib/libpcrecpp.so.0 -> libpcrecpp.so.0.0.0 --rwxr-xr-x root/root usr/lib/libpcrecpp.so.0.0.0 +lrwxrwxrwx root/root usr/lib/libpcrecpp.so -> libpcrecpp.so.0.0.1 +lrwxrwxrwx root/root usr/lib/libpcrecpp.so.0 -> libpcrecpp.so.0.0.1 +-rwxr-xr-x root/root usr/lib/libpcrecpp.so.0.0.1 -rw-r--r-- root/root usr/lib/libpcreposix.a -rwxr-xr-x root/root usr/lib/libpcreposix.la -lrwxrwxrwx root/root usr/lib/libpcreposix.so -> libpcreposix.so.0.0.2 -lrwxrwxrwx root/root usr/lib/libpcreposix.so.0 -> libpcreposix.so.0.0.2 --rwxr-xr-x root/root usr/lib/libpcreposix.so.0.0.2 +lrwxrwxrwx root/root usr/lib/libpcreposix.so -> libpcreposix.so.0.0.3 +lrwxrwxrwx root/root usr/lib/libpcreposix.so.0 -> libpcreposix.so.0.0.3 +-rwxr-xr-x root/root usr/lib/libpcreposix.so.0.0.3 drwxr-xr-x root/root usr/lib/pkgconfig/ -rw-r--r-- root/root usr/lib/pkgconfig/libpcre.pc -rw-r--r-- root/root usr/lib/pkgconfig/libpcrecpp.pc -rw-r--r-- root/root usr/lib/pkgconfig/libpcreposix.pc -drwxr-xr-x root/root usr/man/ -drwxr-xr-x root/root usr/man/man1/ --rw-r--r-- root/root usr/man/man1/pcre-config.1.gz --rw-r--r-- root/root usr/man/man1/pcregrep.1.gz --rw-r--r-- root/root usr/man/man1/pcretest.1.gz -drwxr-xr-x root/root usr/man/man3/ --rw-r--r-- root/root usr/man/man3/pcre.3.gz --rw-r--r-- root/root usr/man/man3/pcre_assign_jit_stack.3.gz --rw-r--r-- root/root usr/man/man3/pcre_compile.3.gz --rw-r--r-- root/root usr/man/man3/pcre_compile2.3.gz --rw-r--r-- root/root usr/man/man3/pcre_config.3.gz --rw-r--r-- root/root usr/man/man3/pcre_copy_named_substring.3.gz --rw-r--r-- root/root usr/man/man3/pcre_copy_substring.3.gz --rw-r--r-- root/root usr/man/man3/pcre_dfa_exec.3.gz --rw-r--r-- root/root usr/man/man3/pcre_exec.3.gz --rw-r--r-- root/root usr/man/man3/pcre_free_study.3.gz --rw-r--r-- root/root usr/man/man3/pcre_free_substring.3.gz --rw-r--r-- root/root usr/man/man3/pcre_free_substring_list.3.gz --rw-r--r-- root/root usr/man/man3/pcre_fullinfo.3.gz --rw-r--r-- root/root usr/man/man3/pcre_get_named_substring.3.gz --rw-r--r-- root/root usr/man/man3/pcre_get_stringnumber.3.gz --rw-r--r-- root/root usr/man/man3/pcre_get_stringtable_entries.3.gz --rw-r--r-- root/root usr/man/man3/pcre_get_substring.3.gz --rw-r--r-- root/root usr/man/man3/pcre_get_substring_list.3.gz --rw-r--r-- root/root usr/man/man3/pcre_jit_exec.3.gz --rw-r--r-- root/root usr/man/man3/pcre_jit_stack_alloc.3.gz --rw-r--r-- root/root usr/man/man3/pcre_jit_stack_free.3.gz --rw-r--r-- root/root usr/man/man3/pcre_maketables.3.gz --rw-r--r-- root/root usr/man/man3/pcre_pattern_to_host_byte_order.3.gz --rw-r--r-- root/root usr/man/man3/pcre_refcount.3.gz --rw-r--r-- root/root usr/man/man3/pcre_study.3.gz --rw-r--r-- root/root usr/man/man3/pcre_version.3.gz --rw-r--r-- root/root usr/man/man3/pcreapi.3.gz --rw-r--r-- root/root usr/man/man3/pcrebuild.3.gz --rw-r--r-- root/root usr/man/man3/pcrecallout.3.gz --rw-r--r-- root/root usr/man/man3/pcrecompat.3.gz --rw-r--r-- root/root usr/man/man3/pcrecpp.3.gz --rw-r--r-- root/root usr/man/man3/pcredemo.3.gz --rw-r--r-- root/root usr/man/man3/pcrejit.3.gz --rw-r--r-- root/root usr/man/man3/pcrelimits.3.gz --rw-r--r-- root/root usr/man/man3/pcrematching.3.gz --rw-r--r-- root/root usr/man/man3/pcrepartial.3.gz --rw-r--r-- root/root usr/man/man3/pcrepattern.3.gz --rw-r--r-- root/root usr/man/man3/pcreperform.3.gz --rw-r--r-- root/root usr/man/man3/pcreposix.3.gz --rw-r--r-- root/root usr/man/man3/pcreprecompile.3.gz --rw-r--r-- root/root usr/man/man3/pcresample.3.gz --rw-r--r-- root/root usr/man/man3/pcrestack.3.gz --rw-r--r-- root/root usr/man/man3/pcresyntax.3.gz --rw-r--r-- root/root usr/man/man3/pcreunicode.3.gz +drwxr-xr-x root/root usr/share/ +drwxr-xr-x root/root usr/share/man/ +drwxr-xr-x root/root usr/share/man/man1/ +-rw-r--r-- root/root usr/share/man/man1/pcre-config.1.gz +-rw-r--r-- root/root usr/share/man/man1/pcregrep.1.gz +-rw-r--r-- root/root usr/share/man/man1/pcretest.1.gz +drwxr-xr-x root/root usr/share/man/man3/ +-rw-r--r-- root/root usr/share/man/man3/pcre.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_assign_jit_stack.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_compile.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_compile2.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_config.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_copy_named_substring.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_copy_substring.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_dfa_exec.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_exec.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_free_study.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_free_substring.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_free_substring_list.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_fullinfo.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_get_named_substring.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_get_stringnumber.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_get_stringtable_entries.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_get_substring.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_get_substring_list.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_jit_exec.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_jit_stack_alloc.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_jit_stack_free.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_maketables.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_pattern_to_host_byte_order.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_refcount.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_study.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcre_version.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcreapi.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcrebuild.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcrecallout.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcrecompat.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcrecpp.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcredemo.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcrejit.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcrelimits.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcrematching.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcrepartial.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcrepattern.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcreperform.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcreposix.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcreprecompile.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcresample.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcrestack.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcresyntax.3.gz +-rw-r--r-- root/root usr/share/man/man3/pcreunicode.3.gz diff --git a/libpcre/.md5sum b/libpcre/.md5sum index 953c4f3..d8ed8f5 100644 --- a/libpcre/.md5sum +++ b/libpcre/.md5sum @@ -1 +1,4 @@ -6aacb23986adccd9b3bc626c00979958 pcre-8.35.tar.bz2 +45df6737e61738cc8bb061e0b9c0fbb2 01-seven-security-patches.patch +5222dd119a2cfde15df9ae2583c64698 libpcre-8.37-CVE-2015-5073.patch +08fb0081fa8b0b0b1ac60bbd9524fa18 libpcre-8.37-CVE-2015-XXXX.patch +ed91be292cb01d21bc7e526816c26981 pcre-8.37.tar.bz2 diff --git a/libpcre/01-seven-security-patches.patch b/libpcre/01-seven-security-patches.patch new file mode 100644 index 0000000..f5705e6 --- /dev/null +++ b/libpcre/01-seven-security-patches.patch @@ -0,0 +1,1250 @@ +Index: pcre/configure.ac +=================================================================== +--- pcre/configure.ac (revision 1553) ++++ pcre/configure.ac (working copy) +@@ -9,9 +9,9 @@ + dnl be defined as -RC2, for example. For real releases, it should be empty. + + m4_define(pcre_major, [8]) +-m4_define(pcre_minor, [37]) +-m4_define(pcre_prerelease, []) +-m4_define(pcre_date, [2015-04-28]) ++m4_define(pcre_minor, [38]) ++m4_define(pcre_prerelease, [-RC1]) ++m4_define(pcre_date, [2015-05-03]) + + # NOTE: The CMakeLists.txt file searches for the above variables in the first + # 50 lines of this file. Please update that if the variables above are moved. +Index: pcre/sljit/sljitConfig.h +=================================================================== +--- pcre/sljit/sljitConfig.h (revision 1553) ++++ pcre/sljit/sljitConfig.h (working copy) +@@ -96,6 +96,15 @@ + #define SLJIT_EXECUTABLE_ALLOCATOR 1 + #endif + ++/* Force cdecl calling convention even if a better calling ++ convention (e.g. fastcall) is supported by the C compiler. ++ If this option is enabled, C functions without ++ SLJIT_CALL can also be called from JIT code. */ ++#ifndef SLJIT_USE_CDECL_CALLING_CONVENTION ++/* Disabled by default */ ++#define SLJIT_USE_CDECL_CALLING_CONVENTION 0 ++#endif ++ + /* Return with error when an invalid argument is passed. */ + #ifndef SLJIT_ARGUMENT_CHECKS + /* Disabled by default */ +Index: pcre/sljit/sljitLir.c +=================================================================== +--- pcre/sljit/sljitLir.c (revision 1553) ++++ pcre/sljit/sljitLir.c (working copy) +@@ -845,8 +845,8 @@ + } + + static SLJIT_CONST char* op0_names[] = { +- (char*)"breakpoint", (char*)"nop", +- (char*)"lumul", (char*)"lsmul", (char*)"ludiv", (char*)"lsdiv", ++ (char*)"breakpoint", (char*)"nop", (char*)"lumul", (char*)"lsmul", ++ (char*)"udivmod", (char*)"sdivmod", (char*)"udivi", (char*)"sdivi" + }; + + static SLJIT_CONST char* op1_names[] = { +@@ -1036,7 +1036,7 @@ + { + #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LSMUL) +- || ((op & ~SLJIT_INT_OP) >= SLJIT_LUDIV && (op & ~SLJIT_INT_OP) <= SLJIT_LSDIV)); ++ || ((op & ~SLJIT_INT_OP) >= SLJIT_UDIVMOD && (op & ~SLJIT_INT_OP) <= SLJIT_SDIVI)); + CHECK_ARGUMENT(op < SLJIT_LUMUL || compiler->scratches >= 2); + #endif + #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) +@@ -1447,6 +1447,8 @@ + + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset) + { ++ SLJIT_UNUSED_ARG(offset); ++ + #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + FUNCTION_CHECK_DST(dst, dstw); + #endif +@@ -1462,6 +1464,8 @@ + + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value) + { ++ SLJIT_UNUSED_ARG(init_value); ++ + #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + FUNCTION_CHECK_DST(dst, dstw); + #endif +Index: pcre/sljit/sljitNativeMIPS_common.c +=================================================================== +--- pcre/sljit/sljitNativeMIPS_common.c (revision 1553) ++++ pcre/sljit/sljitNativeMIPS_common.c (working copy) +@@ -1053,8 +1053,11 @@ + #endif + FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0))); + return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); +- case SLJIT_LUDIV: +- case SLJIT_LSDIV: ++ case SLJIT_UDIVMOD: ++ case SLJIT_SDIVMOD: ++ case SLJIT_UDIVI: ++ case SLJIT_SDIVI: ++ SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); + #if !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +@@ -1062,15 +1065,15 @@ + + #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) + if (int_op) +- FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); ++ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); + else +- FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); ++ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); + #else +- FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); ++ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); + #endif + + FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0))); +- return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); ++ return (op >= SLJIT_UDIVI) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); + } + + return SLJIT_SUCCESS; +Index: pcre/sljit/sljitNativeSPARC_common.c +=================================================================== +--- pcre/sljit/sljitNativeSPARC_common.c (revision 1553) ++++ pcre/sljit/sljitNativeSPARC_common.c (working copy) +@@ -777,20 +777,25 @@ + #else + #error "Implementation required" + #endif +- case SLJIT_LUDIV: +- case SLJIT_LSDIV: ++ case SLJIT_UDIVMOD: ++ case SLJIT_SDIVMOD: ++ case SLJIT_UDIVI: ++ case SLJIT_SDIVI: ++ SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); + #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) +- if (op == SLJIT_LUDIV) ++ if ((op | 0x2) == SLJIT_UDIVI) + FAIL_IF(push_inst(compiler, WRY | S1(0), MOVABLE_INS)); + else { + FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(SLJIT_R0) | IMM(31), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, WRY | S1(TMP_REG1), MOVABLE_INS)); + } +- FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2))); +- FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0))); ++ if (op <= SLJIT_SDIVMOD) ++ FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2))); ++ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0))); ++ if (op >= SLJIT_UDIVI) ++ return SLJIT_SUCCESS; + FAIL_IF(push_inst(compiler, SMUL | D(SLJIT_R1) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R1))); +- FAIL_IF(push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1))); +- return SLJIT_SUCCESS; ++ return push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1)); + #else + #error "Implementation required" + #endif +Index: pcre/sljit/sljitNativeARM_32.c +=================================================================== +--- pcre/sljit/sljitNativeARM_32.c (revision 1553) ++++ pcre/sljit/sljitNativeARM_32.c (working copy) +@@ -1833,18 +1833,33 @@ + | (reg_map[SLJIT_R0] << 8) + | reg_map[TMP_REG1]); + #endif +- case SLJIT_LUDIV: +- case SLJIT_LSDIV: +- if (compiler->scratches >= 3) ++ case SLJIT_UDIVMOD: ++ case SLJIT_SDIVMOD: ++ case SLJIT_UDIVI: ++ case SLJIT_SDIVI: ++ SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); ++ SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2, bad_register_mapping); ++ ++ if ((op >= SLJIT_UDIVI) && (compiler->scratches >= 3)) { + FAIL_IF(push_inst(compiler, 0xe52d2008 /* str r2, [sp, #-8]! */)); ++ FAIL_IF(push_inst(compiler, 0xe58d1004 /* str r1, [sp, #4] */)); ++ } ++ else if ((op >= SLJIT_UDIVI) || (compiler->scratches >= 3)) ++ FAIL_IF(push_inst(compiler, 0xe52d0008 | (op >= SLJIT_UDIVI ? 0x1000 : 0x2000) /* str r1/r2, [sp, #-8]! */)); ++ + #if defined(__GNUC__) + FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, +- (op == SLJIT_LUDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); ++ ((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); + #else + #error "Software divmod functions are needed" + #endif +- if (compiler->scratches >= 3) +- return push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */); ++ ++ if ((op >= SLJIT_UDIVI) && (compiler->scratches >= 3)) { ++ FAIL_IF(push_inst(compiler, 0xe59d1004 /* ldr r1, [sp, #4] */)); ++ FAIL_IF(push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */)); ++ } ++ else if ((op >= SLJIT_UDIVI) || (compiler->scratches >= 3)) ++ return push_inst(compiler, 0xe49d0008 | (op >= SLJIT_UDIVI ? 0x1000 : 0x2000) /* ldr r1/r2, [sp], #8 */); + return SLJIT_SUCCESS; + } + +Index: pcre/sljit/sljitLir.h +=================================================================== +--- pcre/sljit/sljitLir.h (revision 1553) ++++ pcre/sljit/sljitLir.h (working copy) +@@ -687,7 +687,7 @@ + #define SLJIT_OP0_BASE 0 + + /* Flags: - (never set any flags) +- Note: breakpoint instruction is not supported by all architectures (namely ppc) ++ Note: breakpoint instruction is not supported by all architectures (e.g. ppc) + It falls back to SLJIT_NOP in those cases. */ + #define SLJIT_BREAKPOINT (SLJIT_OP0_BASE + 0) + /* Flags: - (never set any flags) +@@ -696,24 +696,42 @@ + #define SLJIT_NOP (SLJIT_OP0_BASE + 1) + /* Flags: - (may destroy flags) + Unsigned multiplication of SLJIT_R0 and SLJIT_R1. +- Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */ ++ Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */ + #define SLJIT_LUMUL (SLJIT_OP0_BASE + 2) + /* Flags: - (may destroy flags) + Signed multiplication of SLJIT_R0 and SLJIT_R1. +- Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */ ++ Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */ + #define SLJIT_LSMUL (SLJIT_OP0_BASE + 3) + /* Flags: I - (may destroy flags) + Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1. +- The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1. +- Note: if SLJIT_R1 contains 0, the behaviour is undefined. */ +-#define SLJIT_LUDIV (SLJIT_OP0_BASE + 4) +-#define SLJIT_ILUDIV (SLJIT_LUDIV | SLJIT_INT_OP) ++ The result is placed into SLJIT_R0 and the remainder into SLJIT_R1. ++ Note: if SLJIT_R1 is 0, the behaviour is undefined. */ ++#define SLJIT_UDIVMOD (SLJIT_OP0_BASE + 4) ++#define SLJIT_IUDIVMOD (SLJIT_UDIVMOD | SLJIT_INT_OP) + /* Flags: I - (may destroy flags) + Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1. +- The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1. +- Note: if SLJIT_R1 contains 0, the behaviour is undefined. */ +-#define SLJIT_LSDIV (SLJIT_OP0_BASE + 5) +-#define SLJIT_ILSDIV (SLJIT_LSDIV | SLJIT_INT_OP) ++ The result is placed into SLJIT_R0 and the remainder into SLJIT_R1. ++ Note: if SLJIT_R1 is 0, the behaviour is undefined. ++ Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00), ++ the behaviour is undefined. */ ++#define SLJIT_SDIVMOD (SLJIT_OP0_BASE + 5) ++#define SLJIT_ISDIVMOD (SLJIT_SDIVMOD | SLJIT_INT_OP) ++/* Flags: I - (may destroy flags) ++ Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1. ++ The result is placed into SLJIT_R0. SLJIT_R1 preserves its value. ++ Note: if SLJIT_R1 is 0, the behaviour is undefined. ++ Note: SLJIT_SDIV is single precision divide. */ ++#define SLJIT_UDIVI (SLJIT_OP0_BASE + 6) ++#define SLJIT_IUDIVI (SLJIT_UDIVI | SLJIT_INT_OP) ++/* Flags: I - (may destroy flags) ++ Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1. ++ The result is placed into SLJIT_R0. SLJIT_R1 preserves its value. ++ Note: if SLJIT_R1 is 0, the behaviour is undefined. ++ Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00), ++ the behaviour is undefined. ++ Note: SLJIT_SDIV is single precision divide. */ ++#define SLJIT_SDIVI (SLJIT_OP0_BASE + 7) ++#define SLJIT_ISDIVI (SLJIT_SDIVI | SLJIT_INT_OP) + + SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op); + +Index: pcre/sljit/sljitNativeARM_T2_32.c +=================================================================== +--- pcre/sljit/sljitNativeARM_T2_32.c (revision 1553) ++++ pcre/sljit/sljitNativeARM_T2_32.c (working copy) +@@ -1239,6 +1239,9 @@ + + SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op) + { ++ sljit_sw saved_reg_list[3]; ++ sljit_sw saved_reg_count; ++ + CHECK_ERROR(); + CHECK(check_sljit_emit_op0(compiler, op)); + +@@ -1255,24 +1258,53 @@ + | (reg_map[SLJIT_R0] << 12) + | (reg_map[SLJIT_R0] << 16) + | reg_map[SLJIT_R1]); +- case SLJIT_LUDIV: +- case SLJIT_LSDIV: +- if (compiler->scratches >= 4) { +- FAIL_IF(push_inst32(compiler, 0xf84d2d04 /* str r2, [sp, #-4]! */)); +- FAIL_IF(push_inst32(compiler, 0xf84dcd04 /* str ip, [sp, #-4]! */)); +- } else if (compiler->scratches >= 3) +- FAIL_IF(push_inst32(compiler, 0xf84d2d08 /* str r2, [sp, #-8]! */)); ++ case SLJIT_UDIVMOD: ++ case SLJIT_SDIVMOD: ++ case SLJIT_UDIVI: ++ case SLJIT_SDIVI: ++ SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); ++ SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 12, bad_register_mapping); ++ ++ saved_reg_count = 0; ++ if (compiler->scratches >= 4) ++ saved_reg_list[saved_reg_count++] = 12; ++ if (compiler->scratches >= 3) ++ saved_reg_list[saved_reg_count++] = 2; ++ if (op >= SLJIT_UDIVI) ++ saved_reg_list[saved_reg_count++] = 1; ++ ++ if (saved_reg_count > 0) { ++ FAIL_IF(push_inst32(compiler, 0xf84d0d00 | (saved_reg_count >= 3 ? 16 : 8) ++ | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */)); ++ if (saved_reg_count >= 2) { ++ SLJIT_ASSERT(saved_reg_list[1] < 8); ++ FAIL_IF(push_inst16(compiler, 0x9001 | (saved_reg_list[1] << 8) /* str rX, [sp, #4] */)); ++ } ++ if (saved_reg_count >= 3) { ++ SLJIT_ASSERT(saved_reg_list[2] < 8); ++ FAIL_IF(push_inst16(compiler, 0x9002 | (saved_reg_list[2] << 8) /* str rX, [sp, #8] */)); ++ } ++ } ++ + #if defined(__GNUC__) + FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, +- (op == SLJIT_LUDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); ++ ((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); + #else + #error "Software divmod functions are needed" + #endif +- if (compiler->scratches >= 4) { +- FAIL_IF(push_inst32(compiler, 0xf85dcb04 /* ldr ip, [sp], #4 */)); +- return push_inst32(compiler, 0xf85d2b04 /* ldr r2, [sp], #4 */); +- } else if (compiler->scratches >= 3) +- return push_inst32(compiler, 0xf85d2b08 /* ldr r2, [sp], #8 */); ++ ++ if (saved_reg_count > 0) { ++ if (saved_reg_count >= 3) { ++ SLJIT_ASSERT(saved_reg_list[2] < 8); ++ FAIL_IF(push_inst16(compiler, 0x9802 | (saved_reg_list[2] << 8) /* ldr rX, [sp, #8] */)); ++ } ++ if (saved_reg_count >= 2) { ++ SLJIT_ASSERT(saved_reg_list[1] < 8); ++ FAIL_IF(push_inst16(compiler, 0x9801 | (saved_reg_list[1] << 8) /* ldr rX, [sp, #4] */)); ++ } ++ return push_inst32(compiler, 0xf85d0b00 | (saved_reg_count >= 3 ? 16 : 8) ++ | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */); ++ } + return SLJIT_SUCCESS; + } + +Index: pcre/sljit/sljitNativeARM_64.c +=================================================================== +--- pcre/sljit/sljitNativeARM_64.c (revision 1553) ++++ pcre/sljit/sljitNativeARM_64.c (working copy) +@@ -1087,14 +1087,20 @@ + saved_regs_size += sizeof(sljit_sw); + } + local_size -= saved_regs_size + SLJIT_LOCALS_OFFSET; +- FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10))); ++ if (saved_regs_size > 0) ++ FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10))); + } + + tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; + prev = -1; + for (i = SLJIT_S0; i >= tmp; i--) { + if (prev == -1) { +- prev = i; ++ if (!(offs & (1 << 15))) { ++ prev = i; ++ continue; ++ } ++ FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5))); ++ offs += 1 << 15; + continue; + } + FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); +@@ -1104,7 +1110,12 @@ + + for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { + if (prev == -1) { +- prev = i; ++ if (!(offs & (1 << 15))) { ++ prev = i; ++ continue; ++ } ++ FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5))); ++ offs += 1 << 15; + continue; + } + FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); +@@ -1112,8 +1123,7 @@ + prev = -1; + } + +- if (prev != -1) +- FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(TMP_SP) | (offs >> 5))); ++ SLJIT_ASSERT(prev == -1); + + if (compiler->local_size > (63 * sizeof(sljit_sw))) { + /* The local_size is already adjusted by the saved registers. */ +@@ -1188,7 +1198,12 @@ + prev = -1; + for (i = SLJIT_S0; i >= tmp; i--) { + if (prev == -1) { +- prev = i; ++ if (!(offs & (1 << 15))) { ++ prev = i; ++ continue; ++ } ++ FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5))); ++ offs += 1 << 15; + continue; + } + FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); +@@ -1198,7 +1213,12 @@ + + for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { + if (prev == -1) { +- prev = i; ++ if (!(offs & (1 << 15))) { ++ prev = i; ++ continue; ++ } ++ FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5))); ++ offs += 1 << 15; + continue; + } + FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); +@@ -1206,13 +1226,12 @@ + prev = -1; + } + +- if (prev != -1) +- FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(TMP_SP) | (offs >> 5))); ++ SLJIT_ASSERT(prev == -1); + + if (compiler->local_size <= (63 * sizeof(sljit_sw))) { + FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR) + | RN(TMP_SP) | (((local_size >> 3) & 0x7f) << 15))); +- } else { ++ } else if (saved_regs_size > 0) { + FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10))); + } + +@@ -1242,12 +1261,15 @@ + FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0))); + FAIL_IF(push_inst(compiler, MADD | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO))); + return push_inst(compiler, (op == SLJIT_LUMUL ? UMULH : SMULH) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1)); +- case SLJIT_LUDIV: +- case SLJIT_LSDIV: ++ case SLJIT_UDIVMOD: ++ case SLJIT_SDIVMOD: + FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0))); +- FAIL_IF(push_inst(compiler, ((op == SLJIT_LUDIV ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1))); ++ FAIL_IF(push_inst(compiler, ((op == SLJIT_UDIVMOD ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1))); + FAIL_IF(push_inst(compiler, (MADD ^ inv_bits) | RD(SLJIT_R1) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO))); + return push_inst(compiler, (SUB ^ inv_bits) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1)); ++ case SLJIT_UDIVI: ++ case SLJIT_SDIVI: ++ return push_inst(compiler, ((op == SLJIT_UDIVI ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)); + } + + return SLJIT_SUCCESS; +Index: pcre/sljit/sljitNativePPC_common.c +=================================================================== +--- pcre/sljit/sljitNativePPC_common.c (revision 1553) ++++ pcre/sljit/sljitNativePPC_common.c (working copy) +@@ -1267,22 +1267,23 @@ + FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); + return push_inst(compiler, (op == SLJIT_LUMUL ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1)); + #endif +- case SLJIT_LUDIV: +- case SLJIT_LSDIV: ++ case SLJIT_UDIVMOD: ++ case SLJIT_SDIVMOD: + FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0))); + #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) +- if (int_op) { +- FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); +- FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); +- } else { +- FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVDU : DIVD) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); +- FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); +- } +- return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1)); ++ FAIL_IF(push_inst(compiler, (int_op ? (op == SLJIT_UDIVMOD ? DIVWU : DIVW) : (op == SLJIT_UDIVMOD ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1))); ++ FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); + #else +- FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); ++ FAIL_IF(push_inst(compiler, (op == SLJIT_UDIVMOD ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1))); + FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); ++#endif + return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1)); ++ case SLJIT_UDIVI: ++ case SLJIT_SDIVI: ++#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) ++ return push_inst(compiler, (int_op ? (op == SLJIT_UDIVI ? DIVWU : DIVW) : (op == SLJIT_UDIVI ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)); ++#else ++ return push_inst(compiler, (op == SLJIT_UDIVI ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)); + #endif + } + +Index: pcre/sljit/sljitNativeX86_common.c +=================================================================== +--- pcre/sljit/sljitNativeX86_common.c (revision 1553) ++++ pcre/sljit/sljitNativeX86_common.c (working copy) +@@ -742,8 +742,10 @@ + break; + case SLJIT_LUMUL: + case SLJIT_LSMUL: +- case SLJIT_LUDIV: +- case SLJIT_LSDIV: ++ case SLJIT_UDIVMOD: ++ case SLJIT_SDIVMOD: ++ case SLJIT_UDIVI: ++ case SLJIT_SDIVI: + compiler->flags_saved = 0; + #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + #ifdef _WIN64 +@@ -761,9 +763,10 @@ + #endif + compiler->mode32 = op & SLJIT_INT_OP; + #endif ++ SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); + + op = GET_OPCODE(op); +- if (op == SLJIT_LUDIV) { ++ if ((op | 0x2) == SLJIT_UDIVI) { + #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64) + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0); + inst = emit_x86_instruction(compiler, 1, SLJIT_R1, 0, SLJIT_R1, 0); +@@ -774,7 +777,7 @@ + *inst = XOR_r_rm; + } + +- if (op == SLJIT_LSDIV) { ++ if ((op | 0x2) == SLJIT_SDIVI) { + #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64) + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0); + #endif +@@ -805,10 +808,10 @@ + FAIL_IF(!inst); + INC_SIZE(2); + *inst++ = GROUP_F7; +- *inst = MOD_REG | ((op >= SLJIT_LUDIV) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]); ++ *inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]); + #else + #ifdef _WIN64 +- size = (!compiler->mode32 || op >= SLJIT_LUDIV) ? 3 : 2; ++ size = (!compiler->mode32 || op >= SLJIT_UDIVMOD) ? 3 : 2; + #else + size = (!compiler->mode32) ? 3 : 2; + #endif +@@ -817,11 +820,11 @@ + INC_SIZE(size); + #ifdef _WIN64 + if (!compiler->mode32) +- *inst++ = REX_W | ((op >= SLJIT_LUDIV) ? REX_B : 0); +- else if (op >= SLJIT_LUDIV) ++ *inst++ = REX_W | ((op >= SLJIT_UDIVMOD) ? REX_B : 0); ++ else if (op >= SLJIT_UDIVMOD) + *inst++ = REX_B; + *inst++ = GROUP_F7; +- *inst = MOD_REG | ((op >= SLJIT_LUDIV) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]); ++ *inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]); + #else + if (!compiler->mode32) + *inst++ = REX_W; +@@ -836,15 +839,21 @@ + case SLJIT_LSMUL: + *inst |= IMUL; + break; +- case SLJIT_LUDIV: ++ case SLJIT_UDIVMOD: ++ case SLJIT_UDIVI: + *inst |= DIV; + break; +- case SLJIT_LSDIV: ++ case SLJIT_SDIVMOD: ++ case SLJIT_SDIVI: + *inst |= IDIV; + break; + } + #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64) +- EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); ++ if (op <= SLJIT_SDIVMOD) ++ EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); ++#else ++ if (op >= SLJIT_UDIVI) ++ EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); + #endif + break; + } +@@ -1905,60 +1914,62 @@ + return SLJIT_SUCCESS; + } + +- if (FAST_IS_REG(src1)) { ++ if (!(src1 & SLJIT_IMM)) { + if (src2 & SLJIT_IMM) { + #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (IS_HALFWORD(src2w) || compiler->mode32) { +- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0); ++ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w); + FAIL_IF(!inst); + *inst = GROUP_F7; + } + else { + FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w)); +- inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, 0); ++ inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, src1w); + FAIL_IF(!inst); + *inst = TEST_rm_r; + } + #else +- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0); ++ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w); + FAIL_IF(!inst); + *inst = GROUP_F7; + #endif ++ return SLJIT_SUCCESS; + } +- else { ++ else if (FAST_IS_REG(src1)) { + inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w); + FAIL_IF(!inst); + *inst = TEST_rm_r; ++ return SLJIT_SUCCESS; + } +- return SLJIT_SUCCESS; + } + +- if (FAST_IS_REG(src2)) { ++ if (!(src2 & SLJIT_IMM)) { + if (src1 & SLJIT_IMM) { + #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (IS_HALFWORD(src1w) || compiler->mode32) { +- inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, 0); ++ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, src2w); + FAIL_IF(!inst); + *inst = GROUP_F7; + } + else { + FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w)); +- inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, 0); ++ inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, src2w); + FAIL_IF(!inst); + *inst = TEST_rm_r; + } + #else +- inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, 0); ++ inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, src2w); + FAIL_IF(!inst); + *inst = GROUP_F7; + #endif ++ return SLJIT_SUCCESS; + } +- else { ++ else if (FAST_IS_REG(src2)) { + inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w); + FAIL_IF(!inst); + *inst = TEST_rm_r; ++ return SLJIT_SUCCESS; + } +- return SLJIT_SUCCESS; + } + + EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); +Index: pcre/sljit/sljitConfigInternal.h +=================================================================== +--- pcre/sljit/sljitConfigInternal.h (revision 1553) ++++ pcre/sljit/sljitConfigInternal.h (working copy) +@@ -468,7 +468,12 @@ + + #ifndef SLJIT_CALL + +-#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) ++#if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION) ++ ++/* Force cdecl. */ ++#define SLJIT_CALL ++ ++#elif (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + + #if defined(__GNUC__) && !defined(__APPLE__) + +Index: pcre/ChangeLog +=================================================================== +--- pcre/ChangeLog (revision 1553) ++++ pcre/ChangeLog (working copy) +@@ -1,6 +1,46 @@ + ChangeLog for PCRE + ------------------ + ++Note that the PCRE 8.xx series (PCRE1) is now in a bugfix-only state. All ++development is happening in the PCRE2 10.xx series. ++ ++Version 8.38 xx-xxx-xxxx ++------------------------ ++ ++1. If a group that contained a recursive back reference also contained a ++ forward reference subroutine call followed by a non-forward-reference ++ subroutine call, for example /.((?2)(?R)\1)()/, pcre2_compile() failed to ++ compile correct code, leading to undefined behaviour or an internally ++ detected error. This bug was discovered by the LLVM fuzzer. ++ ++2. Quantification of certain items (e.g. atomic back references) could cause ++ incorrect code to be compiled when recursive forward references were ++ involved. For example, in this pattern: /(?1)()((((((\1++))\x85)+)|))/. ++ This bug was discovered by the LLVM fuzzer. ++ ++3. A repeated conditional group whose condition was a reference by name caused ++ a buffer overflow if there was more than one group with the given name. ++ This bug was discovered by the LLVM fuzzer. ++ ++4. A recursive back reference by name within a group that had the same name as ++ another group caused a buffer overflow. For example: ++ /(?J)(?'d'(?'d'\g{d}))/. This bug was discovered by the LLVM fuzzer. ++ ++5. A forward reference by name to a group whose number is the same as the ++ current group, for example in this pattern: /(?|(\k'Pm')|(?'Pm'))/, caused ++ a buffer overflow at compile time. This bug was discovered by the LLVM ++ fuzzer. ++ ++6. A lookbehind assertion within a set of mutually recursive subpatterns could ++ provoke a buffer overflow. This bug was discovered by the LLVM fuzzer. ++ ++7. Another buffer overflow bug involved duplicate named groups with a ++ reference between their definition, with a group that reset capture ++ numbers, for example: /(?J:(?|(?'R')(\k'R')|((?'R'))))/. This has been ++ fixed by always allowing for more memory, even if not needed. (A proper fix ++ is implemented in PCRE2, but it involves more refactoring.) ++ ++ + Version 8.37 28-April-2015 + -------------------------- + +Index: pcre/testdata/testoutput1 +=================================================================== +--- pcre/testdata/testoutput1 (revision 1553) ++++ pcre/testdata/testoutput1 (working copy) +@@ -9429,4 +9429,9 @@ + 0: aaaaaaaaa + 1: a + ++"(?|(\k'Pm')|(?'Pm'))" ++ abcd ++ 0: ++ 1: ++ + /-- End of testinput1 --/ +Index: pcre/testdata/testoutput2 +=================================================================== +--- pcre/testdata/testoutput2 (revision 1553) ++++ pcre/testdata/testoutput2 (working copy) +@@ -14423,4 +14423,42 @@ + + /((?2){73}(?2))((?1))/ + ++/.((?2)(?R)\1)()/BZ ++------------------------------------------------------------------ ++ Bra ++ Any ++ Once ++ CBra 1 ++ Recurse ++ Recurse ++ \1 ++ Ket ++ Ket ++ CBra 2 ++ Ket ++ Ket ++ End ++------------------------------------------------------------------ ++ ++/(?1)()((((((\1++))\x85)+)|))/ ++ ++/(\9*+(?2);\3++()2|)++{/ ++Failed: reference to non-existent subpattern at offset 22 ++ ++/\V\x85\9*+((?2)\3++()2)*:2/ ++Failed: reference to non-existent subpattern at offset 26 ++ ++/(((?(R)){0,2}) (?''((?'R')((?'R')))))/J ++ ++/(((?(X)){0,2}) (?''((?'X')((?'X')))))/J ++ ++/(((?(R)){0,2}) (?''((?'X')((?'R')))))/ ++ ++"(?J)(?'d'(?'d'\g{d}))" ++ ++".*?\h.+.\.+\R*?\xd(?i)(?=!(?=b`b`b`\`b\xa9b!)`\a`bbbbbbbbbbbbb`bbbbbbbbbbbb*R\x85bbbbbbb\C?{((?2)(?))(( ++\H){8(?<=(?1){29}\xa8bbbb\x16\xd\xc6^($(?a)...(?P=a)bbb(?P>a)d/BM +-Memory allocation (code space): 61 ++Memory allocation (code space): 77 + ------------------------------------------------------------------ + 0 24 Bra + 2 5 CBra 1 +@@ -748,4 +748,21 @@ + 22 End + ------------------------------------------------------------------ + ++/.((?2)(?R)\1)()/B ++------------------------------------------------------------------ ++ 0 23 Bra ++ 2 Any ++ 3 13 Once ++ 5 9 CBra 1 ++ 8 18 Recurse ++ 10 0 Recurse ++ 12 \1 ++ 14 9 Ket ++ 16 13 Ket ++ 18 3 CBra 2 ++ 21 3 Ket ++ 23 23 Ket ++ 25 End ++------------------------------------------------------------------ ++ + /-- End of testinput11 --/ +Index: pcre/testdata/testinput11 +=================================================================== +--- pcre/testdata/testinput11 (revision 1553) ++++ pcre/testdata/testinput11 (working copy) +@@ -136,4 +136,6 @@ + + /((?+1)(\1))/B + ++/.((?2)(?R)\1)()/B ++ + /-- End of testinput11 --/ +Index: pcre/testdata/testoutput11-8 +=================================================================== +--- pcre/testdata/testoutput11-8 (revision 1553) ++++ pcre/testdata/testoutput11-8 (working copy) +@@ -231,7 +231,7 @@ + ------------------------------------------------------------------ + + /(?Pa)...(?P=a)bbb(?P>a)d/BM +-Memory allocation (code space): 38 ++Memory allocation (code space): 50 + ------------------------------------------------------------------ + 0 30 Bra + 3 7 CBra 1 +@@ -748,4 +748,21 @@ + 34 End + ------------------------------------------------------------------ + ++/.((?2)(?R)\1)()/B ++------------------------------------------------------------------ ++ 0 35 Bra ++ 3 Any ++ 4 20 Once ++ 7 14 CBra 1 ++ 12 27 Recurse ++ 15 0 Recurse ++ 18 \1 ++ 21 14 Ket ++ 24 20 Ket ++ 27 5 CBra 2 ++ 32 5 Ket ++ 35 35 Ket ++ 38 End ++------------------------------------------------------------------ ++ + /-- End of testinput11 --/ +Index: pcre/testdata/testinput1 +=================================================================== +--- pcre/testdata/testinput1 (revision 1553) ++++ pcre/testdata/testinput1 (working copy) +@@ -5730,4 +5730,7 @@ + "(?1)(?#?'){8}(a)" + baaaaaaaaac + ++"(?|(\k'Pm')|(?'Pm'))" ++ abcd ++ + /-- End of testinput1 --/ +Index: pcre/testdata/testinput2 +=================================================================== +--- pcre/testdata/testinput2 (revision 1553) ++++ pcre/testdata/testinput2 (working copy) +@@ -4152,4 +4152,25 @@ + + /((?2){73}(?2))((?1))/ + ++/.((?2)(?R)\1)()/BZ ++ ++/(?1)()((((((\1++))\x85)+)|))/ ++ ++/(\9*+(?2);\3++()2|)++{/ ++ ++/\V\x85\9*+((?2)\3++()2)*:2/ ++ ++/(((?(R)){0,2}) (?''((?'R')((?'R')))))/J ++ ++/(((?(X)){0,2}) (?''((?'X')((?'X')))))/J ++ ++/(((?(R)){0,2}) (?''((?'X')((?'R')))))/ ++ ++"(?J)(?'d'(?'d'\g{d}))" ++ ++".*?\h.+.\.+\R*?\xd(?i)(?=!(?=b`b`b`\`b\xa9b!)`\a`bbbbbbbbbbbbb`bbbbbbbbbbbb*R\x85bbbbbbb\C?{((?2)(?))(( ++\H){8(?<=(?1){29}\xa8bbbb\x16\xd\xc6^($(?a)...(?P=a)bbb(?P>a)d/BM +-Memory allocation (code space): 125 ++Memory allocation (code space): 157 + ------------------------------------------------------------------ + 0 24 Bra + 2 5 CBra 1 +@@ -748,4 +748,21 @@ + 22 End + ------------------------------------------------------------------ + ++/.((?2)(?R)\1)()/B ++------------------------------------------------------------------ ++ 0 23 Bra ++ 2 Any ++ 3 13 Once ++ 5 9 CBra 1 ++ 8 18 Recurse ++ 10 0 Recurse ++ 12 \1 ++ 14 9 Ket ++ 16 13 Ket ++ 18 3 CBra 2 ++ 21 3 Ket ++ 23 23 Ket ++ 25 End ++------------------------------------------------------------------ ++ + /-- End of testinput11 --/ +Index: pcre/pcre_compile.c +=================================================================== +--- pcre/pcre_compile.c (revision 1553) ++++ pcre/pcre_compile.c (working copy) +@@ -1799,7 +1799,7 @@ + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + do cc += GET(cc, 1); while (*cc == OP_ALT); +- cc += PRIV(OP_lengths)[*cc]; ++ cc += 1 + LINK_SIZE; + break; + + /* Skip over things that don't match chars */ +@@ -3985,11 +3985,12 @@ + is called, the partially compiled regex must be temporarily terminated with + OP_END. + +-This function has been extended with the possibility of forward references for +-recursions and subroutine calls. It must also check the list of such references +-for the group we are dealing with. If it finds that one of the recursions in +-the current group is on this list, it adjusts the offset in the list, not the +-value in the reference (which is a group number). ++This function has been extended to cope with forward references for recursions ++and subroutine calls. It must check the list of such references for the ++group we are dealing with. If it finds that one of the recursions in the ++current group is on this list, it does not adjust the value in the reference ++(which is a group number). After the group has been scanned, all the offsets in ++the forward reference list for the group are adjusted. + + Arguments: + group points to the start of the group +@@ -4005,29 +4006,21 @@ + adjust_recurse(pcre_uchar *group, int adjust, BOOL utf, compile_data *cd, + size_t save_hwm_offset) + { ++int offset; ++pcre_uchar *hc; + pcre_uchar *ptr = group; + + while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL) + { +- int offset; +- pcre_uchar *hc; +- +- /* See if this recursion is on the forward reference list. If so, adjust the +- reference. */ +- + for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm; + hc += LINK_SIZE) + { + offset = (int)GET(hc, 0); +- if (cd->start_code + offset == ptr + 1) +- { +- PUT(hc, 0, offset + adjust); +- break; +- } ++ if (cd->start_code + offset == ptr + 1) break; + } + +- /* Otherwise, adjust the recursion offset if it's after the start of this +- group. */ ++ /* If we have not found this recursion on the forward reference list, adjust ++ the recursion's offset if it's after the start of this group. */ + + if (hc >= cd->hwm) + { +@@ -4037,6 +4030,15 @@ + + ptr += 1 + LINK_SIZE; + } ++ ++/* Now adjust all forward reference offsets for the group. */ ++ ++for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm; ++ hc += LINK_SIZE) ++ { ++ offset = (int)GET(hc, 0); ++ PUT(hc, 0, offset + adjust); ++ } + } + + +@@ -4465,7 +4467,7 @@ + const pcre_uchar *nestptr = NULL; + pcre_uchar *previous = NULL; + pcre_uchar *previous_callout = NULL; +-size_t save_hwm_offset = 0; ++size_t item_hwm_offset = 0; + pcre_uint8 classbits[32]; + + /* We can fish out the UTF-8 setting once and for all into a BOOL, but we +@@ -4767,6 +4769,7 @@ + zeroreqchar = reqchar; + zeroreqcharflags = reqcharflags; + previous = code; ++ item_hwm_offset = cd->hwm - cd->start_workspace; + *code++ = ((options & PCRE_DOTALL) != 0)? OP_ALLANY: OP_ANY; + break; + +@@ -4818,6 +4821,7 @@ + /* Handle a real character class. */ + + previous = code; ++ item_hwm_offset = cd->hwm - cd->start_workspace; + + /* PCRE supports POSIX class stuff inside a class. Perl gives an error if + they are encountered at the top level, so we'll do that too. */ +@@ -5930,7 +5934,7 @@ + { + register int i; + int len = (int)(code - previous); +- size_t base_hwm_offset = save_hwm_offset; ++ size_t base_hwm_offset = item_hwm_offset; + pcre_uchar *bralink = NULL; + pcre_uchar *brazeroptr = NULL; + +@@ -5985,7 +5989,7 @@ + if (repeat_max <= 1) /* Covers 0, 1, and unlimited */ + { + *code = OP_END; +- adjust_recurse(previous, 1, utf, cd, save_hwm_offset); ++ adjust_recurse(previous, 1, utf, cd, item_hwm_offset); + memmove(previous + 1, previous, IN_UCHARS(len)); + code++; + if (repeat_max == 0) +@@ -6009,7 +6013,7 @@ + { + int offset; + *code = OP_END; +- adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, save_hwm_offset); ++ adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, item_hwm_offset); + memmove(previous + 2 + LINK_SIZE, previous, IN_UCHARS(len)); + code += 2 + LINK_SIZE; + *previous++ = OP_BRAZERO + repeat_type; +@@ -6267,7 +6271,7 @@ + { + int nlen = (int)(code - bracode); + *code = OP_END; +- adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, save_hwm_offset); ++ adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); + memmove(bracode + 1 + LINK_SIZE, bracode, IN_UCHARS(nlen)); + code += 1 + LINK_SIZE; + nlen += 1 + LINK_SIZE; +@@ -6401,7 +6405,7 @@ + else + { + *code = OP_END; +- adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset); ++ adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); + memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len)); + code += 1 + LINK_SIZE; + len += 1 + LINK_SIZE; +@@ -6450,7 +6454,7 @@ + + default: + *code = OP_END; +- adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset); ++ adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); + memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len)); + code += 1 + LINK_SIZE; + len += 1 + LINK_SIZE; +@@ -6623,7 +6627,7 @@ + newoptions = options; + skipbytes = 0; + bravalue = OP_CBRA; +- save_hwm_offset = cd->hwm - cd->start_workspace; ++ item_hwm_offset = cd->hwm - cd->start_workspace; + reset_bracount = FALSE; + + /* Deal with the extended parentheses; all are introduced by '?', and the +@@ -6769,7 +6773,7 @@ + ptr++; + } + namelen = (int)(ptr - name); +- if (lengthptr != NULL) *lengthptr += IMM2_SIZE; ++ if (lengthptr != NULL) skipbytes += IMM2_SIZE; + } + + /* Check the terminator */ +@@ -7173,14 +7177,26 @@ + number. If the name is not found, set the value to 0 for a forward + reference. */ + ++ recno = 0; + ng = cd->named_groups; + for (i = 0; i < cd->names_found; i++, ng++) + { + if (namelen == ng->length && + STRNCMP_UC_UC(name, ng->name, namelen) == 0) +- break; ++ { ++ open_capitem *oc; ++ recno = ng->number; ++ if (is_recurse) break; ++ for (oc = cd->open_caps; oc != NULL; oc = oc->next) ++ { ++ if (oc->number == recno) ++ { ++ oc->flag = TRUE; ++ break; ++ } ++ } ++ } + } +- recno = (i < cd->names_found)? ng->number : 0; + + /* Count named back references. */ + +@@ -7191,6 +7207,19 @@ + 16-bit data item. */ + + *lengthptr += IMM2_SIZE; ++ ++ /* If this is a forward reference and we are within a (?|...) group, ++ the reference may end up as the number of a group which we are ++ currently inside, that is, it could be a recursive reference. In the ++ real compile this will be picked up and the reference wrapped with ++ OP_ONCE to make it atomic, so we must space in case this occurs. */ ++ ++ /* In fact, this can happen for a non-forward reference because ++ another group with the same number might be created later. This ++ issue is fixed "properly" in PCRE2. As PCRE1 is now in maintenance ++ only mode, we finesse the bug by allowing more memory always. */ ++ ++ /* if (recno == 0) */ *lengthptr += 2 + 2*LINK_SIZE; + } + + /* In the real compile, search the name table. We check the name +@@ -7247,6 +7276,7 @@ + { + if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; + previous = code; ++ item_hwm_offset = cd->hwm - cd->start_workspace; + *code++ = ((options & PCRE_CASELESS) != 0)? OP_DNREFI : OP_DNREF; + PUT2INC(code, 0, index); + PUT2INC(code, 0, count); +@@ -7360,6 +7390,7 @@ + HANDLE_RECURSION: + + previous = code; ++ item_hwm_offset = cd->hwm - cd->start_workspace; + called = cd->start_code; + + /* When we are actually compiling, find the bracket that is being +@@ -7561,7 +7592,11 @@ + previous = NULL; + cd->iscondassert = FALSE; + } +- else previous = code; ++ else ++ { ++ previous = code; ++ item_hwm_offset = cd->hwm - cd->start_workspace; ++ } + + *code = bravalue; + tempcode = code; +@@ -7809,7 +7844,7 @@ + const pcre_uchar *p; + pcre_uint32 cf; + +- save_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */ ++ item_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */ + terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)? + CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE; + +@@ -7877,6 +7912,7 @@ + HANDLE_REFERENCE: + if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; + previous = code; ++ item_hwm_offset = cd->hwm - cd->start_workspace; + *code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF; + PUT2INC(code, 0, recno); + cd->backref_map |= (recno < 32)? (1 << recno) : 1; +@@ -7906,6 +7942,7 @@ + if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr)) + goto FAILED; + previous = code; ++ item_hwm_offset = cd->hwm - cd->start_workspace; + *code++ = ((escape == ESC_p) != negated)? OP_PROP : OP_NOTPROP; + *code++ = ptype; + *code++ = pdata; +@@ -7946,6 +7983,7 @@ + + { + previous = (escape > ESC_b && escape < ESC_Z)? code : NULL; ++ item_hwm_offset = cd->hwm - cd->start_workspace; + *code++ = (!utf && escape == ESC_C)? OP_ALLANY : escape; + } + } +@@ -7989,6 +8027,7 @@ + + ONE_CHAR: + previous = code; ++ item_hwm_offset = cd->hwm - cd->start_workspace; + + /* For caseless UTF-8 mode when UCP support is available, check whether + this character has more than one other case. If so, generate a special diff --git a/libpcre/Pkgfile b/libpcre/Pkgfile index 3991f14..e9adc5c 100644 --- a/libpcre/Pkgfile +++ b/libpcre/Pkgfile @@ -5,9 +5,13 @@ # Depends on: name=libpcre -version=8.35 -release=1 -source=(ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-$version.tar.bz2) +version=8.37 +release=5 +source=(ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-$version.tar.bz2 + 01-seven-security-patches.patch \ + $name-$version-CVE-2015-5073.patch \ + $name-$version-CVE-2015-XXXX.patch) + build() { cd pcre-$version @@ -15,7 +19,6 @@ build() { ./configure --build=$CHOST \ --host=$CTARGET \ --prefix=/usr \ - --mandir=/usr/man \ --enable-utf8 \ --enable-unicode-properties \ --enable-jit @@ -27,6 +30,6 @@ build() { mv $PKG/usr/lib/libpcre.so.* $PKG/lib ln -sf ../../lib/$(readlink $PKG/usr/lib/libpcre.so) $PKG/usr/lib/libpcre.so - rm -r $PKG/usr/share - rm $PKG/usr/man/man3/{pcre{16,32}*,pcre_utf{16,32}*} + rm -r $PKG/usr/share/doc + rm $PKG/usr/share/man/man3/{pcre{16,32}*,pcre_utf{16,32}*} } diff --git a/libpcre/libpcre-8.37-CVE-2015-5073.patch b/libpcre/libpcre-8.37-CVE-2015-5073.patch new file mode 100644 index 0000000..a97ea39 --- /dev/null +++ b/libpcre/libpcre-8.37-CVE-2015-5073.patch @@ -0,0 +1,72 @@ +https://bugs.exim.org/show_bug.cgi?id=1651 +https://bugs.gentoo.org/553300 +https://bugzilla.redhat.com/1237224 + +From 354e1f8e921dcb9cf2f3a5eac93cd826d01a7d8a Mon Sep 17 00:00:00 2001 +From: ph10 +Date: Tue, 23 Jun 2015 16:34:53 +0000 +Subject: [PATCH] Fix buffer overflow for forward reference within backward + assertion with excess closing parenthesis. Bugzilla 1651. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is upstream commit ported to 8.37: + +commit 764692f9aea9eab50fdba6cb537441d8b34c6c37 +Author: ph10 +Date: Tue Jun 23 16:34:53 2015 +0000 + + Fix buffer overflow for forward reference within backward assertion with excess + closing parenthesis. Bugzilla 1651. + + git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1571 2f5784b3-3f2a-0410-8824-cb99058d5e15 + +It fixes CVE-2015-5073. + +Signed-off-by: Petr Písař +--- + pcre_compile.c | 2 +- + testdata/testinput2 | 2 ++ + testdata/testoutput2 | 3 +++ + 3 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/pcre_compile.c b/pcre_compile.c +index 6f06912..b66b1f6 100644 +--- a/pcre_compile.c ++++ b/pcre_compile.c +@@ -9392,7 +9392,7 @@ OP_RECURSE that are not fixed length get a diagnosic with a useful offset. The + exceptional ones forgo this. We scan the pattern to check that they are fixed + length, and set their lengths. */ + +-if (cd->check_lookbehind) ++if (errorcode == 0 && cd->check_lookbehind) + { + pcre_uchar *cc = (pcre_uchar *)codestart; + +diff --git a/testdata/testinput2 b/testdata/testinput2 +index 83bb471..5cc9ce6 100644 +--- a/testdata/testinput2 ++++ b/testdata/testinput2 +@@ -4154,4 +4154,6 @@ backtracking verbs. --/ + + "(?J)(?'d'(?'d'\g{d}))" + ++/(?=di(?<=(?1))|(?=(.))))/ ++ + /-- End of testinput2 --/ +diff --git a/testdata/testoutput2 b/testdata/testoutput2 +index 7dff52a..4decb8d 100644 +--- a/testdata/testoutput2 ++++ b/testdata/testoutput2 +@@ -14425,4 +14425,7 @@ Failed: lookbehind assertion is not fixed length at offset 17 + + "(?J)(?'d'(?'d'\g{d}))" + ++/(?=di(?<=(?1))|(?=(.))))/ ++Failed: unmatched parentheses at offset 23 ++ + /-- End of testinput2 --/ +-- +2.4.3 + diff --git a/libpcre/libpcre-8.37-CVE-2015-XXXX.patch b/libpcre/libpcre-8.37-CVE-2015-XXXX.patch new file mode 100644 index 0000000..71e9999 --- /dev/null +++ b/libpcre/libpcre-8.37-CVE-2015-XXXX.patch @@ -0,0 +1,170 @@ +commit 7af8e8717def179fd7b69e173abd347c1a3547cb +Author: ph10 +Date: Wed Aug 5 15:38:32 2015 +0000 + + Fix buffer overflow for named references in (?| situations. + + + git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1585 2f5784b3-3f2a-0410-8824-cb99058d5e15 + +diff --git a/pcre_compile.c b/pcre_compile.c +index 7d9f276..89ca8f1 100644 +--- a/pcre_compile.c ++++ b/pcre_compile.c +@@ -6668,6 +6668,7 @@ for (;; ptr++) + /* ------------------------------------------------------------ */ + case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */ + reset_bracount = TRUE; ++ cd->dupgroups = TRUE; /* Record (?| encountered */ + /* Fall through */ + + /* ------------------------------------------------------------ */ +@@ -7178,7 +7179,8 @@ for (;; ptr++) + if (lengthptr != NULL) + { + named_group *ng; +- ++ recno = 0; ++ + if (namelen == 0) + { + *errorcodeptr = ERR62; +@@ -7195,32 +7197,6 @@ for (;; ptr++) + goto FAILED; + } + +- /* The name table does not exist in the first pass; instead we must +- scan the list of names encountered so far in order to get the +- number. If the name is not found, set the value to 0 for a forward +- reference. */ +- +- recno = 0; +- ng = cd->named_groups; +- for (i = 0; i < cd->names_found; i++, ng++) +- { +- if (namelen == ng->length && +- STRNCMP_UC_UC(name, ng->name, namelen) == 0) +- { +- open_capitem *oc; +- recno = ng->number; +- if (is_recurse) break; +- for (oc = cd->open_caps; oc != NULL; oc = oc->next) +- { +- if (oc->number == recno) +- { +- oc->flag = TRUE; +- break; +- } +- } +- } +- } +- + /* Count named back references. */ + + if (!is_recurse) cd->namedrefcount++; +@@ -7242,7 +7218,44 @@ for (;; ptr++) + issue is fixed "properly" in PCRE2. As PCRE1 is now in maintenance + only mode, we finesse the bug by allowing more memory always. */ + +- /* if (recno == 0) */ *lengthptr += 2 + 2*LINK_SIZE; ++ *lengthptr += 2 + 2*LINK_SIZE; ++ ++ /* It is even worse than that. The current reference may be to an ++ existing named group with a different number (so apparently not ++ recursive) but which later on is also attached to a group with the ++ current number. This can only happen if $(| has been previous ++ encountered. In that case, we allow yet more memory, just in case. ++ (Again, this is fixed "properly" in PCRE2. */ ++ ++ if (cd->dupgroups) *lengthptr += 2 + 2*LINK_SIZE; ++ ++ /* Otherwise, check for recursion here. The name table does not exist ++ in the first pass; instead we must scan the list of names encountered ++ so far in order to get the number. If the name is not found, leave ++ the value of recno as 0 for a forward reference. */ ++ ++ else ++ { ++ ng = cd->named_groups; ++ for (i = 0; i < cd->names_found; i++, ng++) ++ { ++ if (namelen == ng->length && ++ STRNCMP_UC_UC(name, ng->name, namelen) == 0) ++ { ++ open_capitem *oc; ++ recno = ng->number; ++ if (is_recurse) break; ++ for (oc = cd->open_caps; oc != NULL; oc = oc->next) ++ { ++ if (oc->number == recno) ++ { ++ oc->flag = TRUE; ++ break; ++ } ++ } ++ } ++ } ++ } + } + + /* In the real compile, search the name table. We check the name +@@ -7289,8 +7302,6 @@ for (;; ptr++) + for (i++; i < cd->names_found; i++) + { + if (STRCMP_UC_UC(slot + IMM2_SIZE, cslot + IMM2_SIZE) != 0) break; +- +- + count++; + cslot += cd->name_entry_size; + } +@@ -9239,6 +9250,7 @@ cd->names_found = 0; + cd->name_entry_size = 0; + cd->name_table = NULL; + cd->dupnames = FALSE; ++cd->dupgroups = FALSE; + cd->namedrefcount = 0; + cd->start_code = cworkspace; + cd->hwm = cworkspace; +@@ -9273,7 +9285,7 @@ if (errorcode != 0) goto PCRE_EARLY_ERROR_RETURN; + + DPRINTF(("end pre-compile: length=%d workspace=%d\n", length, + (int)(cd->hwm - cworkspace))); +- ++ + if (length > MAX_PATTERN_SIZE) + { + errorcode = ERR20; +diff --git a/pcre_internal.h b/pcre_internal.h +index 80e2420..544d9c0 100644 +--- a/pcre_internal.h ++++ b/pcre_internal.h +@@ -2454,6 +2454,7 @@ typedef struct compile_data { + BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */ + BOOL check_lookbehind; /* Lookbehinds need later checking */ + BOOL dupnames; /* Duplicate names exist */ ++ BOOL dupgroups; /* Duplicate groups exist: (?| found */ + BOOL iscondassert; /* Next assert is a condition */ + int nltype; /* Newline type */ + int nllen; /* Newline string length */ +diff --git a/testdata/testinput2 b/testdata/testinput2 +index df2c1cc..e119bd9 100644 +--- a/testdata/testinput2 ++++ b/testdata/testinput2 +@@ -4194,4 +4194,6 @@ backtracking verbs. --/ + + /(?1){3918}(((((0(\k'R'))))(?J)(?'R'(?'R'\3){99})))/I + ++/(?J:(?|(:(?|(?'R')(\k'R')|((?'R')))H'Rk'Rf)|s(?'R')))/ ++ + /-- End of testinput2 --/ +diff --git a/testdata/testoutput2 b/testdata/testoutput2 +index d3fc254..54db2cc 100644 +--- a/testdata/testoutput2 ++++ b/testdata/testoutput2 +@@ -14537,4 +14537,6 @@ Duplicate name status changes + No first char + Need char = '0' + ++/(?J:(?|(:(?|(?'R')(\k'R')|((?'R')))H'Rk'Rf)|s(?'R')))/ ++ + /-- End of testinput2 --/ -- 2.26.2