diff options
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.patch | 166 |
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 @@ | |||
1 | From 89be91f3df00657261870adbc590209fdb2bc405 Mon Sep 17 00:00:00 2001 | ||
2 | From: Ulya Trofimovich <skvadrik@gmail.com> | ||
3 | Date: Thu, 23 Apr 2020 23:02:21 +0100 | ||
4 | Subject: [PATCH] Rewrite recursion into iteration (estimation of NFA size for | ||
5 | RE). | ||
6 | |||
7 | This is to avoid stack overflow on large RE (especially on instrumented | ||
8 | builds that have larger stack frames, like AddressSanitizer). | ||
9 | |||
10 | Partial fix for #219 "overflow-1.re test fails on system with small stack". | ||
11 | |||
12 | Upstram-Status: Backport: | ||
13 | https://github.com/skvadrik/re2c/commit/89be91f3df00657261870adbc590209fdb2bc405 | ||
14 | |||
15 | CVE: CVE-2018-21232 | ||
16 | |||
17 | Signed-off-by: Davide Gardenal <davide.gardenal@huawei.com> | ||
18 | --- | ||
19 | diff --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 | |||