summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--gnu/local.mk1
-rw-r--r--gnu/packages/gnome.scm16
-rw-r--r--gnu/packages/patches/libcroco-CVE-2020-12825.patch187
3 files changed, 204 insertions, 0 deletions
diff --git a/gnu/local.mk b/gnu/local.mk
index 9e20260ec3..eae602a01e 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1275,6 +1275,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/libcaca-CVE-2021-3410-pt2.patch		\
   %D%/packages/patches/libcanberra-sound-theme-freedesktop.patch \
   %D%/packages/patches/libcanberra-wayland-crash.patch \
+  %D%/packages/patches/libcroco-CVE-2020-12825.patch		\
   %D%/packages/patches/libcyaml-libyaml-compat.patch		\
   %D%/packages/patches/libexpected-nofetch.patch                \
   %D%/packages/patches/libgeotiff-adapt-test-script-for-proj-6.2.patch		\
diff --git a/gnu/packages/gnome.scm b/gnu/packages/gnome.scm
index 5ee28eec03..a0796b0115 100644
--- a/gnu/packages/gnome.scm
+++ b/gnu/packages/gnome.scm
@@ -3227,6 +3227,7 @@ the GNOME desktop environment.")
               (sha256
                (base32
                 "1m110rbj5d2raxcdp4iz0qp172284945awrsbdlq99ksmqsc4zkn"))))
+    (replacement libcroco/fixed)
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)))
@@ -3245,6 +3246,21 @@ XML/CSS rendering engine.")
     ;; LGPLv2.1-only.
     (license license:lgpl2.1)))
 
