xref: /OK3568_Linux_fs/yocto/poky/meta/recipes-support/libcroco/files/CVE-2020-12825.patch (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593SmuzhiyunFrom fdf78a4877afa987ba646a8779b513f258e6d04c Mon Sep 17 00:00:00 2001
2*4882a593SmuzhiyunFrom: Michael Catanzaro <mcatanzaro@gnome.org>
3*4882a593SmuzhiyunDate: Fri, 31 Jul 2020 15:21:53 -0500
4*4882a593SmuzhiyunSubject: [PATCH] libcroco: Limit recursion in block and any productions
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun (CVE-2020-12825)
7*4882a593Smuzhiyun
8*4882a593SmuzhiyunIf we don't have any limits, we can recurse forever and overflow the
9*4882a593Smuzhiyunstack.
10*4882a593Smuzhiyun
11*4882a593SmuzhiyunFixes #8
12*4882a593SmuzhiyunThis is per https://gitlab.gnome.org/Archive/libcroco/-/issues/8
13*4882a593Smuzhiyun
14*4882a593Smuzhiyunhttps://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1404
15*4882a593Smuzhiyun
16*4882a593SmuzhiyunCVE: CVE-2020-12825
17*4882a593SmuzhiyunUpstream-Status: Backport [https://gitlab.gnome.org/Archive/libcroco/-/commit/6eb257e5c731c691eb137fca94e916ca73941a5a]
18*4882a593SmuzhiyunComment: No refreshing changes done.
19*4882a593SmuzhiyunSigned-off-by: Saloni Jain <Saloni.Jain@kpit.com>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun---
22*4882a593Smuzhiyun src/cr-parser.c | 44 +++++++++++++++++++++++++++++---------------
23*4882a593Smuzhiyun 1 file changed, 29 insertions(+), 15 deletions(-)
24*4882a593Smuzhiyun
25*4882a593Smuzhiyundiff --git a/src/cr-parser.c b/src/cr-parser.c
26*4882a593Smuzhiyunindex 18c9a01..f4a62e3 100644
27*4882a593Smuzhiyun--- a/src/cr-parser.c
28*4882a593Smuzhiyun+++ b/src/cr-parser.c
29*4882a593Smuzhiyun@@ -136,6 +136,8 @@ struct _CRParserPriv {
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #define CHARS_TAB_SIZE 12
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun+#define RECURSIVE_CALLERS_LIMIT 100
34*4882a593Smuzhiyun+
35*4882a593Smuzhiyun /**
36*4882a593Smuzhiyun  * IS_NUM:
37*4882a593Smuzhiyun  *@a_char: the char to test.
38*4882a593Smuzhiyun@@ -344,9 +346,11 @@ static enum CRStatus cr_parser_parse_selector_core (CRParser * a_this);
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun static enum CRStatus cr_parser_parse_declaration_core (CRParser * a_this);
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun-static enum CRStatus cr_parser_parse_any_core (CRParser * a_this);
43*4882a593Smuzhiyun+static enum CRStatus cr_parser_parse_any_core (CRParser * a_this,
44*4882a593Smuzhiyun+                                               guint      n_calls);
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun-static enum CRStatus cr_parser_parse_block_core (CRParser * a_this);
47*4882a593Smuzhiyun+static enum CRStatus cr_parser_parse_block_core (CRParser * a_this,
48*4882a593Smuzhiyun+                                                 guint      n_calls);
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun static enum CRStatus cr_parser_parse_value_core (CRParser * a_this);
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun@@ -784,7 +788,7 @@ cr_parser_parse_atrule_core (CRParser * a_this)
53*4882a593Smuzhiyun         cr_parser_try_to_skip_spaces_and_comments (a_this);
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun         do {
56*4882a593Smuzhiyun-                status = cr_parser_parse_any_core (a_this);
57*4882a593Smuzhiyun+                status = cr_parser_parse_any_core (a_this, 0);
58*4882a593Smuzhiyun         } while (status == CR_OK);
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun         status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
61*4882a593Smuzhiyun@@ -795,7 +799,7 @@ cr_parser_parse_atrule_core (CRParser * a_this)
62*4882a593Smuzhiyun                 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
63*4882a593Smuzhiyun                                       token);
64*4882a593Smuzhiyun                 token = NULL;
65*4882a593Smuzhiyun-                status = cr_parser_parse_block_core (a_this);
66*4882a593Smuzhiyun+                status = cr_parser_parse_block_core (a_this, 0);
67*4882a593Smuzhiyun                 CHECK_PARSING_STATUS (status,
68*4882a593Smuzhiyun                                       FALSE);
69*4882a593Smuzhiyun                 goto done;
70*4882a593Smuzhiyun@@ -930,11 +934,11 @@ cr_parser_parse_selector_core (CRParser * a_this)
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun         RECORD_INITIAL_POS (a_this, &init_pos);
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun-        status = cr_parser_parse_any_core (a_this);
75*4882a593Smuzhiyun+        status = cr_parser_parse_any_core (a_this, 0);
76*4882a593Smuzhiyun         CHECK_PARSING_STATUS (status, FALSE);
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun         do {
79*4882a593Smuzhiyun-                status = cr_parser_parse_any_core (a_this);
80*4882a593Smuzhiyun+                status = cr_parser_parse_any_core (a_this, 0);
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun         } while (status == CR_OK);
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun@@ -956,10 +960,12 @@ cr_parser_parse_selector_core (CRParser * a_this)
85*4882a593Smuzhiyun  *in chapter 4.1 of the css2 spec.
86*4882a593Smuzhiyun  *block ::= '{' S* [ any | block | ATKEYWORD S* | ';' ]* '}' S*;
87*4882a593Smuzhiyun  *@param a_this the current instance of #CRParser.
88*4882a593Smuzhiyun+ *@param n_calls used to limit recursion depth
89*4882a593Smuzhiyun  *FIXME: code this function.
90*4882a593Smuzhiyun  */
91*4882a593Smuzhiyun static enum CRStatus
92*4882a593Smuzhiyun-cr_parser_parse_block_core (CRParser * a_this)
93*4882a593Smuzhiyun+cr_parser_parse_block_core (CRParser * a_this,
94*4882a593Smuzhiyun+                            guint      n_calls)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun         CRToken *token = NULL;
97*4882a593Smuzhiyun         CRInputPos init_pos;
98*4882a593Smuzhiyun@@ -967,6 +973,9 @@ cr_parser_parse_block_core (CRParser * a_this)
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun+        if (n_calls > RECURSIVE_CALLERS_LIMIT)
103*4882a593Smuzhiyun+                return CR_ERROR;
104*4882a593Smuzhiyun+
105*4882a593Smuzhiyun         RECORD_INITIAL_POS (a_this, &init_pos);
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun         status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
108*4882a593Smuzhiyun@@ -996,13 +1005,13 @@ cr_parser_parse_block_core (CRParser * a_this)
109*4882a593Smuzhiyun         } else if (token->type == CBO_TK) {
110*4882a593Smuzhiyun                 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
111*4882a593Smuzhiyun                 token = NULL;
112*4882a593Smuzhiyun-                status = cr_parser_parse_block_core (a_this);
113*4882a593Smuzhiyun+                status = cr_parser_parse_block_core (a_this, n_calls + 1);
114*4882a593Smuzhiyun                 CHECK_PARSING_STATUS (status, FALSE);
115*4882a593Smuzhiyun                 goto parse_block_content;
116*4882a593Smuzhiyun         } else {
117*4882a593Smuzhiyun                 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
118*4882a593Smuzhiyun                 token = NULL;
119*4882a593Smuzhiyun-                status = cr_parser_parse_any_core (a_this);
120*4882a593Smuzhiyun+                status = cr_parser_parse_any_core (a_this, n_calls + 1);
121*4882a593Smuzhiyun                 CHECK_PARSING_STATUS (status, FALSE);
122*4882a593Smuzhiyun                 goto parse_block_content;
123*4882a593Smuzhiyun         }
124*4882a593Smuzhiyun@@ -1109,7 +1118,7 @@ cr_parser_parse_value_core (CRParser * a_this)
125*4882a593Smuzhiyun                 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
126*4882a593Smuzhiyun                                                token);
127*4882a593Smuzhiyun                 token = NULL;
128*4882a593Smuzhiyun-                status = cr_parser_parse_block_core (a_this);
129*4882a593Smuzhiyun+                status = cr_parser_parse_block_core (a_this, 0);
130*4882a593Smuzhiyun                 CHECK_PARSING_STATUS (status, FALSE);
131*4882a593Smuzhiyun                 ref++;
132*4882a593Smuzhiyun                 goto continue_parsing;
133*4882a593Smuzhiyun@@ -1123,7 +1132,7 @@ cr_parser_parse_value_core (CRParser * a_this)
134*4882a593Smuzhiyun                 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
135*4882a593Smuzhiyun                                                token);
136*4882a593Smuzhiyun                 token = NULL;
137*4882a593Smuzhiyun-                status = cr_parser_parse_any_core (a_this);
138*4882a593Smuzhiyun+                status = cr_parser_parse_any_core (a_this, 0);
139*4882a593Smuzhiyun                 if (status == CR_OK) {
140*4882a593Smuzhiyun                         ref++;
141*4882a593Smuzhiyun                         goto continue_parsing;
142*4882a593Smuzhiyun@@ -1162,10 +1171,12 @@ cr_parser_parse_value_core (CRParser * a_this)
143*4882a593Smuzhiyun  *        | FUNCTION | DASHMATCH | '(' any* ')' | '[' any* ']' ] S*;
144*4882a593Smuzhiyun  *
145*4882a593Smuzhiyun  *@param a_this the current instance of #CRParser.
146*4882a593Smuzhiyun+ *@param n_calls used to limit recursion depth
147*4882a593Smuzhiyun  *@return CR_OK upon successfull completion, an error code otherwise.
148*4882a593Smuzhiyun  */
149*4882a593Smuzhiyun static enum CRStatus
150*4882a593Smuzhiyun-cr_parser_parse_any_core (CRParser * a_this)
151*4882a593Smuzhiyun+cr_parser_parse_any_core (CRParser * a_this,
152*4882a593Smuzhiyun+                          guint      n_calls)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun         CRToken *token1 = NULL,
155*4882a593Smuzhiyun                 *token2 = NULL;
156*4882a593Smuzhiyun@@ -1174,6 +1185,9 @@ cr_parser_parse_any_core (CRParser * a_this)
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun         g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun+        if (n_calls > RECURSIVE_CALLERS_LIMIT)
161*4882a593Smuzhiyun+                return CR_ERROR;
162*4882a593Smuzhiyun+
163*4882a593Smuzhiyun         RECORD_INITIAL_POS (a_this, &init_pos);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun         status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token1);
166*4882a593Smuzhiyun@@ -1212,7 +1226,7 @@ cr_parser_parse_any_core (CRParser * a_this)
167*4882a593Smuzhiyun                  *We consider parameter as being an "any*" production.
168*4882a593Smuzhiyun                  */
169*4882a593Smuzhiyun                 do {
170*4882a593Smuzhiyun-                        status = cr_parser_parse_any_core (a_this);
171*4882a593Smuzhiyun+                        status = cr_parser_parse_any_core (a_this, n_calls + 1);
172*4882a593Smuzhiyun                 } while (status == CR_OK);
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun                 ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
175*4882a593Smuzhiyun@@ -1237,7 +1251,7 @@ cr_parser_parse_any_core (CRParser * a_this)
176*4882a593Smuzhiyun                 }
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun                 do {
179*4882a593Smuzhiyun-                        status = cr_parser_parse_any_core (a_this);
180*4882a593Smuzhiyun+                        status = cr_parser_parse_any_core (a_this, n_calls + 1);
181*4882a593Smuzhiyun                 } while (status == CR_OK);
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun                 ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
184*4882a593Smuzhiyun@@ -1265,7 +1279,7 @@ cr_parser_parse_any_core (CRParser * a_this)
185*4882a593Smuzhiyun                 }
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun                 do {
188*4882a593Smuzhiyun-                        status = cr_parser_parse_any_core (a_this);
189*4882a593Smuzhiyun+                        status = cr_parser_parse_any_core (a_this, n_calls + 1);
190*4882a593Smuzhiyun                 } while (status == CR_OK);
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun                 ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
193