summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/gcc
diff options
context:
space:
mode:
authorYuanjie Huang <yuanjie.huang@windriver.com>2017-02-15 01:38:00 -0800
committerRichard Purdie <richard.purdie@linuxfoundation.org>2017-02-23 12:49:50 -0800
commitbb90ff781b744ecdb0404dd65040e258e4ece978 (patch)
tree9820b0c89fc003974cc2e0ffa6aa78f71957771d /meta/recipes-devtools/gcc
parent04ce3a37b6a4a53d020feb8ec2c21348aff6a81b (diff)
downloadpoky-bb90ff781b744ecdb0404dd65040e258e4ece978.tar.gz
gcc: Fix CVE-2016-6131 in libiberty
[NVD] -- https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-6131 The demangler in GNU Libiberty allows remote attackers to cause a denial of service (infinite loop, stack overflow, and crash) via a cycle in the references of remembered mangled types. [BZ #71696] -- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71696 2016-08-04 Marcel Böhme <boehme.marcel@gmail.com> PR c++/71696 * cplus-dem.c: Prevent infinite recursion when there is a cycle in the referencing of remembered mangled types. (work_stuff): New stack to keep track of the remembered mangled types that are currently being processed. (push_processed_type): New method to push currently processed remembered type onto the stack. (pop_processed_type): New method to pop currently processed remembered type from the stack. (work_stuff_copy_to_from): Copy values of new variables. (delete_non_B_K_work_stuff): Free stack memory. (demangle_args): Push/Pop currently processed remembered type. (do_type): Do not demangle a cyclic reference and push/pop referenced remembered type. cherry-picked from commit of git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@239143 138bc75d-0d04-0410-961f-82ee72b054a4 (From OE-Core rev: 3c288b181a4cfecc80b48994f4dd2df285e4d1d0) (From OE-Core rev: 96a16c4181d18b8580dad243350d589586cb2b07) Signed-off-by: Yuanjie Huang <yuanjie.huang@windriver.com> Signed-off-by: Ross Burton <ross.burton@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-devtools/gcc')
-rw-r--r--meta/recipes-devtools/gcc/gcc-5.4.inc1
-rw-r--r--meta/recipes-devtools/gcc/gcc-5.4/CVE-2016-6131.patch251
-rw-r--r--meta/recipes-devtools/gcc/gcc-6.3.inc4
-rw-r--r--meta/recipes-devtools/gcc/gcc-6.3/CVE-2016-6131.patch251
4 files changed, 506 insertions, 1 deletions
diff --git a/meta/recipes-devtools/gcc/gcc-5.4.inc b/meta/recipes-devtools/gcc/gcc-5.4.inc
index 338530fd6d..b7696756af 100644
--- a/meta/recipes-devtools/gcc/gcc-5.4.inc
+++ b/meta/recipes-devtools/gcc/gcc-5.4.inc
@@ -89,6 +89,7 @@ SRC_URI = "\
89 file://0057-unwind-fix-for-musl.patch \ 89 file://0057-unwind-fix-for-musl.patch \
90 file://0058-fdebug-prefix-map-support-to-remap-relative-path.patch \ 90 file://0058-fdebug-prefix-map-support-to-remap-relative-path.patch \
91 file://0059-libgcc-use-ldflags.patch \ 91 file://0059-libgcc-use-ldflags.patch \
92 file://CVE-2016-6131.patch \
92" 93"
93 94
94BACKPORTS = "" 95BACKPORTS = ""
diff --git a/meta/recipes-devtools/gcc/gcc-5.4/CVE-2016-6131.patch b/meta/recipes-devtools/gcc/gcc-5.4/CVE-2016-6131.patch
new file mode 100644
index 0000000000..88524c342e
--- /dev/null
+++ b/meta/recipes-devtools/gcc/gcc-5.4/CVE-2016-6131.patch
@@ -0,0 +1,251 @@
1From b3f6b32165d3f437bd0ac6269c3c499b68ecf036 Mon Sep 17 00:00:00 2001
2From: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
3Date: Thu, 4 Aug 2016 16:53:18 +0000
4Subject: [PATCH] Fix for PR71696 in Libiberty Demangler
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9[BZ #71696] -- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71696
10
112016-08-04 Marcel Böhme <boehme.marcel@gmail.com>
12
13 PR c++/71696
14 * cplus-dem.c: Prevent infinite recursion when there is a cycle
15 in the referencing of remembered mangled types.
16 (work_stuff): New stack to keep track of the remembered mangled
17 types that are currently being processed.
18 (push_processed_type): New method to push currently processed
19 remembered type onto the stack.
20 (pop_processed_type): New method to pop currently processed
21 remembered type from the stack.
22 (work_stuff_copy_to_from): Copy values of new variables.
23 (delete_non_B_K_work_stuff): Free stack memory.
24 (demangle_args): Push/Pop currently processed remembered type.
25 (do_type): Do not demangle a cyclic reference and push/pop
26 referenced remembered type.
27
28cherry-picked from commit of
29git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@239143 138bc75d-0d04-0410-961f-82ee72b054a4
30
31Upstream-Status: Backport [master]
32CVE: CVE-2016-6131
33Signed-off-by: Yuanjie Huang <yuanjie.huang@windriver.com>
34---
35 libiberty/ChangeLog | 17 ++++++++
36 libiberty/cplus-dem.c | 78 ++++++++++++++++++++++++++++++++---
37 libiberty/testsuite/demangle-expected | 18 ++++++++
38 3 files changed, 108 insertions(+), 5 deletions(-)
39
40diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
41index 9859ad3..7939480 100644
42--- a/libiberty/ChangeLog
43+++ b/libiberty/ChangeLog
44@@ -1,3 +1,20 @@
45+2016-08-04 Marcel Böhme <boehme.marcel@gmail.com>
46+
47+ PR c++/71696
48+ * cplus-dem.c: Prevent infinite recursion when there is a cycle
49+ in the referencing of remembered mangled types.
50+ (work_stuff): New stack to keep track of the remembered mangled
51+ types that are currently being processed.
52+ (push_processed_type): New method to push currently processed
53+ remembered type onto the stack.
54+ (pop_processed_type): New method to pop currently processed
55+ remembered type from the stack.
56+ (work_stuff_copy_to_from): Copy values of new variables.
57+ (delete_non_B_K_work_stuff): Free stack memory.
58+ (demangle_args): Push/Pop currently processed remembered type.
59+ (do_type): Do not demangle a cyclic reference and push/pop
60+ referenced remembered type.
61+
62 2016-06-03 Release Manager
63
64 * GCC 5.4.0 released.
65diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c
66index 7514e57..f21e630 100644
67--- a/libiberty/cplus-dem.c
68+++ b/libiberty/cplus-dem.c
69@@ -144,6 +144,9 @@ struct work_stuff
70 string* previous_argument; /* The last function argument demangled. */
71 int nrepeats; /* The number of times to repeat the previous
72 argument. */
73+ int *proctypevec; /* Indices of currently processed remembered typevecs. */
74+ int proctypevec_size;
75+ int nproctypes;
76 };
77
78 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
79@@ -435,6 +438,10 @@ iterate_demangle_function (struct work_stuff *,
80
81 static void remember_type (struct work_stuff *, const char *, int);
82
83+static void push_processed_type (struct work_stuff *, int);
84+
85+static void pop_processed_type (struct work_stuff *);
86+
87 static void remember_Btype (struct work_stuff *, const char *, int, int);
88
89 static int register_Btype (struct work_stuff *);
90@@ -1301,6 +1308,10 @@ work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
91 memcpy (to->btypevec[i], from->btypevec[i], len);
92 }
93
94+ if (from->proctypevec)
95+ to->proctypevec =
96+ XDUPVEC (int, from->proctypevec, from->proctypevec_size);
97+
98 if (from->ntmpl_args)
99 to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
100
101@@ -1329,11 +1340,17 @@ delete_non_B_K_work_stuff (struct work_stuff *work)
102 /* Discard the remembered types, if any. */
103
104 forget_types (work);
105- if (work -> typevec != NULL)
106+ if (work->typevec != NULL)
107 {
108- free ((char *) work -> typevec);
109- work -> typevec = NULL;
110- work -> typevec_size = 0;
111+ free ((char *) work->typevec);
112+ work->typevec = NULL;
113+ work->typevec_size = 0;
114+ }
115+ if (work->proctypevec != NULL)
116+ {
117+ free (work->proctypevec);
118+ work->proctypevec = NULL;
119+ work->proctypevec_size = 0;
120 }
121 if (work->tmpl_argvec)
122 {
123@@ -3552,6 +3569,8 @@ static int
124 do_type (struct work_stuff *work, const char **mangled, string *result)
125 {
126 int n;
127+ int i;
128+ int is_proctypevec;
129 int done;
130 int success;
131 string decl;
132@@ -3564,6 +3583,7 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
133
134 done = 0;
135 success = 1;
136+ is_proctypevec = 0;
137 while (success && !done)
138 {
139 int member;
140@@ -3616,8 +3636,15 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
141 success = 0;
142 }
143 else
144+ for (i = 0; i < work->nproctypes; i++)
145+ if (work -> proctypevec [i] == n)
146+ success = 0;
147+
148+ if (success)
149 {
150- remembered_type = work -> typevec[n];
151+ is_proctypevec = 1;
152+ push_processed_type (work, n);
153+ remembered_type = work->typevec[n];
154 mangled = &remembered_type;
155 }
156 break;
157@@ -3840,6 +3867,9 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
158 string_delete (result);
159 string_delete (&decl);
160
161+ if (is_proctypevec)
162+ pop_processed_type (work);
163+
164 if (success)
165 /* Assume an integral type, if we're not sure. */
166 return (int) ((tk == tk_none) ? tk_integral : tk);
167@@ -4252,6 +4282,41 @@ do_arg (struct work_stuff *work, const char **mangled, string *result)
168 }
169
170 static void
171+push_processed_type (struct work_stuff *work, int typevec_index)
172+{
173+ if (work->nproctypes >= work->proctypevec_size)
174+ {
175+ if (!work->proctypevec_size)
176+ {
177+ work->proctypevec_size = 4;
178+ work->proctypevec = XNEWVEC (int, work->proctypevec_size);
179+ }
180+ else
181+ {
182+ if (work->proctypevec_size < 16)
183+ /* Double when small. */
184+ work->proctypevec_size *= 2;
185+ else
186+ {
187+ /* Grow slower when large. */
188+ if (work->proctypevec_size > (INT_MAX / 3) * 2)
189+ xmalloc_failed (INT_MAX);
190+ work->proctypevec_size = (work->proctypevec_size * 3 / 2);
191+ }
192+ work->proctypevec
193+ = XRESIZEVEC (int, work->proctypevec, work->proctypevec_size);
194+ }
195+ }
196+ work->proctypevec [work->nproctypes++] = typevec_index;
197+}
198+
199+static void
200+pop_processed_type (struct work_stuff *work)
201+{
202+ work->nproctypes--;
203+}
204+
205+static void
206 remember_type (struct work_stuff *work, const char *start, int len)
207 {
208 char *tem;
209@@ -4515,10 +4580,13 @@ demangle_args (struct work_stuff *work, const char **mangled,
210 {
211 string_append (declp, ", ");
212 }
213+ push_processed_type (work, t);
214 if (!do_arg (work, &tem, &arg))
215 {
216+ pop_processed_type (work);
217 return (0);
218 }
219+ pop_processed_type (work);
220 if (PRINT_ARG_TYPES)
221 {
222 string_appends (declp, &arg);
223diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
224index 1d8b771..d690b23 100644
225--- a/libiberty/testsuite/demangle-expected
226+++ b/libiberty/testsuite/demangle-expected
227@@ -4429,3 +4429,21 @@ __vt_90000000000cafebabe
228
229 _Z80800000000000000000000
230 _Z80800000000000000000000
231+#
232+# Tests write access violation PR70926
233+
234+0__Ot2m02R5T0000500000
235+0__Ot2m02R5T0000500000
236+#
237+
238+0__GT50000000000_
239+0__GT50000000000_
240+#
241+
242+__t2m05B500000000000000000_
243+__t2m05B500000000000000000_
244+#
245+# Tests stack overflow PR71696
246+
247+__10%0__S4_0T0T0
248+%0<>::%0(%0<>)
249--
2502.9.3
251
diff --git a/meta/recipes-devtools/gcc/gcc-6.3.inc b/meta/recipes-devtools/gcc/gcc-6.3.inc
index ce414720ce..da7a083c08 100644
--- a/meta/recipes-devtools/gcc/gcc-6.3.inc
+++ b/meta/recipes-devtools/gcc/gcc-6.3.inc
@@ -82,7 +82,9 @@ SRC_URI = "\
82 file://0054_all_nopie-all-flags.patch \ 82 file://0054_all_nopie-all-flags.patch \
83 ${BACKPORTS} \ 83 ${BACKPORTS} \
84" 84"
85BACKPORTS = "" 85BACKPORTS = "\
86 file://CVE-2016-6131.patch \
87"
86SRC_URI[md5sum] = "677a7623c7ef6ab99881bc4e048debb6" 88SRC_URI[md5sum] = "677a7623c7ef6ab99881bc4e048debb6"
87SRC_URI[sha256sum] = "f06ae7f3f790fbf0f018f6d40e844451e6bc3b7bc96e128e63b09825c1f8b29f" 89SRC_URI[sha256sum] = "f06ae7f3f790fbf0f018f6d40e844451e6bc3b7bc96e128e63b09825c1f8b29f"
88 90
diff --git a/meta/recipes-devtools/gcc/gcc-6.3/CVE-2016-6131.patch b/meta/recipes-devtools/gcc/gcc-6.3/CVE-2016-6131.patch
new file mode 100644
index 0000000000..e873cc6e85
--- /dev/null
+++ b/meta/recipes-devtools/gcc/gcc-6.3/CVE-2016-6131.patch
@@ -0,0 +1,251 @@
1From 59a0e4bd8391962f62600ae3ac95ab0fba74d464 Mon Sep 17 00:00:00 2001
2From: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
3Date: Thu, 4 Aug 2016 16:53:18 +0000
4Subject: [PATCH] Fix for PR71696 in Libiberty Demangler
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9[BZ #71696] -- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71696
10
112016-08-04 Marcel Böhme <boehme.marcel@gmail.com>
12
13 PR c++/71696
14 * cplus-dem.c: Prevent infinite recursion when there is a cycle
15 in the referencing of remembered mangled types.
16 (work_stuff): New stack to keep track of the remembered mangled
17 types that are currently being processed.
18 (push_processed_type): New method to push currently processed
19 remembered type onto the stack.
20 (pop_processed_type): New method to pop currently processed
21 remembered type from the stack.
22 (work_stuff_copy_to_from): Copy values of new variables.
23 (delete_non_B_K_work_stuff): Free stack memory.
24 (demangle_args): Push/Pop currently processed remembered type.
25 (do_type): Do not demangle a cyclic reference and push/pop
26 referenced remembered type.
27
28cherry-picked from commit of
29git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@239143 138bc75d-0d04-0410-961f-82ee72b054a4
30
31Upstream-Status: Backport [master]
32CVE: CVE-2016-6131
33Signed-off-by: Yuanjie Huang <yuanjie.huang@windriver.com>
34---
35 libiberty/ChangeLog | 17 ++++++++
36 libiberty/cplus-dem.c | 78 ++++++++++++++++++++++++++++++++---
37 libiberty/testsuite/demangle-expected | 18 ++++++++
38 3 files changed, 108 insertions(+), 5 deletions(-)
39
40diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
41index 240138f..adf1d72 100644
42--- a/libiberty/ChangeLog
43+++ b/libiberty/ChangeLog
44@@ -1,3 +1,20 @@
45+2016-08-04 Marcel Böhme <boehme.marcel@gmail.com>
46+
47+ PR c++/71696
48+ * cplus-dem.c: Prevent infinite recursion when there is a cycle
49+ in the referencing of remembered mangled types.
50+ (work_stuff): New stack to keep track of the remembered mangled
51+ types that are currently being processed.
52+ (push_processed_type): New method to push currently processed
53+ remembered type onto the stack.
54+ (pop_processed_type): New method to pop currently processed
55+ remembered type from the stack.
56+ (work_stuff_copy_to_from): Copy values of new variables.
57+ (delete_non_B_K_work_stuff): Free stack memory.
58+ (demangle_args): Push/Pop currently processed remembered type.
59+ (do_type): Do not demangle a cyclic reference and push/pop
60+ referenced remembered type.
61+
62 2016-12-21 Release Manager
63
64 * GCC 6.3.0 released.
65diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c
66index 7514e57..f21e630 100644
67--- a/libiberty/cplus-dem.c
68+++ b/libiberty/cplus-dem.c
69@@ -144,6 +144,9 @@ struct work_stuff
70 string* previous_argument; /* The last function argument demangled. */
71 int nrepeats; /* The number of times to repeat the previous
72 argument. */
73+ int *proctypevec; /* Indices of currently processed remembered typevecs. */
74+ int proctypevec_size;
75+ int nproctypes;
76 };
77
78 #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
79@@ -435,6 +438,10 @@ iterate_demangle_function (struct work_stuff *,
80
81 static void remember_type (struct work_stuff *, const char *, int);
82
83+static void push_processed_type (struct work_stuff *, int);
84+
85+static void pop_processed_type (struct work_stuff *);
86+
87 static void remember_Btype (struct work_stuff *, const char *, int, int);
88
89 static int register_Btype (struct work_stuff *);
90@@ -1301,6 +1308,10 @@ work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
91 memcpy (to->btypevec[i], from->btypevec[i], len);
92 }
93
94+ if (from->proctypevec)
95+ to->proctypevec =
96+ XDUPVEC (int, from->proctypevec, from->proctypevec_size);
97+
98 if (from->ntmpl_args)
99 to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
100
101@@ -1329,11 +1340,17 @@ delete_non_B_K_work_stuff (struct work_stuff *work)
102 /* Discard the remembered types, if any. */
103
104 forget_types (work);
105- if (work -> typevec != NULL)
106+ if (work->typevec != NULL)
107 {
108- free ((char *) work -> typevec);
109- work -> typevec = NULL;
110- work -> typevec_size = 0;
111+ free ((char *) work->typevec);
112+ work->typevec = NULL;
113+ work->typevec_size = 0;
114+ }
115+ if (work->proctypevec != NULL)
116+ {
117+ free (work->proctypevec);
118+ work->proctypevec = NULL;
119+ work->proctypevec_size = 0;
120 }
121 if (work->tmpl_argvec)
122 {
123@@ -3552,6 +3569,8 @@ static int
124 do_type (struct work_stuff *work, const char **mangled, string *result)
125 {
126 int n;
127+ int i;
128+ int is_proctypevec;
129 int done;
130 int success;
131 string decl;
132@@ -3564,6 +3583,7 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
133
134 done = 0;
135 success = 1;
136+ is_proctypevec = 0;
137 while (success && !done)
138 {
139 int member;
140@@ -3616,8 +3636,15 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
141 success = 0;
142 }
143 else
144+ for (i = 0; i < work->nproctypes; i++)
145+ if (work -> proctypevec [i] == n)
146+ success = 0;
147+
148+ if (success)
149 {
150- remembered_type = work -> typevec[n];
151+ is_proctypevec = 1;
152+ push_processed_type (work, n);
153+ remembered_type = work->typevec[n];
154 mangled = &remembered_type;
155 }
156 break;
157@@ -3840,6 +3867,9 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
158 string_delete (result);
159 string_delete (&decl);
160
161+ if (is_proctypevec)
162+ pop_processed_type (work);
163+
164 if (success)
165 /* Assume an integral type, if we're not sure. */
166 return (int) ((tk == tk_none) ? tk_integral : tk);
167@@ -4252,6 +4282,41 @@ do_arg (struct work_stuff *work, const char **mangled, string *result)
168 }
169
170 static void
171+push_processed_type (struct work_stuff *work, int typevec_index)
172+{
173+ if (work->nproctypes >= work->proctypevec_size)
174+ {
175+ if (!work->proctypevec_size)
176+ {
177+ work->proctypevec_size = 4;
178+ work->proctypevec = XNEWVEC (int, work->proctypevec_size);
179+ }
180+ else
181+ {
182+ if (work->proctypevec_size < 16)
183+ /* Double when small. */
184+ work->proctypevec_size *= 2;
185+ else
186+ {
187+ /* Grow slower when large. */
188+ if (work->proctypevec_size > (INT_MAX / 3) * 2)
189+ xmalloc_failed (INT_MAX);
190+ work->proctypevec_size = (work->proctypevec_size * 3 / 2);
191+ }
192+ work->proctypevec
193+ = XRESIZEVEC (int, work->proctypevec, work->proctypevec_size);
194+ }
195+ }
196+ work->proctypevec [work->nproctypes++] = typevec_index;
197+}
198+
199+static void
200+pop_processed_type (struct work_stuff *work)
201+{
202+ work->nproctypes--;
203+}
204+
205+static void
206 remember_type (struct work_stuff *work, const char *start, int len)
207 {
208 char *tem;
209@@ -4515,10 +4580,13 @@ demangle_args (struct work_stuff *work, const char **mangled,
210 {
211 string_append (declp, ", ");
212 }
213+ push_processed_type (work, t);
214 if (!do_arg (work, &tem, &arg))
215 {
216+ pop_processed_type (work);
217 return (0);
218 }
219+ pop_processed_type (work);
220 if (PRINT_ARG_TYPES)
221 {
222 string_appends (declp, &arg);
223diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
224index 157d2ee..8793a0b 100644
225--- a/libiberty/testsuite/demangle-expected
226+++ b/libiberty/testsuite/demangle-expected
227@@ -4491,3 +4491,21 @@ void eat<int*, Foo()::{lambda(auto:1*, auto:2*)#6}>(int*&, Foo()::{lambda(auto:1
228
229 _Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E0_EvRS3_RS5_
230 void eat<int*, void Bar<short>()::{lambda(short*, auto:1*, auto:2*)#2}>(int*&, void Bar<short>()::{lambda(short*, auto:1*, auto:2*)#2}&)
231+#
232+# Tests write access violation PR70926
233+
234+0__Ot2m02R5T0000500000
235+0__Ot2m02R5T0000500000
236+#
237+
238+0__GT50000000000_
239+0__GT50000000000_
240+#
241+
242+__t2m05B500000000000000000_
243+__t2m05B500000000000000000_
244+#
245+# Tests stack overflow PR71696
246+
247+__10%0__S4_0T0T0
248+%0<>::%0(%0<>)
249--
2502.9.3
251