diff --git a/pcre-8.36-Remove-computing-the-JIT-read-only-data-size-in-adva.patch b/pcre-8.36-Remove-computing-the-JIT-read-only-data-size-in-adva.patch new file mode 100644 index 0000000..4f49b2e --- /dev/null +++ b/pcre-8.36-Remove-computing-the-JIT-read-only-data-size-in-adva.patch @@ -0,0 +1,366 @@ +From acfc48addb7b4fc73985f9f236fbb7e12e2388ef Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= +Date: Thu, 26 Mar 2015 10:55:42 +0100 +Subject: [PATCH] Remove computing the JIT read-only data size in advance and + use on-demand memory allocation. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Upstream commit: + +commit 3831a81914cf11565bf429dd019c9442b404bc5f +Author: zherczeg +Date: Thu Mar 5 08:53:37 2015 +0000 + + Remove computing the JIT read-only data size in advance and use on-demand memory allocation. + + git-svn-id: svn://vcs.exim.org/pcre/code/trunk@1530 2f5784b3-3f2a-0410-8824-cb99058d5e15 + +ported to 8.36. + + + +Signed-off-by: Petr Písař +--- + pcre_jit_compile.c | 123 ++++++++++++++++++---------------------------- + sljit/sljitLir.h | 6 +++ + sljit/sljitNativeARM_32.c | 4 +- + testdata/testinput12 | 8 +++ + testdata/testoutput12 | 8 +++ + 5 files changed, 74 insertions(+), 75 deletions(-) + +diff --git a/pcre_jit_compile.c b/pcre_jit_compile.c +index 256e3a4..53049fe 100644 +--- a/pcre_jit_compile.c ++++ b/pcre_jit_compile.c +@@ -179,7 +179,7 @@ typedef struct jit_arguments { + + typedef struct executable_functions { + void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES]; +- sljit_uw *read_only_data[JIT_NUMBER_OF_COMPILE_MODES]; ++ void *read_only_data_heads[JIT_NUMBER_OF_COMPILE_MODES]; + sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES]; + PUBL(jit_callback) callback; + void *userdata; +@@ -322,14 +322,10 @@ typedef struct compiler_common { + pcre_uchar *start; + /* Maps private data offset to each opcode. */ + sljit_si *private_data_ptrs; +- /* This read-only data is available during runtime. */ +- sljit_uw *read_only_data; +- /* The total size of the read-only data. */ +- sljit_uw read_only_data_size; +- /* The next free entry of the read_only_data. */ +- sljit_uw *read_only_data_ptr; + /* Tells whether the capturing bracket is optimized. */ + pcre_uint8 *optimized_cbracket; ++ /* Chain list of read-only data ptrs. */ ++ void *read_only_data_head; + /* Tells whether the starting offset is a target of then. */ + pcre_uint8 *then_offsets; + /* Current position where a THEN must jump. */ +@@ -802,16 +798,6 @@ while (cc < ccend) + cc += 1 + IMM2_SIZE; + break; + +- case OP_BRA: +- case OP_CBRA: +- case OP_SBRA: +- case OP_SCBRA: +- count = no_alternatives(cc); +- if (count > 4) +- common->read_only_data_size += count * sizeof(sljit_uw); +- cc += 1 + LINK_SIZE + (*cc == OP_CBRA || *cc == OP_SCBRA ? IMM2_SIZE : 0); +- break; +- + case OP_CBRAPOS: + case OP_SCBRAPOS: + common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0; +@@ -2114,6 +2100,38 @@ DEFINE_COMPILER; + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw)); + } + ++static sljit_uw * allocate_read_only_data(compiler_common *common, sljit_uw size) ++{ ++DEFINE_COMPILER; ++sljit_uw *result; ++ ++if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) ++ return NULL; ++ ++result = (sljit_uw *)SLJIT_MALLOC(size + sizeof(sljit_uw)); ++if (SLJIT_UNLIKELY(result == NULL)) ++ { ++ sljit_set_compiler_memory_error(compiler); ++ return NULL; ++ } ++ ++*(void**)result = common->read_only_data_head; ++common->read_only_data_head = (void *)result; ++return result + 1; ++} ++ ++static void free_read_only_data(void *current) ++{ ++void *next; ++ ++while (current != NULL) ++ { ++ next = *(void**)current; ++ SLJIT_FREE(current); ++ current = next; ++ } ++} ++ + static SLJIT_INLINE void reset_ovector(compiler_common *common, int length) + { + DEFINE_COMPILER; +@@ -3530,9 +3548,6 @@ int range_right = -1, range_len = 3 - 1; + sljit_ub *update_table = NULL; + BOOL in_range; + +-/* This is even TRUE, if both are NULL. */ +-SLJIT_ASSERT(common->read_only_data_ptr == common->read_only_data); +- + for (i = 0; i < MAX_N_CHARS; i++) + { + chars[i << 1] = NOTACHAR; +@@ -3581,18 +3596,9 @@ for (i = 0; i <= max; i++) + + if (range_right >= 0) + { +- /* Since no data is consumed (see the assert in the beginning +- of this function), this space can be reallocated. */ +- if (common->read_only_data) +- SLJIT_FREE(common->read_only_data); +- +- common->read_only_data_size += 256; +- common->read_only_data = (sljit_uw *)SLJIT_MALLOC(common->read_only_data_size); +- if (common->read_only_data == NULL) ++ update_table = (sljit_ub *)allocate_read_only_data(common, 256); ++ if (update_table == NULL) + return TRUE; +- +- update_table = (sljit_ub *)common->read_only_data; +- common->read_only_data_ptr = (sljit_uw *)(update_table + 256); + memset(update_table, IN_UCHARS(range_len), 256); + + for (i = 0; i < range_len; i++) +@@ -8982,8 +8988,9 @@ else if (has_alternatives) + if (alt_max > 4) + { + /* Table jump if alt_max is greater than 4. */ +- next_update_addr = common->read_only_data_ptr; +- common->read_only_data_ptr += alt_max; ++ next_update_addr = allocate_read_only_data(common, alt_max * sizeof(sljit_uw)); ++ if (SLJIT_UNLIKELY(next_update_addr == NULL)) ++ return; + sljit_emit_ijump(compiler, SLJIT_JUMP, SLJIT_MEM1(TMP1), (sljit_sw)next_update_addr); + add_label_addr(common, next_update_addr++); + } +@@ -9766,9 +9773,7 @@ memset(common, 0, sizeof(compiler_common)); + rootbacktrack.cc = (pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size; + + common->start = rootbacktrack.cc; +-common->read_only_data = NULL; +-common->read_only_data_size = 0; +-common->read_only_data_ptr = NULL; ++common->read_only_data_head = NULL; + common->fcc = tables + fcc_offset; + common->lcc = (sljit_sw)(tables + lcc_offset); + common->mode = mode; +@@ -9951,25 +9956,11 @@ if (common->has_then) + set_then_offsets(common, common->start, NULL); + } + +-if (common->read_only_data_size > 0) +- { +- common->read_only_data = (sljit_uw *)SLJIT_MALLOC(common->read_only_data_size); +- if (common->read_only_data == NULL) +- { +- SLJIT_FREE(common->optimized_cbracket); +- SLJIT_FREE(common->private_data_ptrs); +- return; +- } +- common->read_only_data_ptr = common->read_only_data; +- } +- + compiler = sljit_create_compiler(); + if (!compiler) + { + SLJIT_FREE(common->optimized_cbracket); + SLJIT_FREE(common->private_data_ptrs); +- if (common->read_only_data) +- SLJIT_FREE(common->read_only_data); + return; + } + common->compiler = compiler; +@@ -10008,16 +9999,7 @@ if ((re->options & PCRE_ANCHORED) == 0) + if ((re->options & PCRE_NO_START_OPTIMIZE) == 0) + { + if (mode == JIT_COMPILE && fast_forward_first_n_chars(common, (re->options & PCRE_FIRSTLINE) != 0)) +- { +- /* If read_only_data is reallocated, we might have an allocation failure. */ +- if (common->read_only_data_size > 0 && common->read_only_data == NULL) +- { +- sljit_free_compiler(compiler); +- SLJIT_FREE(common->optimized_cbracket); +- SLJIT_FREE(common->private_data_ptrs); +- return; +- } +- } ++ ; + else if ((re->flags & PCRE_FIRSTSET) != 0) + fast_forward_first_char(common, (pcre_uchar)re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0, (re->options & PCRE_FIRSTLINE) != 0); + else if ((re->flags & PCRE_STARTLINE) != 0) +@@ -10070,8 +10052,7 @@ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + sljit_free_compiler(compiler); + SLJIT_FREE(common->optimized_cbracket); + SLJIT_FREE(common->private_data_ptrs); +- if (common->read_only_data) +- SLJIT_FREE(common->read_only_data); ++ free_read_only_data(common->read_only_data_head); + return; + } + +@@ -10111,8 +10092,7 @@ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + sljit_free_compiler(compiler); + SLJIT_FREE(common->optimized_cbracket); + SLJIT_FREE(common->private_data_ptrs); +- if (common->read_only_data) +- SLJIT_FREE(common->read_only_data); ++ free_read_only_data(common->read_only_data_head); + return; + } + +@@ -10192,8 +10172,7 @@ while (common->currententry != NULL) + sljit_free_compiler(compiler); + SLJIT_FREE(common->optimized_cbracket); + SLJIT_FREE(common->private_data_ptrs); +- if (common->read_only_data) +- SLJIT_FREE(common->read_only_data); ++ free_read_only_data(common->read_only_data_head); + return; + } + flush_stubs(common); +@@ -10303,7 +10282,6 @@ if (common->getucd != NULL) + } + #endif + +-SLJIT_ASSERT(common->read_only_data + (common->read_only_data_size >> SLJIT_WORD_SHIFT) == common->read_only_data_ptr); + SLJIT_FREE(common->optimized_cbracket); + SLJIT_FREE(common->private_data_ptrs); + +@@ -10318,8 +10296,7 @@ while (label_addr != NULL) + sljit_free_compiler(compiler); + if (executable_func == NULL) + { +- if (common->read_only_data) +- SLJIT_FREE(common->read_only_data); ++ free_read_only_data(common->read_only_data_head); + return; + } + +@@ -10343,8 +10320,7 @@ else + /* This case is highly unlikely since we just recently + freed a lot of memory. Not impossible though. */ + sljit_free_code(executable_func); +- if (common->read_only_data) +- SLJIT_FREE(common->read_only_data); ++ free_read_only_data(common->read_only_data_head); + return; + } + memset(functions, 0, sizeof(executable_functions)); +@@ -10355,7 +10331,7 @@ else + } + + functions->executable_funcs[mode] = executable_func; +-functions->read_only_data[mode] = common->read_only_data; ++functions->read_only_data_heads[mode] = common->read_only_data_head; + functions->executable_sizes[mode] = executable_size; + } + +@@ -10542,8 +10518,7 @@ for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++) + { + if (functions->executable_funcs[i] != NULL) + sljit_free_code(functions->executable_funcs[i]); +- if (functions->read_only_data[i] != NULL) +- SLJIT_FREE(functions->read_only_data[i]); ++ free_read_only_data(functions->read_only_data_heads[i]); + } + SLJIT_FREE(functions); + } +diff --git a/sljit/sljitLir.h b/sljit/sljitLir.h +index 9718871..2e135e2 100644 +--- a/sljit/sljitLir.h ++++ b/sljit/sljitLir.h +@@ -419,6 +419,12 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compile + these checks increases the performance of the compiling process. */ + static SLJIT_INLINE sljit_si sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; } + ++/* Sets the compiler error code to SLJIT_ERR_ALLOC_FAILED. After ++ the error code is set, the compiler behaves as if itself detected ++ an allocation failure. This can greatly simplify error management, ++ since only the compiler needs to be checked after compilation. */ ++static SLJIT_INLINE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler) { compiler->error = SLJIT_ERR_ALLOC_FAILED; } ++ + /* + Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit, + and <= 128 bytes on 64 bit architectures. The memory area is owned by the +diff --git a/sljit/sljitNativeARM_32.c b/sljit/sljitNativeARM_32.c +index 0998423..44b539c 100644 +--- a/sljit/sljitNativeARM_32.c ++++ b/sljit/sljitNativeARM_32.c +@@ -315,11 +315,13 @@ struct future_patch { + sljit_si value; + }; + +-static SLJIT_INLINE sljit_si resolve_const_pool_index(struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr) ++static sljit_si resolve_const_pool_index(struct sljit_compiler *compiler, struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr) + { + sljit_si value; + struct future_patch *curr_patch, *prev_patch; + ++ SLJIT_UNUSED_ARG(compiler); ++ + /* Using the values generated by patch_pc_relative_loads. */ + if (!*first_patch) + value = (sljit_si)cpool_start_address[cpool_current_index]; +diff --git a/testdata/testinput12 b/testdata/testinput12 +index 5d727af..d68551f 100644 +--- a/testdata/testinput12 ++++ b/testdata/testinput12 +@@ -87,4 +87,12 @@ and a couple of things that are different with JIT. --/ + /^12345678abcd/mS++ + 12345678abcd + ++/-- Test pattern compilation --/ ++ ++/(?:a|b|c|d|e)(?R)/S++ ++ ++/(?:a|b|c|d|e)(?R)(?R)/S++ ++ ++/(a(?:a|b|c|d|e)b){8,16}/S++ ++ + /-- End of testinput12 --/ +diff --git a/testdata/testoutput12 b/testdata/testoutput12 +index 67ad2c8..7a1cf69 100644 +--- a/testdata/testoutput12 ++++ b/testdata/testoutput12 +@@ -176,4 +176,12 @@ No match, mark = m (JIT) + 12345678abcd + 0: 12345678abcd (JIT) + ++/-- Test pattern compilation --/ ++ ++/(?:a|b|c|d|e)(?R)/S++ ++ ++/(?:a|b|c|d|e)(?R)(?R)/S++ ++ ++/(a(?:a|b|c|d|e)b){8,16}/S++ ++ + /-- End of testinput12 --/ +-- +2.1.0 + diff --git a/pcre.spec b/pcre.spec index 77ff169..5948974 100644 --- a/pcre.spec +++ b/pcre.spec @@ -2,7 +2,7 @@ #%%global rcversion RC1 Name: pcre Version: 8.36 -Release: %{?rcversion:0.}3%{?rcversion:.%rcversion}%{?dist}.1 +Release: %{?rcversion:0.}4%{?rcversion:.%rcversion}%{?dist} %global myversion %{version}%{?rcversion:-%rcversion} Summary: Perl-compatible regular expression library Group: System Environment/Libraries @@ -19,6 +19,9 @@ Patch2: pcre-8.36-Fix-bug-when-there-are-unset-groups-prior-to-ACCEPT-.patch # Fix unused memory usage on zero-repeat assertion condition, bug #1165626, # CVE-2014-8964, in upstream after 8.36 Patch3: pcre-8.36-Fix-zero-repeat-assertion-condition-bug.patch +# Fix computing size of JIT read-only data, bug #1206131, upstream bug #1597, +# in upstream after 8.36 +Patch4: pcre-8.36-Remove-computing-the-JIT-read-only-data-size-in-adva.patch BuildRequires: readline-devel # New libtool to get rid of rpath BuildRequires: autoconf, automake, libtool @@ -62,6 +65,7 @@ Utilities demonstrating PCRE capabilities like pcregrep or pcretest. %patch1 -p1 -b .terminated_typos %patch2 -p1 -b .reset_groups %patch3 -p1 -b .zero_repeat_assertion +%patch4 -p1 -b .jit_size # Because of rpath patch libtoolize --copy --force && autoreconf -vif # One contributor's name is non-UTF-8 @@ -132,6 +136,9 @@ make %{?_smp_mflags} check VERBOSE=yes %{_mandir}/man1/pcretest.* %changelog +* Thu Mar 26 2015 Petr Pisar - 8.36-4 +- Fix computing size of JIT read-only data (bug #1206131) + * Thu Feb 19 2015 David Tardon - 8.36-3.1 - rebuild for C++ stdlib API changes in gcc5