summaryrefslogtreecommitdiff
path: root/backport-Guard-against-out-of-bounds-memory-access-when-parsing.patch
blob: 196ce7d24f826d45d3b87cb0d28bc3834eb1618b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
From ef218fbba60bfe5b0a8ac9ea4445eac5fb0847e5 Mon Sep 17 00:00:00 2001
From: Alex Dowad <alexinbeijing@gmail.com>
Date: Sat, 7 Sep 2024 00:16:03 +0900
Subject: [PATCH] Guard against out-of-bounds memory access when parsing
 LIMIT_HEAP et al (#463)

Patterns passed to pcre2_compile are not guaranteed to be
null-terminated. Also, it can happen that there is an invalid
pattern like this:

    (*LIMIT_HEAP=123

If the next byte of memory after the end of the pattern happens
to be a digit, it will be parsed as part of the limit value. Or,
if the next byte is a right parenthesis character, it will be taken
as the end of the (*LIMIT_HEAP=nnn) construct.

This will result in `skipatstart` being larger than `patlen`, which
will result in underflow and an erroneous call to malloc requesting
a huge number of bytes.
---
 src/pcre2_compile.c   | 7 ++++---
 testdata/testoutput15 | 4 ++--
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/pcre2_compile.c b/src/pcre2_compile.c
index e6843bb13..410f220b3 100644
--- a/src/pcre2_compile.c
+++ b/src/pcre2_compile.c
@@ -10552,12 +10552,12 @@ if ((options & PCRE2_LITERAL) == 0)
             ptr += pp;
             goto HAD_EARLY_ERROR;
             }
-          while (IS_DIGIT(ptr[pp]))
+          while (pp < patlen && IS_DIGIT(ptr[pp]))
             {
             if (c > UINT32_MAX / 10 - 1) break;   /* Integer overflow */
             c = c*10 + (ptr[pp++] - CHAR_0);
             }
-          if (ptr[pp++] != CHAR_RIGHT_PARENTHESIS)
+          if (pp >= patlen || ptr[pp] != CHAR_RIGHT_PARENTHESIS)
             {
             errorcode = ERR60;
             ptr += pp;
@@ -10566,7 +10566,7 @@ if ((options & PCRE2_LITERAL) == 0)
           if (p->type == PSO_LIMH) limit_heap = c;
             else if (p->type == PSO_LIMM) limit_match = c;
             else limit_depth = c;
-          skipatstart += pp - skipatstart;
+          skipatstart = ++pp;
           break;
           }
         break;   /* Out of the table scan loop */
@@ -10574,6 +10574,7 @@ if ((options & PCRE2_LITERAL) == 0)
       }
     if (i >= sizeof(pso_list)/sizeof(pso)) break;   /* Out of pso loop */
     }
+    PCRE2_ASSERT(skipatstart <= patlen);
   }
 
 /* End of pattern-start options; advance to start of real regex. */
diff --git a/testdata/testoutput15 b/testdata/testoutput15
index aa9c5c930..f36faeeaf 100644
--- a/testdata/testoutput15
+++ b/testdata/testoutput15
@@ -111,10 +111,10 @@ Minimum depth limit = 10
  3: ee
 
 /(*LIMIT_MATCH=12bc)abc/
-Failed: error 160 at offset 17: (*VERB) not recognized or malformed
+Failed: error 160 at offset 16: (*VERB) not recognized or malformed
 
 /(*LIMIT_MATCH=4294967290)abc/
-Failed: error 160 at offset 24: (*VERB) not recognized or malformed
+Failed: error 160 at offset 23: (*VERB) not recognized or malformed
 
 /(*LIMIT_DEPTH=4294967280)abc/I
 Capture group count = 0