xref: /OK3568_Linux_fs/yocto/poky/meta/recipes-devtools/gcc/gcc/0001-CVE-2021-46195.patch (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1From f10bec5ffa487ad3033ed5f38cfd0fc7d696deab Mon Sep 17 00:00:00 2001
2From: Nick Clifton <nickc@redhat.com>
3Date: Mon, 31 Jan 2022 14:28:42 +0000
4Subject: [PATCH] libiberty: Fix infinite recursion in rust demangler.
5
6libiberty/
7	PR demangler/98886
8	PR demangler/99935
9	* rust-demangle.c (struct rust_demangler): Add a recursion
10	counter.
11	(demangle_path): Increment/decrement the recursion counter upon
12	entry and exit.  Fail if the counter exceeds a fixed limit.
13	(demangle_type): Likewise.
14	(rust_demangle_callback): Initialise the recursion counter,
15	disabling if requested by the option flags.
16
17CVE: CVE-2021-46195
18Upstream-Status: Backport
19[https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=f10bec5ffa487ad3033ed5f38cfd0fc7d696deab]
20Signed-off-by: Pgowda <pgowda.cve@gmail.com>
21---
22 libiberty/rust-demangle.c | 47 ++++++++++++++++++++++++++++++++++-----
23 1 file changed, 41 insertions(+), 6 deletions(-)
24
25diff --git a/libiberty/rust-demangle.c b/libiberty/rust-demangle.c
26index 18c760491bd..3b24d63892a 100644
27--- a/libiberty/rust-demangle.c
28+++ b/libiberty/rust-demangle.c
29@@ -74,6 +74,12 @@ struct rust_demangler
30   /* Rust mangling version, with legacy mangling being -1. */
31   int version;
32
33+  /* Recursion depth.  */
34+  unsigned int recursion;
35+  /* Maximum number of times demangle_path may be called recursively.  */
36+#define RUST_MAX_RECURSION_COUNT  1024
37+#define RUST_NO_RECURSION_LIMIT   ((unsigned int) -1)
38+
39   uint64_t bound_lifetime_depth;
40 };
41
42@@ -671,6 +677,15 @@ demangle_path (struct rust_demangler *rdm, int in_value)
43   if (rdm->errored)
44     return;
45
46+  if (rdm->recursion != RUST_NO_RECURSION_LIMIT)
47+    {
48+      ++ rdm->recursion;
49+      if (rdm->recursion > RUST_MAX_RECURSION_COUNT)
50+	/* FIXME: There ought to be a way to report
51+	   that the recursion limit has been reached.  */
52+	goto fail_return;
53+    }
54+
55   switch (tag = next (rdm))
56     {
57     case 'C':
58@@ -688,10 +703,7 @@ demangle_path (struct rust_demangler *rdm, int in_value)
59     case 'N':
60       ns = next (rdm);
61       if (!ISLOWER (ns) && !ISUPPER (ns))
62-        {
63-          rdm->errored = 1;
64-          return;
65-        }
66+	goto fail_return;
67
68       demangle_path (rdm, in_value);
69
70@@ -776,9 +788,15 @@ demangle_path (struct rust_demangler *rdm, int in_value)
71         }
72       break;
73     default:
74-      rdm->errored = 1;
75-      return;
76+      goto fail_return;
77     }
78+  goto pass_return;
79+
80+ fail_return:
81+  rdm->errored = 1;
82+ pass_return:
83+  if (rdm->recursion != RUST_NO_RECURSION_LIMIT)
84+    -- rdm->recursion;
85 }
86
87 static void
88@@ -870,6 +888,19 @@ demangle_type (struct rust_demangler *rdm)
89       return;
90     }
91
92+   if (rdm->recursion != RUST_NO_RECURSION_LIMIT)
93+    {
94+      ++ rdm->recursion;
95+      if (rdm->recursion > RUST_MAX_RECURSION_COUNT)
96+	/* FIXME: There ought to be a way to report
97+	   that the recursion limit has been reached.  */
98+	{
99+	  rdm->errored = 1;
100+	  -- rdm->recursion;
101+	  return;
102+	}
103+    }
104+
105   switch (tag)
106     {
107     case 'R':
108@@ -1030,6 +1061,9 @@ demangle_type (struct rust_demangler *rdm)
109       rdm->next--;
110       demangle_path (rdm, 0);
111     }
112+
113+  if (rdm->recursion != RUST_NO_RECURSION_LIMIT)
114+    -- rdm->recursion;
115 }
116
117 /* A trait in a trait object may have some "existential projections"
118@@ -1320,6 +1354,7 @@ rust_demangle_callback (const char *mangled, int options,
119   rdm.skipping_printing = 0;
120   rdm.verbose = (options & DMGL_VERBOSE) != 0;
121   rdm.version = 0;
122+  rdm.recursion = (options & DMGL_NO_RECURSE_LIMIT) ? RUST_NO_RECURSION_LIMIT : 0;
123   rdm.bound_lifetime_depth = 0;
124
125   /* Rust symbols always start with _R (v0) or _ZN (legacy). */
126--
1272.27.0
128
129