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