bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

regex patch to catch some size-overflow bugs


From: Paul Eggert
Subject: regex patch to catch some size-overflow bugs
Date: Fri, 02 Sep 2005 15:57:49 -0700
User-agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux)

And now, for the regex patch that I wanted to install originally!
Most of the other regex patches were in preparation for this one.
This patch duplicates some of the ideas from the xmalloc module,
but I judged that better than trying to get the glibc folks to
adopt xmalloc.

The regex code currently misbehaves badly if there's an arithmetic
overflow when calculating sizes, e.g., when doubling buffer sizes.
I installed this patch into gnulib and filed glibc bug 1291.

2005-09-02  Paul Eggert  <address@hidden>

        Check for arithmetic overflow when calculating sizes, to prevent
        some buffer-overflow issues.  These patches are conservative, in the
        sense that when I couldn't determine whether an overflow was possible,
        I inserted a run-time check.
        * regex_internal.h (re_xmalloc, re_xrealloc, re_x2realloc): New macros.
        (SIZE_MAX) [!defined SIZE_MAX]: New macro.
        (re_alloc_oversized, re_x2alloc_oversized, re_xnmalloc):
        (re_xnrealloc, re_x2nrealloc): New inline functions.
        * lib/regcomp.c (init_dfa, analyze, build_range_exp, parse_bracket_exp):
        (build_equiv_class, build_charclass): Check for arithmetic overflow
        in size expression calculations.
        * lib/regex_internal.c (re_string_realloc_buffers):
        (build_wcs_upper_buffer, re_node_set_add_intersect):
        (re_node_set_init_union, re_node_set_insert, re_node_set_insert_last):
        (re_dfa_add_node, register_state): Likewise.
        * lib/regexec.c (re_search_stub, re_copy_regs, re_search_internal):
        (prune_impossible_nodes, push_fail_stack, set_regs, check_arrival):
        (build_trtable, extend_buffers, match_ctx_init, match_ctx_add_entry):
        (match_ctx_add_subtop, match_ctx_add_sublast): Likewise.

--- lib/regex_internal.h        1 Sep 2005 19:41:07 -0000       1.11
+++ lib/regex_internal.h        2 Sep 2005 22:39:27 -0000
@@ -442,9 +442,69 @@ static unsigned int re_string_context_at
 #endif
 
 #define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t)))
+#define re_xmalloc(t,n) ((t *) re_xnmalloc (n, sizeof (t)))
 #define re_calloc(t,n) ((t *) calloc (n, sizeof (t)))
 #define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t)))
+#define re_xrealloc(p,t,n) ((t *) re_xnrealloc (p, n, sizeof (t)))
+#define re_x2realloc(p,t,pn) ((t *) re_x2nrealloc (p, pn, sizeof (t)))
 #define re_free(p) free (p)
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+/* Return true if an array of N objects, each of size S, cannot exist
+   due to size arithmetic overflow.  S must be nonzero.  */
+static inline bool
+re_alloc_oversized (size_t n, size_t s)
+{
+  return BE (SIZE_MAX / s < n, 0);
+}
+
+/* Return true if an array of (2 * N + 1) objects, each of size S,
+   cannot exist due to size arithmetic overflow.  S must be nonzero.  */
+static inline bool
+re_x2alloc_oversized (size_t n, size_t s)
+{
+  return BE ((SIZE_MAX / s - 1) / 2 < n, 0);
+}
+
+/* Allocate an array of N objects, each with S bytes of memory,
+   dynamically, with error checking.  S must be nonzero.  */
+static inline void *
+re_xnmalloc (size_t n, size_t s)
+{
+  return re_alloc_oversized (n, s) ? NULL : malloc (n * s);
+}
+
+/* Change the size of an allocated block of memory P to an array of N
+   objects each of S bytes, with error checking.  S must be nonzero.  */
+static inline void *
+re_xnrealloc (void *p, size_t n, size_t s)
+{
+  return re_alloc_oversized (n, s) ? NULL : realloc (p, n * s);
+}
+
+/* Reallocate a block of memory P to an array of (2 * (*PN) + 1)
+   objects each of S bytes, with error checking.  S must be nonzero.
+   If the allocation is successful, set *PN to the new allocation
+   count and return the resulting pointer.  Otherwise, return
+   NULL.  */
+static inline void *
+re_x2nrealloc (void *p, size_t *pn, size_t s)
+{
+  if (re_x2alloc_oversized (*pn, s))
+    return NULL;
+  else
+    {
+      /* Add 1 in case *PN is zero.  */
+      size_t n1 = 2 * *pn + 1;
+      p = realloc (p, n1 * s);
+      if (BE (p != NULL, 1))
+       *pn = n1;
+      return p;
+    }
+}
 
 struct bin_tree_t
 {
--- lib/regcomp.c       1 Sep 2005 19:41:07 -0000       1.15
+++ lib/regcomp.c       2 Sep 2005 22:39:28 -0000
@@ -808,7 +808,7 @@ init_dfa (re_dfa_t *dfa, Idx pat_len)
   dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
 
   dfa->nodes_alloc = pat_len + 1;
-  dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc);
+  dfa->nodes = re_xmalloc (re_token_t, dfa->nodes_alloc);
 
   /*  table_size = 2 ^ ceil(log pat_len) */
   for (table_size = 1; table_size <= pat_len; table_size <<= 1)
