bug-gnulib
[Top][All Lists]
Advanced

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

regex alloca fixes


From: Paul Eggert
Subject: regex alloca fixes
Date: Thu, 25 Aug 2005 23:09:25 -0700
User-agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux)

I noticed that regex invoked alloca with unbounded size.  Rather
than use the allocsa module I thought it better to stick to glibc
style, and define __libc_use_alloca when _LIBC isn't defined.
I installed this (and filed glibc bug 1245):

2005-08-25  Paul Eggert  <address@hidden>

        * config/srclist.txt: Add glibc bug 1245.

        * lib/regexec.c (set_regs): Don't alloca with an unbounded size.

        alloca modernization/simplification for regex.
        * lib/regex.c: Remove portability cruft for alloca.  This no longer
        needs to be at the start of the file, and can be moved into
        regex_internal.h and simplified.
        * lib/regex_internal.h: Include <alloca.h>.
        (__libc_use_alloca) [!defined _LIBC]: New macro.
        * lib/regexec.c (build_trtable): Remove "#ifdef _LIBC",
        since the code now works outside glibc.

--- config/srclist.txt.~1.86.~  2005-08-25 13:39:57.000000000 -0700
+++ config/srclist.txt  2005-08-25 22:55:59.000000000 -0700
@@ -105,6 +105,7 @@ $LIBCSRC/stdlib/getsubopt.c         lib gpl
 #$LIBCSRC/posix/regcomp.c              lib gpl
 #
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1238
+# http://sources.redhat.com/bugzilla/show_bug.cgi?id=1245
 #$LIBCSRC/posix/regex.c                        lib gpl
 #
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1201
@@ -128,6 +129,7 @@ $LIBCSRC/stdlib/getsubopt.c         lib gpl
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1221
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1237
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1241
+# http://sources.redhat.com/bugzilla/show_bug.cgi?id=1245
 #$LIBCSRC/posix/regex_internal.h               lib gpl
 #
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1216
@@ -137,6 +139,7 @@ $LIBCSRC/stdlib/getsubopt.c         lib gpl
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1231
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1237
 # http://sources.redhat.com/bugzilla/show_bug.cgi?id=1241
+# http://sources.redhat.com/bugzilla/show_bug.cgi?id=1245
 #$LIBCSRC/posix/regexec.c              lib gpl
 #
 # c89 changes $LIBCSRC/string/strdup.c         lib gpl
--- lib/regex.c 24 Aug 2005 23:43:01 -0000      1.91
+++ lib/regex.c 26 Aug 2005 05:41:47 -0000
@@ -21,30 +21,6 @@
 #include "config.h"
 #endif
 
-#ifdef _AIX
-#pragma alloca
-#else
-# ifndef allocax           /* predefined by HP cc +Olibcalls */
-#  ifdef __GNUC__
-#   define alloca(size) __builtin_alloca (size)
-#  else
-#   if HAVE_ALLOCA_H
-#    include <alloca.h>
-#   else
-#    ifdef __hpux
-        void *alloca ();
-#    else
-#     if !defined __OS2__ && !defined WIN32
-        char *alloca ();
-#     else
-#      include <malloc.h>       /* OS/2 defines alloca in here */
-#     endif
-#    endif
-#   endif
-#  endif
-# endif
-#endif
-
 #ifdef _LIBC
 /* We have to keep the namespace clean.  */
 # define regfree(preg) __regfree (preg)
--- lib/regex_internal.h        25 Aug 2005 20:39:57 -0000      1.4
+++ lib/regex_internal.h        26 Aug 2005 05:41:47 -0000
@@ -431,6 +431,21 @@ static unsigned char re_string_fetch_byt
 #define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
 #define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
 
+#include <alloca.h>
+
+#ifndef __LIBC
+# if HAVE_ALLOCA
+/* The OS usually guarantees only one guard page at the bottom of the stack,
+   and a page size can be as small as 4096 bytes.  So we cannot safely
+   allocate anything larger than 4096 bytes.  Also care for the possibility
+   of a few compiler-allocated temporary stack slots.  */
+#  define __libc_use_alloca(n) ((n) < 4032)
+# else
+/* alloca is implemented with malloc, so just use malloc.  */
+#  define __libc_use_alloca(n) 0
+# endif
+#endif
+
 #define re_malloc(t,n) ((t *) malloc ((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)))
