bug-gnulib
[Top][All Lists]
Advanced

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

[PATCH 02/10] regex: avoid undefined behavior


From: Paul Eggert
Subject: [PATCH 02/10] regex: avoid undefined behavior
Date: Fri, 5 Feb 2021 17:25:54 -0800

* lib/regexec.c (pop_fail_stack): If the stack is empty, return -1
instead of indulging in undefined behavior.  This simplifies
callers, and avoids undefined behavior in some cases (see glibc
bug 11053, though this change does not fix that overall bug).
---
 ChangeLog     |  6 ++++++
 lib/regexec.c | 30 ++++++++++++++----------------
 2 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index fef04a89c..6fcd5819f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2021-02-05  Paul Eggert  <eggert@cs.ucla.edu>
 
+       regex: avoid undefined behavior
+       * lib/regexec.c (pop_fail_stack): If the stack is empty, return -1
+       instead of indulging in undefined behavior.  This simplifies
+       callers, and avoids undefined behavior in some cases (see glibc
+       bug 11053, though this change does not fix that overall bug).
+
        regex: improve comments
        * lib/regexec.c: Add and correct comments about return values.
 
diff --git a/lib/regexec.c b/lib/regexec.c
index fa413dfd5..f982e3aba 100644
--- a/lib/regexec.c
+++ b/lib/regexec.c
@@ -1346,13 +1346,15 @@ static Idx
 pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs,
                regmatch_t *regs, re_node_set *eps_via_nodes)
 {
+  if (fs == NULL || fs->num == 0)
+    return -1;
   Idx num = --fs->num;
-  DEBUG_ASSERT (num >= 0);
   *pidx = fs->stack[num].idx;
   memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs);
   re_node_set_free (eps_via_nodes);
   re_free (fs->stack[num].regs);
   *eps_via_nodes = fs->stack[num].eps_via_nodes;
+  DEBUG_ASSERT (0 <= fs->stack[num].node);
   return fs->stack[num].node;
 }
 
@@ -1411,25 +1413,22 @@ set_regs (const regex_t *preg, const re_match_context_t 
*mctx, size_t nmatch,
       if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
        {
          Idx reg_idx;
+         cur_node = -1;
          if (fs)
            {
              for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
                if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1)
-                 break;
-             if (reg_idx == nmatch)
-               {
-                 re_node_set_free (&eps_via_nodes);
-                 regmatch_list_free (&prev_match);
-                 return free_fail_stack_return (fs);
-               }
-             cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
-                                        &eps_via_nodes);
+                 {
+                   cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
+                                              &eps_via_nodes);
+                   break;
+                 }
            }
-         else
+         if (cur_node < 0)
            {
              re_node_set_free (&eps_via_nodes);
              regmatch_list_free (&prev_match);
-             return REG_NOERROR;
+             return free_fail_stack_return (fs);
            }
        }
 
@@ -1446,13 +1445,12 @@ set_regs (const regex_t *preg, const re_match_context_t 
*mctx, size_t nmatch,
              free_fail_stack_return (fs);
              return REG_ESPACE;
            }
-         if (fs)
-           cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
-                                      &eps_via_nodes);
-         else
+         cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, &eps_via_nodes);
+         if (cur_node < 0)
            {
              re_node_set_free (&eps_via_nodes);
              regmatch_list_free (&prev_match);
+             free_fail_stack_return (fs);
              return REG_NOMATCH;
            }
        }
-- 
2.27.0




reply via email to

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