CRUX-ARM : Home

Home :: Documentation :: Download :: Development :: Community :: Ports :: Packages :: Bugs :: Links :: About :: Donors
libpcre: updated to 8.37
authorVictor Martinez <pitillo@ono.com>
Thu, 12 Nov 2015 12:24:15 +0000 (12:24 +0000)
committerVictor Martinez <pitillo@ono.com>
Thu, 12 Nov 2015 12:24:15 +0000 (12:24 +0000)
libpcre/.footprint
libpcre/.md5sum
libpcre/01-seven-security-patches.patch [new file with mode: 0644]
libpcre/Pkgfile
libpcre/libpcre-8.37-CVE-2015-5073.patch [new file with mode: 0644]
libpcre/libpcre-8.37-CVE-2015-XXXX.patch [new file with mode: 0644]

index dc3ea5bacaa9fd2045898cee37ed95a4bd9059f2..70497da8afce21b3bd6816acd7c2be35341f3369 100644 (file)
@@ -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
index 953c4f366ade59f6e8e7e3f3f355a69663d166a8..d8ed8f55dbafc3cfc38e0c4ee0779c9e04bc9086 100644 (file)
@@ -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 (file)
index 0000000..f5705e6
--- /dev/null
@@ -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^($(?<! )(\xa9H4){4}h}1)B))\x15')"
++
++"(?J:(?|(?'R')(\k'R')|((?'R'))))"
++
+ /-- End of testinput2 --/
+Index: pcre/testdata/testoutput11-16
+===================================================================
+--- pcre/testdata/testoutput11-16      (revision 1553)
++++ pcre/testdata/testoutput11-16      (working copy)
+@@ -231,7 +231,7 @@
+ ------------------------------------------------------------------
+ /(?P<a>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 @@
+ ------------------------------------------------------------------
+ /(?P<a>a)...(?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^($(?<! )(\xa9H4){4}h}1)B))\x15')"
++
++"(?J:(?|(?'R')(\k'R')|((?'R'))))"
++
+ /-- End of testinput2 --/
+Index: pcre/testdata/testoutput11-32
+===================================================================
+--- pcre/testdata/testoutput11-32      (revision 1553)
++++ pcre/testdata/testoutput11-32      (working copy)
+@@ -231,7 +231,7 @@
+ ------------------------------------------------------------------
+ /(?P<a>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
index 3991f143862d608fed0edd9cadb049b60981ce69..e9adc5ce295386ba0644d7f8b8b4da3861188f05 100644 (file)
@@ -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 (file)
index 0000000..a97ea39
--- /dev/null
@@ -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 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+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 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+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ř <ppisar@redhat.com>
+---
+ 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 (file)
index 0000000..71e9999
--- /dev/null
@@ -0,0 +1,170 @@
+commit 7af8e8717def179fd7b69e173abd347c1a3547cb
+Author: ph10 <ph10@2f5784b3-3f2a-0410-8824-cb99058d5e15>
+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 --/