ppisar pushed to pcre (master). "Fix computing size of JIT read-only data"

notifications at fedoraproject.org notifications at fedoraproject.org
Thu Mar 26 12:10:30 UTC 2015


>From 32c1b38f772c33ffc7a0e4885ee746c280f6659e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar at redhat.com>
Date: Thu, 26 Mar 2015 10:58:22 +0100
Subject: Fix computing size of JIT read-only data


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?= <ppisar at redhat.com>
+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 <zherczeg at 2f5784b3-3f2a-0410-8824-cb99058d5e15>
+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.
+
+<http://bugs.exim.org/show_bug.cgi?id=1597>
+
+Signed-off-by: Petr Písař <ppisar at redhat.com>
+---
+ 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 <ppisar at redhat.com> - 8.36-4
+- Fix computing size of JIT read-only data (bug #1206131)
+
 * Thu Feb 19 2015 David Tardon <dtardon at redhat.com> - 8.36-3.1
 - rebuild for C++ stdlib API changes in gcc5
 
-- 
cgit v0.10.2


	http://pkgs.fedoraproject.org/cgit/pcre.git/commit/?h=master&id=32c1b38f772c33ffc7a0e4885ee746c280f6659e


More information about the scm-commits mailing list