diff options
author | Lee Chee Yang <chee.yang.lee@intel.com> | 2020-08-18 22:06:37 +0800 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2020-08-27 08:25:50 +0100 |
commit | c2710903859a5545aa9dd56251f61667ee8d80bd (patch) | |
tree | af085b1dd2b7a732d1c302f59ad48607d51554e3 /meta/recipes-devtools | |
parent | 060ba609bd6ed40c8407934191da60c5e3ad8de7 (diff) | |
download | poky-c2710903859a5545aa9dd56251f61667ee8d80bd.tar.gz |
perl: fix CVE-2020-12723
Minor changes to the test cases count in the .patch file to make it
align with current version, so the fixes can be apply.
Changes apply to line:
https://github.com/perl/perl5/commit/66bbb51b93253a3f87d11c2695cfb7bdb782184a#diff-e31ddd69cf47acf02911647c691a0283L28
(From OE-Core rev: 43f1aa650c45a0976230c7c2f79d8efe0e6e159a)
Signed-off-by: Lee Chee Yang <chee.yang.lee@intel.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-devtools')
-rw-r--r-- | meta/recipes-devtools/perl/files/CVE-2020-12723.patch | 302 | ||||
-rw-r--r-- | meta/recipes-devtools/perl/perl_5.30.1.bb | 1 |
2 files changed, 303 insertions, 0 deletions
diff --git a/meta/recipes-devtools/perl/files/CVE-2020-12723.patch b/meta/recipes-devtools/perl/files/CVE-2020-12723.patch new file mode 100644 index 0000000000..ad195cffab --- /dev/null +++ b/meta/recipes-devtools/perl/files/CVE-2020-12723.patch | |||
@@ -0,0 +1,302 @@ | |||
1 | From da9ec461e22915ccabb06785bf39ec34577ada12 Mon Sep 17 00:00:00 2001 | ||
2 | From: Hugo van der Sanden <hv@crypt.org> | ||
3 | Date: Sat, 11 Apr 2020 14:10:24 +0100 | ||
4 | Subject: [PATCH] study_chunk: avoid mutating regexp program within GOSUB | ||
5 | |||
6 | gh16947 and gh17743: studying GOSUB may restudy in an inner call | ||
7 | (via a mix of recursion and enframing) something that an outer call | ||
8 | is in the middle of looking at. Let the outer frame deal with it. | ||
9 | |||
10 | (CVE-2020-12723) | ||
11 | |||
12 | (cherry picked from commit c4033e740bd18d9fbe3456a9db2ec2053cdc5271) | ||
13 | |||
14 | Upstream-Status: Backport [https://github.com/perl/perl5/commit/66bbb51b93253a3f87d11c2695cfb7bdb782184a] | ||
15 | CVE: CVE-2020-12723 | ||
16 | Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com> | ||
17 | |||
18 | --- | ||
19 | embed.fnc | 2 +- | ||
20 | embed.h | 2 +- | ||
21 | proto.h | 2 +- | ||
22 | regcomp.c | 54 +++++++++++++++++++++++++++++++++++------------------- | ||
23 | t/re/pat.t | 26 +++++++++++++++++++++++++- | ||
24 | 5 files changed, 63 insertions(+), 23 deletions(-) | ||
25 | |||
26 | diff --git a/embed.fnc b/embed.fnc | ||
27 | index f45c127..eff4a50 100644 | ||
28 | --- a/embed.fnc | ||
29 | +++ b/embed.fnc | ||
30 | @@ -2480,7 +2480,7 @@ Es |SSize_t|study_chunk |NN RExC_state_t *pRExC_state \ | ||
31 | |NULLOK struct scan_data_t *data \ | ||
32 | |I32 stopparen|U32 recursed_depth \ | ||
33 | |NULLOK regnode_ssc *and_withp \ | ||
34 | - |U32 flags|U32 depth | ||
35 | + |U32 flags|U32 depth|bool was_mutate_ok | ||
36 | Es |void |rck_elide_nothing|NN regnode *node | ||
37 | EsR |SV * |get_ANYOFM_contents|NN const regnode * n | ||
38 | EsRn |U32 |add_data |NN RExC_state_t* const pRExC_state \ | ||
39 | diff --git a/embed.h b/embed.h | ||
40 | index 356a8b9..5346ec5 100644 | ||
41 | --- a/embed.h | ||
42 | +++ b/embed.h | ||
43 | @@ -1239,7 +1239,7 @@ | ||
44 | #define ssc_is_cp_posixl_init S_ssc_is_cp_posixl_init | ||
45 | #define ssc_or(a,b,c) S_ssc_or(aTHX_ a,b,c) | ||
46 | #define ssc_union(a,b,c) S_ssc_union(aTHX_ a,b,c) | ||
47 | -#define study_chunk(a,b,c,d,e,f,g,h,i,j,k) S_study_chunk(aTHX_ a,b,c,d,e,f,g,h,i,j,k) | ||
48 | +#define study_chunk(a,b,c,d,e,f,g,h,i,j,k,l) S_study_chunk(aTHX_ a,b,c,d,e,f,g,h,i,j,k,l) | ||
49 | # endif | ||
50 | # if defined(PERL_IN_REGCOMP_C) || defined (PERL_IN_DUMP_C) | ||
51 | #define _invlist_dump(a,b,c,d) Perl__invlist_dump(aTHX_ a,b,c,d) | ||
52 | diff --git a/proto.h b/proto.h | ||
53 | index 91530b1..1bda01f 100644 | ||
54 | --- a/proto.h | ||
55 | +++ b/proto.h | ||
56 | @@ -5655,7 +5655,7 @@ PERL_STATIC_INLINE void S_ssc_union(pTHX_ regnode_ssc *ssc, SV* const invlist, c | ||
57 | #define PERL_ARGS_ASSERT_SSC_UNION \ | ||
58 | assert(ssc); assert(invlist) | ||
59 | #endif | ||
60 | -STATIC SSize_t S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, SSize_t *minlenp, SSize_t *deltap, regnode *last, struct scan_data_t *data, I32 stopparen, U32 recursed_depth, regnode_ssc *and_withp, U32 flags, U32 depth); | ||
61 | +STATIC SSize_t S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, SSize_t *minlenp, SSize_t *deltap, regnode *last, struct scan_data_t *data, I32 stopparen, U32 recursed_depth, regnode_ssc *and_withp, U32 flags, U32 depth, bool was_mutate_ok); | ||
62 | #define PERL_ARGS_ASSERT_STUDY_CHUNK \ | ||
63 | assert(pRExC_state); assert(scanp); assert(minlenp); assert(deltap); assert(last) | ||
64 | #endif | ||
65 | diff --git a/regcomp.c b/regcomp.c | ||
66 | index 5a9adee..8d7df1f 100644 | ||
67 | --- a/regcomp.c | ||
68 | +++ b/regcomp.c | ||
69 | @@ -106,6 +106,7 @@ typedef struct scan_frame { | ||
70 | regnode *next_regnode; /* next node to process when last is reached */ | ||
71 | U32 prev_recursed_depth; | ||
72 | I32 stopparen; /* what stopparen do we use */ | ||
73 | + bool in_gosub; /* this or an outer frame is for GOSUB */ | ||
74 | |||
75 | struct scan_frame *this_prev_frame; /* this previous frame */ | ||
76 | struct scan_frame *prev_frame; /* previous frame */ | ||
77 | @@ -4466,7 +4467,7 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, | ||
78 | I32 stopparen, | ||
79 | U32 recursed_depth, | ||
80 | regnode_ssc *and_withp, | ||
81 | - U32 flags, U32 depth) | ||
82 | + U32 flags, U32 depth, bool was_mutate_ok) | ||
83 | /* scanp: Start here (read-write). */ | ||
84 | /* deltap: Write maxlen-minlen here. */ | ||
85 | /* last: Stop before this one. */ | ||
86 | @@ -4545,6 +4546,10 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, | ||
87 | node length to get a real minimum (because | ||
88 | the folded version may be shorter) */ | ||
89 | bool unfolded_multi_char = FALSE; | ||
90 | + /* avoid mutating ops if we are anywhere within the recursed or | ||
91 | + * enframed handling for a GOSUB: the outermost level will handle it. | ||
92 | + */ | ||
93 | + bool mutate_ok = was_mutate_ok && !(frame && frame->in_gosub); | ||
94 | /* Peephole optimizer: */ | ||
95 | DEBUG_STUDYDATA("Peep", data, depth, is_inf); | ||
96 | DEBUG_PEEP("Peep", scan, depth, flags); | ||
97 | @@ -4555,7 +4560,8 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, | ||
98 | * parsing code, as each (?:..) is handled by a different invocation of | ||
99 | * reg() -- Yves | ||
100 | */ | ||
101 | - JOIN_EXACT(scan,&min_subtract, &unfolded_multi_char, 0); | ||
102 | + if (mutate_ok) | ||
103 | + JOIN_EXACT(scan,&min_subtract, &unfolded_multi_char, 0); | ||
104 | |||
105 | /* Follow the next-chain of the current node and optimize | ||
106 | away all the NOTHINGs from it. | ||
107 | @@ -4587,7 +4593,7 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, | ||
108 | /* DEFINEP study_chunk() recursion */ | ||
109 | (void)study_chunk(pRExC_state, &scan, &minlen, | ||
110 | &deltanext, next, &data_fake, stopparen, | ||
111 | - recursed_depth, NULL, f, depth+1); | ||
112 | + recursed_depth, NULL, f, depth+1, mutate_ok); | ||
113 | |||
114 | scan = next; | ||
115 | } else | ||
116 | @@ -4655,7 +4661,8 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, | ||
117 | /* recurse study_chunk() for each BRANCH in an alternation */ | ||
118 | minnext = study_chunk(pRExC_state, &scan, minlenp, | ||
119 | &deltanext, next, &data_fake, stopparen, | ||
120 | - recursed_depth, NULL, f, depth+1); | ||
121 | + recursed_depth, NULL, f, depth+1, | ||
122 | + mutate_ok); | ||
123 | |||
124 | if (min1 > minnext) | ||
125 | min1 = minnext; | ||
126 | @@ -4722,9 +4729,10 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, | ||
127 | } | ||
128 | } | ||
129 | |||
130 | - if (PERL_ENABLE_TRIE_OPTIMISATION && | ||
131 | - OP( startbranch ) == BRANCH ) | ||
132 | - { | ||
133 | + if (PERL_ENABLE_TRIE_OPTIMISATION | ||
134 | + && OP(startbranch) == BRANCH | ||
135 | + && mutate_ok | ||
136 | + ) { | ||
137 | /* demq. | ||
138 | |||
139 | Assuming this was/is a branch we are dealing with: 'scan' | ||
140 | @@ -5179,6 +5187,9 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, | ||
141 | newframe->stopparen = stopparen; | ||
142 | newframe->prev_recursed_depth = recursed_depth; | ||
143 | newframe->this_prev_frame= frame; | ||
144 | + newframe->in_gosub = ( | ||
145 | + (frame && frame->in_gosub) || OP(scan) == GOSUB | ||
146 | + ); | ||
147 | |||
148 | DEBUG_STUDYDATA("frame-new", data, depth, is_inf); | ||
149 | DEBUG_PEEP("fnew", scan, depth, flags); | ||
150 | @@ -5336,7 +5347,7 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, | ||
151 | |||
152 | /* This temporary node can now be turned into EXACTFU, and | ||
153 | * must, as regexec.c doesn't handle it */ | ||
154 | - if (OP(next) == EXACTFU_S_EDGE) { | ||
155 | + if (OP(next) == EXACTFU_S_EDGE && mutate_ok) { | ||
156 | OP(next) = EXACTFU; | ||
157 | } | ||
158 | |||
159 | @@ -5344,8 +5355,9 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, | ||
160 | && isALPHA_A(* STRING(next)) | ||
161 | && ( OP(next) == EXACTFAA | ||
162 | || ( OP(next) == EXACTFU | ||
163 | - && ! HAS_NONLATIN1_SIMPLE_FOLD_CLOSURE(* STRING(next))))) | ||
164 | - { | ||
165 | + && ! HAS_NONLATIN1_SIMPLE_FOLD_CLOSURE(* STRING(next)))) | ||
166 | + && mutate_ok | ||
167 | + ) { | ||
168 | /* These differ in just one bit */ | ||
169 | U8 mask = ~ ('A' ^ 'a'); | ||
170 | |||
171 | @@ -5432,7 +5444,7 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, | ||
172 | (mincount == 0 | ||
173 | ? (f & ~SCF_DO_SUBSTR) | ||
174 | : f) | ||
175 | - ,depth+1); | ||
176 | + , depth+1, mutate_ok); | ||
177 | |||
178 | if (flags & SCF_DO_STCLASS) | ||
179 | data->start_class = oclass; | ||
180 | @@ -5498,7 +5510,9 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, | ||
181 | if ( OP(oscan) == CURLYX && data | ||
182 | && data->flags & SF_IN_PAR | ||
183 | && !(data->flags & SF_HAS_EVAL) | ||
184 | - && !deltanext && minnext == 1 ) { | ||
185 | + && !deltanext && minnext == 1 | ||
186 | + && mutate_ok | ||
187 | + ) { | ||
188 | /* Try to optimize to CURLYN. */ | ||
189 | regnode *nxt = NEXTOPER(oscan) + EXTRA_STEP_2ARGS; | ||
190 | regnode * const nxt1 = nxt; | ||
191 | @@ -5548,10 +5562,10 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, | ||
192 | && !(data->flags & SF_HAS_EVAL) | ||
193 | && !deltanext /* atom is fixed width */ | ||
194 | && minnext != 0 /* CURLYM can't handle zero width */ | ||
195 | - | ||
196 | /* Nor characters whose fold at run-time may be | ||
197 | * multi-character */ | ||
198 | && ! (RExC_seen & REG_UNFOLDED_MULTI_SEEN) | ||
199 | + && mutate_ok | ||
200 | ) { | ||
201 | /* XXXX How to optimize if data == 0? */ | ||
202 | /* Optimize to a simpler form. */ | ||
203 | @@ -5604,7 +5618,7 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp, | ||
204 | /* recurse study_chunk() on optimised CURLYX => CURLYM */ | ||
205 | study_chunk(pRExC_state, &nxt1, minlenp, &deltanext, nxt, | ||
206 | NULL, stopparen, recursed_depth, NULL, 0, | ||
207 | - depth+1); | ||
208 | + depth+1, mutate_ok); | ||
209 | } | ||
210 | else | ||
211 | oscan->flags = 0; | ||
212 | @@ -6009,7 +6023,8 @@ Perl_re_printf( aTHX_ "LHS=%" UVuf " RHS=%" UVuf "\n", | ||
213 | /* recurse study_chunk() for lookahead body */ | ||
214 | minnext = study_chunk(pRExC_state, &nscan, minlenp, &deltanext, | ||
215 | last, &data_fake, stopparen, | ||
216 | - recursed_depth, NULL, f, depth+1); | ||
217 | + recursed_depth, NULL, f, depth+1, | ||
218 | + mutate_ok); | ||
219 | if (scan->flags) { | ||
220 | if ( deltanext < 0 | ||
221 | || deltanext > (I32) U8_MAX | ||
222 | @@ -6114,7 +6129,7 @@ Perl_re_printf( aTHX_ "LHS=%" UVuf " RHS=%" UVuf "\n", | ||
223 | *minnextp = study_chunk(pRExC_state, &nscan, minnextp, | ||
224 | &deltanext, last, &data_fake, | ||
225 | stopparen, recursed_depth, NULL, | ||
226 | - f, depth+1); | ||
227 | + f, depth+1, mutate_ok); | ||
228 | if (scan->flags) { | ||
229 | assert(0); /* This code has never been tested since this | ||
230 | is normally not compiled */ | ||
231 | @@ -6282,7 +6297,8 @@ Perl_re_printf( aTHX_ "LHS=%" UVuf " RHS=%" UVuf "\n", | ||
232 | /* optimise study_chunk() for TRIE */ | ||
233 | minnext = study_chunk(pRExC_state, &scan, minlenp, | ||
234 | &deltanext, (regnode *)nextbranch, &data_fake, | ||
235 | - stopparen, recursed_depth, NULL, f, depth+1); | ||
236 | + stopparen, recursed_depth, NULL, f, depth+1, | ||
237 | + mutate_ok); | ||
238 | } | ||
239 | if (nextbranch && PL_regkind[OP(nextbranch)]==BRANCH) | ||
240 | nextbranch= regnext((regnode*)nextbranch); | ||
241 | @@ -8075,7 +8091,7 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count, | ||
242 | &data, -1, 0, NULL, | ||
243 | SCF_DO_SUBSTR | SCF_WHILEM_VISITED_POS | stclass_flag | ||
244 | | (restudied ? SCF_TRIE_DOING_RESTUDY : 0), | ||
245 | - 0); | ||
246 | + 0, TRUE); | ||
247 | |||
248 | |||
249 | CHECK_RESTUDY_GOTO_butfirst(LEAVE_with_name("study_chunk")); | ||
250 | @@ -8204,7 +8220,7 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count, | ||
251 | SCF_DO_STCLASS_AND|SCF_WHILEM_VISITED_POS|(restudied | ||
252 | ? SCF_TRIE_DOING_RESTUDY | ||
253 | : 0), | ||
254 | - 0); | ||
255 | + 0, TRUE); | ||
256 | |||
257 | CHECK_RESTUDY_GOTO_butfirst(NOOP); | ||
258 | |||
259 | diff --git a/t/re/pat.t b/t/re/pat.t | ||
260 | index 6a868f4..2869b58 100644 | ||
261 | --- a/t/re/pat.t | ||
262 | +++ b/t/re/pat.t | ||
263 | @@ -25,7 +25,7 @@ BEGIN { | ||
264 | skip_all('no re module') unless defined &DynaLoader::boot_DynaLoader; | ||
265 | skip_all_without_unicode_tables(); | ||
266 | |||
267 | -plan tests => 864; # Update this when adding/deleting tests. | ||
268 | +plan tests => 873; # Update this when adding/deleting tests. | ||
269 | |||
270 | run_tests() unless caller; | ||
271 | |||
272 | @@ -2115,6 +2115,30 @@ x{0c!}\;\;îçÿ | ||
273 | like(runperl(prog => "$s", stderr => 1), qr/Unmatched \(/); | ||
274 | } | ||
275 | |||
276 | + # gh16947: test regexp corruption (GOSUB) | ||
277 | + { | ||
278 | + fresh_perl_is(q{ | ||
279 | + 'xy' =~ /x(?0)|x(?|y|y)/ && print 'ok' | ||
280 | + }, 'ok', {}, 'gh16947: test regexp corruption (GOSUB)'); | ||
281 | + } | ||
282 | + # gh16947: test fix doesn't break SUSPEND | ||
283 | + { | ||
284 | + fresh_perl_is(q{ 'sx' =~ m{ss++}i; print 'ok' }, | ||
285 | + 'ok', {}, "gh16947: test fix doesn't break SUSPEND"); | ||
286 | + } | ||
287 | + | ||
288 | + # gh17743: more regexp corruption via GOSUB | ||
289 | + { | ||
290 | + fresh_perl_is(q{ | ||
291 | + "0" =~ /((0(?0)|000(?|0000|0000)(?0))|)/; print "ok" | ||
292 | + }, 'ok', {}, 'gh17743: test regexp corruption (1)'); | ||
293 | + | ||
294 | + fresh_perl_is(q{ | ||
295 | + "000000000000" =~ /(0(())(0((?0)())|000(?|\x{ef}\x{bf}\x{bd}|\x{ef}\x{bf}\x{bd}))|)/; | ||
296 | + print "ok" | ||
297 | + }, 'ok', {}, 'gh17743: test regexp corruption (2)'); | ||
298 | + } | ||
299 | + | ||
300 | } # End of sub run_tests | ||
301 | |||
302 | 1; | ||
diff --git a/meta/recipes-devtools/perl/perl_5.30.1.bb b/meta/recipes-devtools/perl/perl_5.30.1.bb index 47b2f9ca65..b53aff1216 100644 --- a/meta/recipes-devtools/perl/perl_5.30.1.bb +++ b/meta/recipes-devtools/perl/perl_5.30.1.bb | |||
@@ -27,6 +27,7 @@ SRC_URI = "https://www.cpan.org/src/5.0/perl-${PV}.tar.gz;name=perl \ | |||
27 | file://CVE-2020-10543.patch \ | 27 | file://CVE-2020-10543.patch \ |
28 | file://CVE-2020-10878_1.patch \ | 28 | file://CVE-2020-10878_1.patch \ |
29 | file://CVE-2020-10878_2.patch \ | 29 | file://CVE-2020-10878_2.patch \ |
30 | file://CVE-2020-12723.patch \ | ||
30 | " | 31 | " |
31 | SRC_URI_append_class-native = " \ | 32 | SRC_URI_append_class-native = " \ |
32 | file://perl-configpm-switch.patch \ | 33 | file://perl-configpm-switch.patch \ |