+(define-public libcroco/fixed
+  (package
+    (inherit libcroco)
+    (name "libcroco")
+    (version "0.6.13")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "mirror://gnome/sources/" name "/"
+                                  (version-major+minor version)  "/"
+                                  name "-" version ".tar.xz"))
+              (sha256
+               (base32
+                "1m110rbj5d2raxcdp4iz0qp172284945awrsbdlq99ksmqsc4zkn"))
+              (patches (search-patches "libcroco-CVE-2020-12825.patch"))))))
+
 (define-public libgsf
   (package
     (name "libgsf")
diff --git a/gnu/packages/patches/libcroco-CVE-2020-12825.patch b/gnu/packages/patches/libcroco-CVE-2020-12825.patch
new file mode 100644
index 0000000000..35005a6a19
--- /dev/null
+++ b/gnu/packages/patches/libcroco-CVE-2020-12825.patch
@@ -0,0 +1,187 @@
+From 7b64eb285dd937b34df71c95188301be50dd1409 Mon Sep 17 00:00:00 2001
+From: Michael Catanzaro <mcatanzaro@gnome.org>
+Date: Wed, 12 Aug 2020 13:54:15 -0500
+Subject: [PATCH] libcroco: Limit recursion in block and any productions
+ (CVE-2020-12825)
+
+If we don't have any limits, we can recurse forever and overflow the
+stack.
+
+This is per https://gitlab.gnome.org/Archive/libcroco/-/issues/8
+
+https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1404
+---
+ src/st/croco/cr-parser.c | 44 ++++++++++++++++++++++++++--------------
+ 1 file changed, 29 insertions(+), 15 deletions(-)
+
+diff --git a/src/st/croco/cr-parser.c b/src/st/croco/cr-parser.c
+index 07f4ed9e8b..8304b75614 100644
+--- a/src/cr-parser.c
++++ b/src/cr-parser.c
+@@ -136,6 +136,8 @@ struct _CRParserPriv {
+ 
+ #define CHARS_TAB_SIZE 12
+ 
++#define RECURSIVE_CALLERS_LIMIT 100
++
+ /**
+  * IS_NUM:
+  *@a_char: the char to test.
+@@ -343,9 +345,11 @@ static enum CRStatus cr_parser_parse_selector_core (CRParser * a_this);
+ 
+ static enum CRStatus cr_parser_parse_declaration_core (CRParser * a_this);
+ 
+-static enum CRStatus cr_parser_parse_any_core (CRParser * a_this);
++static enum CRStatus cr_parser_parse_any_core (CRParser * a_this,
++                                               guint      n_calls);
+ 
+-static enum CRStatus cr_parser_parse_block_core (CRParser * a_this);
++static enum CRStatus cr_parser_parse_block_core (CRParser * a_this,
++                                                 guint      n_calls);
+ 
+ static enum CRStatus cr_parser_parse_value_core (CRParser * a_this);
+ 
+@@ -783,7 +787,7 @@ cr_parser_parse_atrule_core (CRParser * a_this)
+         cr_parser_try_to_skip_spaces_and_comments (a_this);
+ 
+         do {
+-                status = cr_parser_parse_any_core (a_this);
++                status = cr_parser_parse_any_core (a_this, 0);
+         } while (status == CR_OK);
+ 
+         status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
+@@ -794,7 +798,7 @@ cr_parser_parse_atrule_core (CRParser * a_this)
+                 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, 
+                                       token);
+                 token = NULL;
+-                status = cr_parser_parse_block_core (a_this);
++                status = cr_parser_parse_block_core (a_this, 0);
+                 CHECK_PARSING_STATUS (status,
+                                       FALSE);
+                 goto done;
+@@ -929,11 +933,11 @@ cr_parser_parse_selector_core (CRParser * a_this)
+ 
+         RECORD_INITIAL_POS (a_this, &init_pos);
+ 
+-        status = cr_parser_parse_any_core (a_this);
++        status = cr_parser_parse_any_core (a_this, 0);
+         CHECK_PARSING_STATUS (status, FALSE);
+ 
+         do {
+-                status = cr_parser_parse_any_core (a_this);
++                status = cr_parser_parse_any_core (a_this, 0);
+ 
+         } while (status == CR_OK);
+ 
+@@ -955,10 +959,12 @@ cr_parser_parse_selector_core (CRParser * a_this)
+  *in chapter 4.1 of the css2 spec.
+  *block ::= '{' S* [ any | block | ATKEYWORD S* | ';' ]* '}' S*;
+  *@param a_this the current instance of #CRParser.
++ *@param n_calls used to limit recursion depth
+  *FIXME: code this function.
+  */
+ static enum CRStatus
+-cr_parser_parse_block_core (CRParser * a_this)
++cr_parser_parse_block_core (CRParser * a_this,
++                            guint      n_calls)
+ {
+         CRToken *token = NULL;
+         CRInputPos init_pos;
+@@ -966,6 +972,9 @@ cr_parser_parse_block_core (CRParser * a_this)
+ 
+         g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
+ 
++        if (n_calls > RECURSIVE_CALLERS_LIMIT)
++                return CR_ERROR;
++
+         RECORD_INITIAL_POS (a_this, &init_pos);
+ 
+         status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
+@@ -995,13 +1004,13 @@ cr_parser_parse_block_core (CRParser * a_this)
+         } else if (token->type == CBO_TK) {
+                 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+                 token = NULL;
+-                status = cr_parser_parse_block_core (a_this);
++                status = cr_parser_parse_block_core (a_this, n_calls + 1);
+                 CHECK_PARSING_STATUS (status, FALSE);
+                 goto parse_block_content;
+         } else {
+                 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
+                 token = NULL;
+-                status = cr_parser_parse_any_core (a_this);
++                status = cr_parser_parse_any_core (a_this, n_calls + 1);
+                 CHECK_PARSING_STATUS (status, FALSE);
+                 goto parse_block_content;
+         }
+@@ -1108,7 +1117,7 @@ cr_parser_parse_value_core (CRParser * a_this)
+                 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+                                                token);
+                 token = NULL;
+-                status = cr_parser_parse_block_core (a_this);
++                status = cr_parser_parse_block_core (a_this, 0);
+                 CHECK_PARSING_STATUS (status, FALSE);
+                 ref++;
+                 goto continue_parsing;
+@@ -1122,7 +1131,7 @@ cr_parser_parse_value_core (CRParser * a_this)
+                 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
+                                                token);
+                 token = NULL;
+-                status = cr_parser_parse_any_core (a_this);
++                status = cr_parser_parse_any_core (a_this, 0);
+                 if (status == CR_OK) {
+                         ref++;
+                         goto continue_parsing;
+@@ -1161,10 +1170,12 @@ cr_parser_parse_value_core (CRParser * a_this)
+  *        | FUNCTION | DASHMATCH | '(' any* ')' | '[' any* ']' ] S*;
+  *
+  *@param a_this the current instance of #CRParser.
++ *@param n_calls used to limit recursion depth
+  *@return CR_OK upon successfull completion, an error code otherwise.
+  */
+ static enum CRStatus
+-cr_parser_parse_any_core (CRParser * a_this)
++cr_parser_parse_any_core (CRParser * a_this,
++                          guint      n_calls)
+ {
+         CRToken *token1 = NULL,
+                 *token2 = NULL;
+@@ -1173,6 +1184,9 @@ cr_parser_parse_any_core (CRParser * a_this)
+ 
+         g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
+ 
++        if (n_calls > RECURSIVE_CALLERS_LIMIT)
++                return CR_ERROR;
++
+         RECORD_INITIAL_POS (a_this, &init_pos);
+ 
+         status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token1);
+@@ -1211,7 +1225,7 @@ cr_parser_parse_any_core (CRParser * a_this)
+                  *We consider parameter as being an "any*" production.
+                  */
+                 do {
+-                        status = cr_parser_parse_any_core (a_this);
++                        status = cr_parser_parse_any_core (a_this, n_calls + 1);
+                 } while (status == CR_OK);
+ 
+                 ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
+@@ -1236,7 +1250,7 @@ cr_parser_parse_any_core (CRParser * a_this)
+                 }
+ 
+                 do {
+-                        status = cr_parser_parse_any_core (a_this);
++                        status = cr_parser_parse_any_core (a_this, n_calls + 1);
+                 } while (status == CR_OK);
+ 
+                 ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
+@@ -1264,7 +1278,7 @@ cr_parser_parse_any_core (CRParser * a_this)
+                 }
+ 
+                 do {
+-                        status = cr_parser_parse_any_core (a_this);
++                        status = cr_parser_parse_any_core (a_this, n_calls + 1);
+                 } while (status == CR_OK);
+ 
+                 ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
+-- 
+GitLab
+