@@ -1083,13 +1083,13 @@ analyze (regex_t *preg)
   /* Allocate arrays.  */
   dfa->nexts = re_malloc (Idx, dfa->nodes_alloc);
   dfa->org_indices = re_malloc (Idx, dfa->nodes_alloc);
-  dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc);
+  dfa->edests = re_xmalloc (re_node_set, dfa->nodes_alloc);
   dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc);
   if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL
          || dfa->eclosures == NULL, 0))
     return REG_ESPACE;
 
-  dfa->subexp_map = re_malloc (Idx, preg->re_nsub);
+  dfa->subexp_map = re_xmalloc (Idx, preg->re_nsub);
   if (dfa->subexp_map != NULL)
     {
       Idx i;
@@ -1125,7 +1125,7 @@ analyze (regex_t *preg)
   if ((!preg->re_no_sub && preg->re_nsub > 0 && dfa->has_plural_match)
       || dfa->nbackref)
     {
-      dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len);
+      dfa->inveclosures = re_xmalloc (re_node_set, dfa->nodes_len);
       if (BE (dfa->inveclosures == NULL, 0))
         return REG_ESPACE;
       ret = calc_inveclosure (dfa);
@@ -2608,12 +2608,11 @@ build_range_exp (re_bitset_ptr_t sbcset,
            wchar_t *new_array_start, *new_array_end;
            Idx new_nranges;
 
-           /* +1 in case of mbcset->nranges is 0.  */
-           new_nranges = 2 * mbcset->nranges + 1;
+           new_nranges = mbcset->nranges;
            /* Use realloc since mbcset->range_starts and mbcset->range_ends
               are NULL if *range_alloc == 0.  */
-           new_array_start = re_realloc (mbcset->range_starts, wchar_t,
-                                         new_nranges);
+           new_array_start = re_x2realloc (mbcset->range_starts, wchar_t,
+                                           &new_nranges);
            new_array_end = re_realloc (mbcset->range_ends, wchar_t,
                                        new_nranges);
 
@@ -2840,10 +2839,9 @@ parse_bracket_exp (re_string_t *regexp, 
              uint32_t *new_array_end;
              Idx new_nranges;
 
-             /* +1 in case of mbcset->nranges is 0.  */
-             new_nranges = 2 * mbcset->nranges + 1;
-             new_array_start = re_realloc (mbcset->range_starts, uint32_t,
-                                           new_nranges);
+             new_nranges = mbcset->nranges;
+             new_array_start = re_x2realloc (mbcset->range_starts, uint32_t,
+                                             &new_nranges);
              new_array_end = re_realloc (mbcset->range_ends, uint32_t,
                                          new_nranges);
 
@@ -2914,12 +2912,11 @@ parse_bracket_exp (re_string_t *regexp, 
          if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0))
            {
              /* Not enough, realloc it.  */
-             /* +1 in case of mbcset->ncoll_syms is 0.  */
-             Idx new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1;
+             Idx new_coll_sym_alloc = mbcset->ncoll_syms;
              /* Use realloc since mbcset->coll_syms is NULL
                 if *alloc == 0.  */
-             int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t,
-                                                  new_coll_sym_alloc);
+             int32_t *new_coll_syms = re_x2realloc (mbcset->coll_syms, int32_t,
+                                                    &new_coll_sym_alloc);
              if (BE (new_coll_syms == NULL, 0))
                return REG_ESPACE;
              mbcset->coll_syms = new_coll_syms;
@@ -3103,11 +3100,10 @@ parse_bracket_exp (re_string_t *regexp, 
                {
                  wchar_t *new_mbchars;
                  /* Not enough, realloc it.  */
-                 /* +1 in case of mbcset->nmbchars is 0.  */
-                 mbchar_alloc = 2 * mbcset->nmbchars + 1;
+                 mbchar_alloc = mbcset->nmbchars;
                  /* Use realloc since array is NULL if *alloc == 0.  */
-                 new_mbchars = re_realloc (mbcset->mbchars, wchar_t,
-                                           mbchar_alloc);
+                 new_mbchars = re_x2realloc (mbcset->mbchars, wchar_t,
+                                             &mbchar_alloc);
                  if (BE (new_mbchars == NULL, 0))
                    goto parse_bracket_exp_espace;
                  mbcset->mbchars = new_mbchars;
@@ -3381,12 +3377,11 @@ build_equiv_class (re_bitset_ptr_t sbcse
       if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0))
        {
          /* Not enough, realloc it.  */
-         /* +1 in case of mbcset->nequiv_classes is 0.  */
-         Idx new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1;
+         Idx new_equiv_class_alloc = mbcset->nequiv_classes;
          /* Use realloc since the array is NULL if *alloc == 0.  */
-         int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes,
-                                                  int32_t,
-                                                  new_equiv_class_alloc);
+         int32_t *new_equiv_classes = re_x2realloc (mbcset->equiv_classes,
+                                                    int32_t,
+                                                    &new_equiv_class_alloc);
          if (BE (new_equiv_classes == NULL, 0))
            return REG_ESPACE;
          mbcset->equiv_classes = new_equiv_classes;
@@ -3431,11 +3426,10 @@ build_charclass (unsigned REG_TRANSLATE_
   if (BE (*char_class_alloc == mbcset->nchar_classes, 0))
     {
       /* Not enough, realloc it.  */
-      /* +1 in case of mbcset->nchar_classes is 0.  */
-      Idx new_char_class_alloc = 2 * mbcset->nchar_classes + 1;
+      Idx new_char_class_alloc = mbcset->nchar_classes;
       /* Use realloc since array is NULL if *alloc == 0.  */
-      wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t,
-                                              new_char_class_alloc);
+      wctype_t *new_char_classes = re_x2realloc (mbcset->char_classes, 
wctype_t,
+                                                &new_char_class_alloc);
       if (BE (new_char_classes == NULL, 0))
        return REG_ESPACE;
       mbcset->char_classes = new_char_classes;
--- lib/regex_internal.c        1 Sep 2005 22:10:59 -0000       1.15
+++ lib/regex_internal.c        2 Sep 2005 22:39:28 -0000
@@ -132,13 +132,13 @@ re_string_realloc_buffers (re_string_t *
 #ifdef RE_ENABLE_I18N
   if (pstr->mb_cur_max > 1)
     {
-      wint_t *new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len);
+      wint_t *new_wcs = re_xrealloc (pstr->wcs, wint_t, new_buf_len);
       if (BE (new_wcs == NULL, 0))
        return REG_ESPACE;
       pstr->wcs = new_wcs;
       if (pstr->offsets != NULL)
        {
-         Idx *new_offsets = re_realloc (pstr->offsets, Idx, new_buf_len);
+         Idx *new_offsets = re_xrealloc (pstr->offsets, Idx, new_buf_len);
          if (BE (new_offsets == NULL, 0))
            return REG_ESPACE;
          pstr->offsets = new_offsets;
@@ -392,7 +392,7 @@ build_wcs_upper_buffer (re_string_t *pst
 
                    if (pstr->offsets == NULL)
                      {
-                       pstr->offsets = re_malloc (Idx, pstr->bufs_len);
+                       pstr->offsets = re_xmalloc (Idx, pstr->bufs_len);
 
                        if (pstr->offsets == NULL)
                          return REG_ESPACE;
@@ -873,7 +873,7 @@ re_node_set_alloc (re_node_set *set, Idx
 {
   set->alloc = size;
   set->nelem = 0;
-  set->elems = re_malloc (Idx, size);
+  set->elems = re_xmalloc (Idx, size);
   if (BE (set->elems == NULL, 0))
     return REG_ESPACE;
   return REG_NOERROR;
@@ -964,7 +964,12 @@ re_node_set_add_intersect (re_node_set *
   if (src1->nelem + src2->nelem + dest->nelem > dest->alloc)
     {
       Idx new_alloc = src1->nelem + src2->nelem + dest->alloc;
-      Idx *new_elems = re_realloc (dest->elems, Idx, new_alloc);
+      Idx *new_elems;
+      if (sizeof (Idx) < 3
+         && (new_alloc < dest->alloc
+             || ((Idx) (src1->nelem + src2->nelem) < src1->nelem)))
+       return REG_ESPACE;
+      new_elems = re_xrealloc (dest->elems, Idx, new_alloc);
       if (BE (new_elems == NULL, 0))
         return REG_ESPACE;
       dest->elems = new_elems;
@@ -1050,7 +1055,9 @@ re_node_set_init_union (re_node_set *des
   if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0)
     {
       dest->alloc = src1->nelem + src2->nelem;
-      dest->elems = re_malloc (Idx, dest->alloc);
+      if (sizeof (Idx) < 2 && dest->alloc < src1->nelem)
+       return REG_ESPACE;
+      dest->elems = re_xmalloc (Idx, dest->alloc);
       if (BE (dest->elems == NULL, 0))
        return REG_ESPACE;
     }
@@ -1101,10 +1108,17 @@ re_node_set_merge (re_node_set *dest, co
   Idx is, id, sbase, delta;
   if (src == NULL || src->nelem == 0)
     return REG_NOERROR;
+  if (sizeof (Idx) < 3
+      && ((Idx) (2 * src->nelem) < src->nelem
+         || (Idx) (2 * src->nelem + dest->nelem) < dest->nelem))
+    return REG_ESPACE;
   if (dest->alloc < 2 * src->nelem + dest->nelem)
     {
-      Idx new_alloc = 2 * (src->nelem + dest->alloc);
-      Idx *new_buffer = re_realloc (dest->elems, Idx, new_alloc);
+      Idx new_alloc = src->nelem + dest->alloc;
+      Idx *new_buffer;
+      if (sizeof (Idx) < 4 && new_alloc < dest->alloc)
+       return REG_ESPACE;
+      new_buffer = re_x2realloc (dest->elems, Idx, &new_alloc);
       if (BE (new_buffer == NULL, 0))
        return REG_ESPACE;
       dest->elems = new_buffer;
@@ -1199,9 +1213,7 @@ re_node_set_insert (re_node_set *set, Id
   /* Realloc if we need.  */
   if (set->alloc == set->nelem)
     {
-      Idx *new_elems;
-      set->alloc = set->alloc * 2;
-      new_elems = re_realloc (set->elems, Idx, set->alloc);
+      Idx *new_elems = re_x2realloc (set->elems, Idx, &set->alloc);
       if (BE (new_elems == NULL, 0))
        return false;
       set->elems = new_elems;
@@ -1239,8 +1251,7 @@ re_node_set_insert_last (re_node_set *se
   if (set->alloc == set->nelem)
     {
       Idx *new_elems;
-      set->alloc = (set->alloc + 1) * 2;
-      new_elems = re_realloc (set->elems, Idx, set->alloc);
+      new_elems = re_x2realloc (set->elems, Idx, &set->alloc);
       if (BE (new_elems == NULL, 0))
        return false;
       set->elems = new_elems;
@@ -1313,18 +1324,18 @@ re_dfa_add_node (re_dfa_t *dfa, re_token
   int type = token.type;
   if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0))
     {
-      Idx new_nodes_alloc = dfa->nodes_alloc * 2;
+      Idx new_nodes_alloc = dfa->nodes_alloc;
       Idx *new_nexts, *new_indices;
       re_node_set *new_edests, *new_eclosures;
 
-      re_token_t *new_nodes = re_realloc (dfa->nodes, re_token_t,
-                                         new_nodes_alloc);
+      re_token_t *new_nodes = re_x2realloc (dfa->nodes, re_token_t,
+                                           &new_nodes_alloc);
       if (BE (new_nodes == NULL, 0))
        return REG_MISSING;
       dfa->nodes = new_nodes;
       new_nexts = re_realloc (dfa->nexts, Idx, new_nodes_alloc);
       new_indices = re_realloc (dfa->org_indices, Idx, new_nodes_alloc);
-      new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc);
+      new_edests = re_xrealloc (dfa->edests, re_node_set, new_nodes_alloc);
       new_eclosures = re_realloc (dfa->eclosures, re_node_set, 
new_nodes_alloc);
       if (BE (new_nexts == NULL || new_indices == NULL
              || new_edests == NULL || new_eclosures == NULL, 0))
@@ -1487,9 +1498,9 @@ register_state (const re_dfa_t *dfa, re_
   spot = dfa->state_table + (hash & dfa->state_hash_mask);
   if (BE (spot->alloc <= spot->num, 0))
     {
-      Idx new_alloc = 2 * spot->num + 2;
-      re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *,
-                                             new_alloc);
+      Idx new_alloc = spot->num;
+      re_dfastate_t **new_array = re_x2realloc (spot->array, re_dfastate_t *,
+                                               &new_alloc);
       if (BE (new_array == NULL, 0))
        return REG_ESPACE;
       spot->array = new_array;
--- lib/regexec.c       1 Sep 2005 19:41:07 -0000       1.16
+++ lib/regexec.c       2 Sep 2005 22:39:28 -0000
@@ -434,7 +434,7 @@ re_search_stub (struct re_pattern_buffer
   if (regs == NULL)
     nregs = 1;
   else if (BE (bufp->re_regs_allocated == REG_FIXED
-              && regs->rm_num_regs < bufp->re_nsub + 1, 0))
+              && regs->rm_num_regs <= bufp->re_nsub, 0))
     {
       nregs = regs->rm_num_regs;
       if (BE (nregs < 1, 0))
@@ -446,7 +446,7 @@ re_search_stub (struct re_pattern_buffer
     }
   else
     nregs = bufp->re_nsub + 1;
-  pmatch = re_malloc (regmatch_t, nregs);
+  pmatch = re_xmalloc (regmatch_t, nregs);
   if (BE (pmatch == NULL, 0))
     {
       rval = -2;
@@ -500,7 +500,7 @@ re_copy_regs (struct re_registers *regs,
   /* Have the register data arrays been allocated?  */
   if (regs_allocated == REG_UNALLOCATED)
     { /* No.  So allocate them with malloc.  */
-      regs->rm_start = re_malloc (regoff_t, need_regs);
+      regs->rm_start = re_xmalloc (regoff_t, need_regs);
       regs->rm_end = re_malloc (regoff_t, need_regs);
       if (BE (regs->rm_start == NULL, 0) || BE (regs->rm_end == NULL, 0))
        return REG_UNALLOCATED;
@@ -513,7 +513,7 @@ re_copy_regs (struct re_registers *regs,
       if (BE (need_regs > regs->rm_num_regs, 0))
        {
          regoff_t *new_start =
-           re_realloc (regs->rm_start, regoff_t, need_regs);
+           re_xrealloc (regs->rm_start, regoff_t, need_regs);
          regoff_t *new_end = re_realloc (regs->rm_end, regoff_t, need_regs);
          if (BE (new_start == NULL, 0) || BE (new_end == NULL, 0))
            return REG_UNALLOCATED;
@@ -685,7 +685,7 @@ re_search_internal (const regex_t *preg,
      multi character collating element.  */
   if (nmatch > 1 || dfa->has_mb_node)
     {
-      mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1);
+      mctx.state_log = re_xmalloc (re_dfastate_t *, mctx.input.bufs_len + 1);
       if (BE (mctx.state_log == NULL, 0))
        {
          err = REG_ESPACE;
@@ -945,7 +945,7 @@ prune_impossible_nodes (re_match_context
 #endif
   match_last = mctx->match_last;
   halt_node = mctx->last_node;
-  sifted_states = re_malloc (re_dfastate_t *, match_last + 1);
+  sifted_states = re_xmalloc (re_dfastate_t *, match_last + 1);
   if (BE (sifted_states == NULL, 0))
     {
       ret = REG_ESPACE;
@@ -953,7 +953,7 @@ prune_impossible_nodes (re_match_context
     }
   if (dfa->nbackref)
     {
-      lim_states = re_malloc (re_dfastate_t *, match_last + 1);
+      lim_states = re_xmalloc (re_dfastate_t *, match_last + 1);
       if (BE (lim_states == NULL, 0))
        {
          ret = REG_ESPACE;
@@ -1343,15 +1343,14 @@ push_fail_stack (struct re_fail_stack_t 
   if (fs->num == fs->alloc)
     {
       struct re_fail_stack_ent_t *new_array =
-       re_realloc (fs->stack, struct re_fail_stack_ent_t, fs->alloc * 2);
+       re_x2realloc (fs->stack, struct re_fail_stack_ent_t, &fs->alloc);
       if (new_array == NULL)
        return REG_ESPACE;
-      fs->alloc *= 2;
       fs->stack = new_array;
     }
   fs->stack[num].idx = str_idx;
   fs->stack[num].node = dest_node;
-  fs->stack[num].regs = re_malloc (regmatch_t, nregs);
+  fs->stack[num].regs = re_xmalloc (regmatch_t, nregs);
   if (fs->stack[num].regs == NULL)
     return REG_ESPACE;
   memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs);
@@ -1399,7 +1398,7 @@ set_regs (const regex_t *preg, const re_
   if (fl_backtrack)
     {
       fs = &fs_body;
-      fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc);
+      fs->stack = re_xmalloc (struct re_fail_stack_ent_t, fs->alloc);
       if (fs->stack == NULL)
        return REG_ESPACE;
     }
@@ -1409,6 +1408,11 @@ set_regs (const regex_t *preg, const re_
   cur_node = dfa->init_node;
   re_node_set_init_empty (&eps_via_nodes);
 
+  if (re_alloc_oversized (nmatch, sizeof (regmatch_t)))
+    {
+      free_fail_stack_return (fs);
+      return REG_ESPACE;
+    }
   if (__libc_use_alloca (nmatch * sizeof (regmatch_t)))
     prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t));
   else
@@ -2872,16 +2876,16 @@ check_arrival (re_match_context_t *mctx,
     {
       re_dfastate_t **new_array;
       Idx old_alloc = path->alloc;
-      path->alloc += last_str + mctx->max_mb_elem_len + 1;
-      new_array = re_realloc (path->array, re_dfastate_t *, path->alloc);
-      if (new_array == NULL)
-       {
-         path->alloc = old_alloc;
-         return REG_ESPACE;
-       }
+      Idx new_alloc = old_alloc + last_str + mctx->max_mb_elem_len + 1;
+      if (BE (new_alloc < old_alloc, 0))
+       return REG_ESPACE;
+      new_array = re_xrealloc (path->array, re_dfastate_t *, new_alloc);
+      if (BE (new_array == NULL, 0))
+       return REG_ESPACE;
       path->array = new_array;
+      path->alloc = new_alloc;
       memset (new_array + old_alloc, '\0',
-             sizeof (re_dfastate_t *) * (path->alloc - old_alloc));
+             sizeof (re_dfastate_t *) * (new_alloc - old_alloc));
     }
 
   str_idx = path->next_idx == 0 ? top_str : path->next_idx;
@@ -3336,6 +3340,12 @@ build_trtable (re_dfa_t *dfa, re_dfastat
   if (BE (err != REG_NOERROR, 0))
     goto out_free;
 
+  /* Avoid arithmetic overflow in size calculation.  */
+  if (BE (((SIZE_MAX - (sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX)
+          / (3 * sizeof (re_dfastate_t *)))
+         < ndests, 0))
+    goto out_free;
+
   if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX
                         + ndests * 3 * sizeof (re_dfastate_t *)))
     dest_states = (re_dfastate_t **)
@@ -4057,8 +4067,8 @@ extend_buffers (re_match_context_t *mctx
       /* XXX We have no indication of the size of this buffer.  If this
         allocation fail we have no indication that the state_log array
         does not have the right size.  */
-      re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *,
-                                             pstr->bufs_len + 1);
+      re_dfastate_t **new_array = re_xrealloc (mctx->state_log, re_dfastate_t 
*,
+                                              pstr->bufs_len + 1);
       if (BE (new_array == NULL, 0))
        return REG_ESPACE;
       mctx->state_log = new_array;
@@ -4106,8 +4116,8 @@ match_ctx_init (re_match_context_t *mctx
   mctx->match_last = REG_MISSING;
   if (n > 0)
     {
-      mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n);
-      mctx->sub_tops = re_malloc (re_sub_match_top_t *, n);
+      mctx->bkref_ents = re_xmalloc (struct re_backref_cache_entry, n);
+      mctx->sub_tops = re_xmalloc (re_sub_match_top_t *, n);
       if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0))
        return REG_ESPACE;
     }
@@ -4179,8 +4189,8 @@ match_ctx_add_entry (re_match_context_t 
   if (mctx->nbkref_ents >= mctx->abkref_ents)
     {
       struct re_backref_cache_entry* new_entry;
-      new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry,
-                             mctx->abkref_ents * 2);
+      new_entry = re_x2realloc (mctx->bkref_ents, struct 
re_backref_cache_entry,
+                               &mctx->abkref_ents);
       if (BE (new_entry == NULL, 0))
        {
          re_free (mctx->bkref_ents);
@@ -4188,8 +4198,8 @@ match_ctx_add_entry (re_match_context_t 
        }
       mctx->bkref_ents = new_entry;
       memset (mctx->bkref_ents + mctx->nbkref_ents, '\0',
-             sizeof (struct re_backref_cache_entry) * mctx->abkref_ents);
-      mctx->abkref_ents *= 2;
+             (sizeof (struct re_backref_cache_entry)
+              * (mctx->abkref_ents - mctx->nbkref_ents)));
     }
   if (mctx->nbkref_ents > 0
       && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx)
@@ -4253,10 +4263,10 @@ match_ctx_add_subtop (re_match_context_t
 #endif
   if (BE (mctx->nsub_tops == mctx->asub_tops, 0))
     {
-      Idx new_asub_tops = mctx->asub_tops * 2;
-      re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops,
-                                                  re_sub_match_top_t *,
-                                                  new_asub_tops);
+      Idx new_asub_tops = mctx->asub_tops;
+      re_sub_match_top_t **new_array = re_x2realloc (mctx->sub_tops,
+                                                    re_sub_match_top_t *,
+                                                    &new_asub_tops);
       if (BE (new_array == NULL, 0))
        return REG_ESPACE;
       mctx->sub_tops = new_array;
@@ -4280,10 +4290,10 @@ match_ctx_add_sublast (re_sub_match_top_
   re_sub_match_last_t *new_entry;
   if (BE (subtop->nlasts == subtop->alasts, 0))
     {
-      Idx new_alasts = 2 * subtop->alasts + 1;
-      re_sub_match_last_t **new_array = re_realloc (subtop->lasts,
-                                                   re_sub_match_last_t *,
-                                                   new_alasts);
+      Idx new_alasts = subtop->alasts;
+      re_sub_match_last_t **new_array = re_x2realloc (subtop->lasts,
+                                                     re_sub_match_last_t *,
+                                                     &new_alasts);
       if (BE (new_array == NULL, 0))
        return NULL;
       subtop->lasts = new_array;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]