summaryrefslogtreecommitdiffstats
path: root/meta/recipes-support/re2c/re2c/CVE-2018-21232-4.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-support/re2c/re2c/CVE-2018-21232-4.patch')
-rw-r--r--meta/recipes-support/re2c/re2c/CVE-2018-21232-4.patch166
1 files changed, 166 insertions, 0 deletions
diff --git a/meta/recipes-support/re2c/re2c/CVE-2018-21232-4.patch b/meta/recipes-support/re2c/re2c/CVE-2018-21232-4.patch
new file mode 100644
index 0000000000..ee8d84b1bc
--- /dev/null
+++ b/meta/recipes-support/re2c/re2c/CVE-2018-21232-4.patch
@@ -0,0 +1,166 @@
1From 89be91f3df00657261870adbc590209fdb2bc405 Mon Sep 17 00:00:00 2001
2From: Ulya Trofimovich <skvadrik@gmail.com>
3Date: Thu, 23 Apr 2020 23:02:21 +0100
4Subject: [PATCH] Rewrite recursion into iteration (estimation of NFA size for
5 RE).
6
7This is to avoid stack overflow on large RE (especially on instrumented
8builds that have larger stack frames, like AddressSanitizer).
9
10Partial fix for #219 "overflow-1.re test fails on system with small stack".
11
12Upstram-Status: Backport:
13https://github.com/skvadrik/re2c/commit/89be91f3df00657261870adbc590209fdb2bc405
14
15CVE: CVE-2018-21232
16
17Signed-off-by: Davide Gardenal <davide.gardenal@huawei.com>
18---
19diff --git a/src/nfa/estimate_size.cc b/src/nfa/estimate_size.cc
20--- a/src/nfa/estimate_size.cc (revision e58939b34bb4c37cd990f82dc286f21cb405743e)
21+++ b/src/nfa/estimate_size.cc (date 1647005399735)
22@@ -6,41 +6,113 @@
23 #include "src/re/re.h"
24
25 namespace re2c {
26+namespace {
27+
28+struct StackItem {
29+ const RE *re; // current sub-RE
30+ uint32_t size; // size of the sub-RE (only for alternative and concatenation)
31+ uint8_t succ; // index of the next sucessor to be visited
32+};
33
34-static size_t estimate(const RE *re)
35+static uint32_t estimate_re_size(const RE *re0, std::vector<StackItem> &stack)
36 {
37- switch (re->type) {
38- case RE::NIL: return 0;
39- case RE::SYM: return 1;
40- case RE::TAG: return 1;
41- case RE::ALT:
42- return estimate(re->alt.re1)
43- + estimate(re->alt.re2)
44- + 1;
45- case RE::CAT:
46- return estimate(re->cat.re1)
47- + estimate(re->cat.re2);
48- case RE::ITER: {
49- const size_t
50- iter = estimate(re->iter.re),
51- min = re->iter.min,
52- max = re->iter.max;
53- return max == AST::MANY
54- ? iter * min + 1
55- : iter * max + (max - min);
56- }
57- }
58- return 0; /* unreachable */
59-}
60+ // the estimated size of the last sub-RE visited by DFS
61+ uint32_t size = 0;
62+
63+ const StackItem i0 = {re0, 0, 0};
64+ stack.push_back(i0);
65+
66+ while (!stack.empty()) {
67+ const StackItem i = stack.back();
68+ stack.pop_back();
69+
70+ const RE *re = i.re;
71+ if (re->type == RE::NIL) {
72+ size = 0;
73+ }
74+ else if (re->type == RE::SYM || re->type == RE::TAG) {
75+ size = 1;
76+ }
77+ else if (re->type == RE::ALT) {
78+ if (i.succ == 0) {
79+ // recurse into the left sub-RE
80+ StackItem k = {re, 0, 1};
81+ stack.push_back(k);
82+ StackItem j = {re->alt.re1, 0, 0};
83+ stack.push_back(j);
84+ }
85+ else if (i.succ == 1) {
86+ // recurse into the right sub-RE
87+ StackItem k = {re, size, 2};
88+ stack.push_back(k);
89+ StackItem j = {re->alt.re2, 0, 0};
90+ stack.push_back(j);
91+ }
92+ else {
93+ // both sub-RE visited, recursive return
94+ size = i.size // left sub-RE (saved on stack)
95+ + size // right sub-RE (just visited by DFS)
96+ + 1; // additional state for alternative
97+ }
98+ }
99+ else if (re->type == RE::CAT) {
100+ if (i.succ == 0) {
101+ // recurse into the left sub-RE
102+ StackItem k = {re, 0, 1};
103+ stack.push_back(k);
104+ StackItem j = {re->cat.re1, 0, 0};
105+ stack.push_back(j);
106+ }
107+ else if (i.succ == 1) {
108+ // recurse into the right sub-RE
109+ StackItem k = {re, size, 2};
110+ stack.push_back(k);
111+ StackItem j = {re->cat.re2, 0, 0};
112+ stack.push_back(j);
113+ }
114+ else {
115+ // both sub-RE visited, recursive return
116+ size = i.size // left sub-RE (saved on stack)
117+ + size; // right sub-RE (just visited by DFS)
118+ }
119+ }
120+ else if (re->type == RE::ITER) {
121+ if (i.succ == 0) {
122+ // recurse into the sub-RE
123+ StackItem k = {re, 0, 1};
124+ stack.push_back(k);
125+ StackItem j = {re->iter.re, 0, 0};
126+ stack.push_back(j);
127+ }
128+ else {
129+ // sub-RE visited, recursive return
130+ const uint32_t min = re->iter.min, max = re->iter.max;
131+ size = max == AST::MANY
132+ ? size * min + 1
133+ : size * max + (max - min);
134+ }
135+ }
136+ }
137+
138+ //DASSERT(stack.empty());
139+ return size;
140+}
141+
142+} // anonymous namespace
143
144 size_t estimate_size(const std::vector<RE*> &res)
145 {
146- const size_t nre = res.size();
147- size_t size = nre - 1;
148- for (size_t i = 0; i < nre; ++i) {
149- size += estimate(res[i]) + 1;
150- }
151- return size;
152+ std::vector<StackItem> stack;
153+
154+ const size_t nre = res.size();
155+ //DASSERT(nre > 0);
156+ size_t size = nre - 1;
157+
158+ for (size_t i = 0; i < nre; ++i) {
159+ size += estimate_re_size(res[i], stack) + 1;
160+ }
161+
162+ return size;
163 }
164
165 } // namespace re2c
166