--- lib/regexec.c       25 Aug 2005 20:39:57 -0000      1.8
+++ lib/regexec.c       26 Aug 2005 05:41:47 -0000
@@ -1354,6 +1354,7 @@ set_regs (const regex_t *preg, const re_
   struct re_fail_stack_t *fs;
   struct re_fail_stack_t fs_body = { 0, 2, NULL };
   regmatch_t *prev_idx_match;
+  int prev_idx_match_malloced = 0;
 
 #ifdef DEBUG
   assert (nmatch > 1);
@@ -1372,7 +1373,18 @@ set_regs (const regex_t *preg, const re_
   cur_node = dfa->init_node;
   re_node_set_init_empty (&eps_via_nodes);
 
-  prev_idx_match = (regmatch_t *) alloca (sizeof (regmatch_t) * nmatch);
+  if (__libc_use_alloca (nmatch * sizeof (regmatch_t)))
+    prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t));
+  else
+    {
+      prev_idx_match = re_malloc (regmatch_t, nmatch);
+      if (prev_idx_match == NULL)
+       {
+         free_fail_stack_return (fs);
+         return REG_ESPACE;
+       }
+      prev_idx_match_malloced = 1;
+    }
   memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
 
   for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;)
@@ -1390,6 +1402,8 @@ set_regs (const regex_t *preg, const re_
              if (reg_idx == nmatch)
                {
                  re_node_set_free (&eps_via_nodes);
+                 if (prev_idx_match_malloced)
+                   re_free (prev_idx_match);
                  return free_fail_stack_return (fs);
                }
              cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
@@ -1398,6 +1412,8 @@ set_regs (const regex_t *preg, const re_
          else
            {
              re_node_set_free (&eps_via_nodes);
+             if (prev_idx_match_malloced)
+               re_free (prev_idx_match);
              return REG_NOERROR;
            }
        }
@@ -1411,6 +1427,8 @@ set_regs (const regex_t *preg, const re_
          if (BE (cur_node == -2, 0))
            {
              re_node_set_free (&eps_via_nodes);
+             if (prev_idx_match_malloced)
+               re_free (prev_idx_match);
              free_fail_stack_return (fs);
              return REG_ESPACE;
            }
@@ -1420,11 +1438,15 @@ set_regs (const regex_t *preg, const re_
          else
            {
              re_node_set_free (&eps_via_nodes);
+             if (prev_idx_match_malloced)
+               re_free (prev_idx_match);
              return REG_NOMATCH;
            }
        }
     }
   re_node_set_free (&eps_via_nodes);
+  if (prev_idx_match_malloced)
+    re_free (prev_idx_match);
   return free_fail_stack_return (fs);
 }
 
@@ -3235,12 +3257,10 @@ build_trtable (re_dfa_t *dfa, re_dfastat
      from `state'.  `dests_node[i]' represents the nodes which i-th
      destination state contains, and `dests_ch[i]' represents the
      characters which i-th destination state accepts.  */
-#ifdef _LIBC
   if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX))
     dests_node = (re_node_set *)
       alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX);
   else
-#endif
     {
       dests_node = (re_node_set *)
        malloc ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX);
@@ -3273,13 +3293,11 @@ build_trtable (re_dfa_t *dfa, re_dfastat
   if (BE (err != REG_NOERROR, 0))
     goto out_free;
 
-#ifdef _LIBC
   if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX
                         + ndests * 3 * sizeof (re_dfastate_t *)))
     dest_states = (re_dfastate_t **)
       alloca (ndests * 3 * sizeof (re_dfastate_t *));
   else
-#endif
     {
       dest_states = (re_dfastate_t **)
        malloc (ndests * 3 * sizeof (re_dfastate_t *));




reply via email to

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