summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/gcc/gcc/0005-CVE-2021-42574.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/gcc/gcc/0005-CVE-2021-42574.patch')
-rw-r--r--meta/recipes-devtools/gcc/gcc/0005-CVE-2021-42574.patch575
1 files changed, 575 insertions, 0 deletions
diff --git a/meta/recipes-devtools/gcc/gcc/0005-CVE-2021-42574.patch b/meta/recipes-devtools/gcc/gcc/0005-CVE-2021-42574.patch
new file mode 100644
index 0000000000..6e983a67b6
--- /dev/null
+++ b/meta/recipes-devtools/gcc/gcc/0005-CVE-2021-42574.patch
@@ -0,0 +1,575 @@
1From bef32d4a28595e933f24fef378cf052a30b674a7 Mon Sep 17 00:00:00 2001
2From: David Malcolm <dmalcolm@redhat.com>
3Date: Tue, 2 Nov 2021 15:45:22 -0400
4Subject: [PATCH] libcpp: capture and underline ranges in -Wbidi-chars=
5 [PR103026]
6MIME-Version: 1.0
7Content-Type: text/plain; charset=utf8
8Content-Transfer-Encoding: 8bit
9
10This patch converts the bidi::vec to use a struct so that we can
11capture location_t values for the bidirectional control characters.
12
13Before:
14
15 Wbidi-chars-1.c: In function âmainâ:
16 Wbidi-chars-1.c:6:43: warning: unpaired UTF-8 bidirectional control character detected [-Wbidi-chars=]
17 6 | /*<U+202E> } <U+2066>if (isAdmin)<U+2069> <U+2066> begin admins only */
18 | ^
19 Wbidi-chars-1.c:9:28: warning: unpaired UTF-8 bidirectional control character detected [-Wbidi-chars=]
20 9 | /* end admins only <U+202E> { <U+2066>*/
21 | ^
22
23After:
24
25 Wbidi-chars-1.c: In function âmainâ:
26 Wbidi-chars-1.c:6:43: warning: unpaired UTF-8 bidirectional control characters detected [-Wbidi-chars=]
27 6 | /*<U+202E> } <U+2066>if (isAdmin)<U+2069> <U+2066> begin admins only */
28 | ~~~~~~~~ ~~~~~~~~ ^
29 | | | |
30 | | | end of bidirectional context
31 | U+202E (RIGHT-TO-LEFT OVERRIDE) U+2066 (LEFT-TO-RIGHT ISOLATE)
32 Wbidi-chars-1.c:9:28: warning: unpaired UTF-8 bidirectional control characters detected [-Wbidi-chars=]
33 9 | /* end admins only <U+202E> { <U+2066>*/
34 | ~~~~~~~~ ~~~~~~~~ ^
35 | | | |
36 | | | end of bidirectional context
37 | | U+2066 (LEFT-TO-RIGHT ISOLATE)
38 | U+202E (RIGHT-TO-LEFT OVERRIDE)
39
40Signed-off-by: David Malcolm <dmalcolm@redhat.com>
41
42gcc/testsuite/ChangeLog:
43 PR preprocessor/103026
44 * c-c++-common/Wbidi-chars-ranges.c: New test.
45
46libcpp/ChangeLog:
47 PR preprocessor/103026
48 * lex.c (struct bidi::context): New.
49 (bidi::vec): Convert to a vec of context rather than unsigned
50 char.
51 (bidi::ctx_at): Rename to...
52 (bidi::pop_kind_at): ...this and reimplement for above change.
53 (bidi::current_ctx): Update for change to vec.
54 (bidi::current_ctx_ucn_p): Likewise.
55 (bidi::current_ctx_loc): New.
56 (bidi::on_char): Update for usage of context struct. Add "loc"
57 param and pass it when pushing contexts.
58 (get_location_for_byte_range_in_cur_line): New.
59 (get_bidi_utf8): Rename to...
60 (get_bidi_utf8_1): ...this, reintroducing...
61 (get_bidi_utf8): ...as a wrapper, setting *OUT when the result is
62 not NONE.
63 (get_bidi_ucn): Rename to...
64 (get_bidi_ucn_1): ...this, reintroducing...
65 (get_bidi_ucn): ...as a wrapper, setting *OUT when the result is
66 not NONE.
67 (class unpaired_bidi_rich_location): New.
68 (maybe_warn_bidi_on_close): Use unpaired_bidi_rich_location when
69 reporting on unpaired bidi chars. Split into singular vs plural
70 spellings.
71 (maybe_warn_bidi_on_char): Pass in a location_t rather than a
72 const uchar * and use it when emitting warnings, and when calling
73 bidi::on_char.
74 (_cpp_skip_block_comment): Capture location when kind is not NONE
75 and pass it to maybe_warn_bidi_on_char.
76 (skip_line_comment): Likewise.
77 (forms_identifier_p): Likewise.
78 (lex_raw_string): Likewise.
79 (lex_string): Likewise.
80
81Signed-off-by: David Malcolm <dmalcolm@redhat.com>
82
83CVE: CVE-2021-42574
84Upstream-Status: Backport [https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=bef32d4a28595e933f24fef378cf052a30b674a7]
85Signed-off-by: Pgowda <pgowda.cve@gmail.com>
86
87---
88 .../c-c++-common/Wbidi-chars-ranges.c | 54 ++++
89 libcpp/lex.c | 251 ++++++++++++++----
90 2 files changed, 257 insertions(+), 48 deletions(-)
91 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c
92
93diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c b/gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c
94--- a/gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c 1969-12-31 16:00:00.000000000 -0800
95+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c 2021-12-25 01:39:55.116281847 -0800
96@@ -0,0 +1,54 @@
97+/* PR preprocessor/103026 */
98+/* { dg-do compile } */
99+/* { dg-options "-Wbidi-chars=unpaired -fdiagnostics-show-caret" } */
100+/* Verify that we escape and underline pertinent bidirectional
101+ control characters when quoting the source. */
102+
103+int test_unpaired_bidi () {
104+ int isAdmin = 0;
105+ /*‮ } ⁦if (isAdmin)⁩ ⁦ begin admins only */
106+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */
107+#if 0
108+ { dg-begin-multiline-output "" }
109+ /*<U+202E> } <U+2066>if (isAdmin)<U+2069> <U+2066> begin admins only */
110+ ~~~~~~~~ ~~~~~~~~ ^
111+ | | |
112+ | | end of bidirectional context
113+ U+202E (RIGHT-TO-LEFT OVERRIDE) U+2066 (LEFT-TO-RIGHT ISOLATE)
114+ { dg-end-multiline-output "" }
115+#endif
116+
117+ __builtin_printf("You are an admin.\n");
118+ /* end admins only ‮ { ⁦*/
119+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */
120+#if 0
121+ { dg-begin-multiline-output "" }
122+ /* end admins only <U+202E> { <U+2066>*/
123+ ~~~~~~~~ ~~~~~~~~ ^
124+ | | |
125+ | | end of bidirectional context
126+ | U+2066 (LEFT-TO-RIGHT ISOLATE)
127+ U+202E (RIGHT-TO-LEFT OVERRIDE)
128+ { dg-end-multiline-output "" }
129+#endif
130+
131+ return 0;
132+}
133+
134+int LRE_‪_PDF_\u202c;
135+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
136+#if 0
137+ { dg-begin-multiline-output "" }
138+ int LRE_<U+202A>_PDF_\u202c;
139+ ~~~~~~~~ ^~~~~~
140+ { dg-end-multiline-output "" }
141+#endif
142+
143+const char *s1 = "LRE_‪_PDF_\u202c";
144+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
145+#if 0
146+ { dg-begin-multiline-output "" }
147+ const char *s1 = "LRE_<U+202A>_PDF_\u202c";
148+ ~~~~~~~~ ^~~~~~
149+ { dg-end-multiline-output "" }
150+#endif
151diff --git a/libcpp/lex.c b/libcpp/lex.c
152--- a/libcpp/lex.c 2021-12-25 01:41:16.522868808 -0800
153+++ b/libcpp/lex.c 2021-12-25 06:28:58.530680302 -0800
154@@ -1172,11 +1172,34 @@ namespace bidi {
155 /* All the UTF-8 encodings of bidi characters start with E2. */
156 constexpr uchar utf8_start = 0xe2;
157
158+ struct context
159+ {
160+ context () {}
161+ context (location_t loc, kind k, bool pdf, bool ucn)
162+ : m_loc (loc), m_kind (k), m_pdf (pdf), m_ucn (ucn)
163+ {
164+ }
165+
166+ kind get_pop_kind () const
167+ {
168+ return m_pdf ? kind::PDF : kind::PDI;
169+ }
170+ bool ucn_p () const
171+ {
172+ return m_ucn;
173+ }
174+
175+ location_t m_loc;
176+ kind m_kind;
177+ unsigned m_pdf : 1;
178+ unsigned m_ucn : 1;
179+ };
180+
181 /* A vector holding currently open bidi contexts. We use a char for
182 each context, its LSB is 1 if it represents a PDF context, 0 if it
183 represents a PDI context. The next bit is 1 if this context was open
184 by a bidi character written as a UCN, and 0 when it was UTF-8. */
185- semi_embedded_vec <unsigned char, 16> vec;
186+ semi_embedded_vec <context, 16> vec;
187
188 /* Close the whole comment/identifier/string literal/character constant
189 context. */
190@@ -1193,19 +1216,19 @@ namespace bidi {
191 vec.truncate (len - 1);
192 }
193
194- /* Return the context of the Ith element. */
195- kind ctx_at (unsigned int i)
196+ /* Return the pop kind of the context of the Ith element. */
197+ kind pop_kind_at (unsigned int i)
198 {
199- return (vec[i] & 1) ? kind::PDF : kind::PDI;
200+ return vec[i].get_pop_kind ();
201 }
202
203- /* Return which context is currently opened. */
204+ /* Return the pop kind of the context that is currently opened. */
205 kind current_ctx ()
206 {
207 unsigned int len = vec.count ();
208 if (len == 0)
209 return kind::NONE;
210- return ctx_at (len - 1);
211+ return vec[len - 1].get_pop_kind ();
212 }
213
214 /* Return true if the current context comes from a UCN origin, that is,
215@@ -1214,11 +1237,19 @@ namespace bidi {
216 {
217 unsigned int len = vec.count ();
218 gcc_checking_assert (len > 0);
219- return (vec[len - 1] >> 1) & 1;
220+ return vec[len - 1].m_ucn;
221 }
222
223- /* We've read a bidi char, update the current vector as necessary. */
224- void on_char (kind k, bool ucn_p)
225+ location_t current_ctx_loc ()
226+ {
227+ unsigned int len = vec.count ();
228+ gcc_checking_assert (len > 0);
229+ return vec[len - 1].m_loc;
230+ }
231+
232+ /* We've read a bidi char, update the current vector as necessary.
233+ LOC is only valid when K is not kind::NONE. */
234+ void on_char (kind k, bool ucn_p, location_t loc)
235 {
236 switch (k)
237 {
238@@ -1226,12 +1257,12 @@ namespace bidi {
239 case kind::RLE:
240 case kind::LRO:
241 case kind::RLO:
242- vec.push (ucn_p ? 3u : 1u);
243+ vec.push (context (loc, k, true, ucn_p));
244 break;
245 case kind::LRI:
246 case kind::RLI:
247 case kind::FSI:
248- vec.push (ucn_p ? 2u : 0u);
249+ vec.push (context (loc, k, false, ucn_p));
250 break;
251 /* PDF terminates the scope of the last LRE, RLE, LRO, or RLO
252 whose scope has not yet been terminated. */
253@@ -1245,7 +1276,7 @@ namespace bidi {
254 yet been terminated. */
255 case kind::PDI:
256 for (int i = vec.count () - 1; i >= 0; --i)
257- if (ctx_at (i) == kind::PDI)
258+ if (pop_kind_at (i) == kind::PDI)
259 {
260 vec.truncate (i);
261 break;
262@@ -1295,10 +1326,47 @@ namespace bidi {
263 }
264 }
265
266+/* Get location_t for the range of bytes [START, START + NUM_BYTES)
267+ within the current line in FILE, with the caret at START. */
268+
269+static location_t
270+get_location_for_byte_range_in_cur_line (cpp_reader *pfile,
271+ const unsigned char *const start,
272+ size_t num_bytes)
273+{
274+ gcc_checking_assert (num_bytes > 0);
275+
276+ /* CPP_BUF_COLUMN and linemap_position_for_column both refer
277+ to offsets in bytes, but CPP_BUF_COLUMN is 0-based,
278+ whereas linemap_position_for_column is 1-based. */
279+
280+ /* Get 0-based offsets within the line. */
281+ size_t start_offset = CPP_BUF_COLUMN (pfile->buffer, start);
282+ size_t end_offset = start_offset + num_bytes - 1;
283+
284+ /* Now convert to location_t, where "columns" are 1-based byte offsets. */
285+ location_t start_loc = linemap_position_for_column (pfile->line_table,
286+ start_offset + 1);
287+ location_t end_loc = linemap_position_for_column (pfile->line_table,
288+ end_offset + 1);
289+
290+ if (start_loc == end_loc)
291+ return start_loc;
292+
293+ source_range src_range;
294+ src_range.m_start = start_loc;
295+ src_range.m_finish = end_loc;
296+ location_t combined_loc = COMBINE_LOCATION_DATA (pfile->line_table,
297+ start_loc,
298+ src_range,
299+ NULL);
300+ return combined_loc;
301+}
302+
303 /* Parse a sequence of 3 bytes starting with P and return its bidi code. */
304
305 static bidi::kind
306-get_bidi_utf8 (const unsigned char *const p)
307+get_bidi_utf8_1 (const unsigned char *const p)
308 {
309 gcc_checking_assert (p[0] == bidi::utf8_start);
310
311@@ -1340,10 +1408,25 @@ get_bidi_utf8 (const unsigned char *cons
312 return bidi::kind::NONE;
313 }
314
315+/* Parse a sequence of 3 bytes starting with P and return its bidi code.
316+ If the kind is not NONE, write the location to *OUT.*/
317+
318+static bidi::kind
319+get_bidi_utf8 (cpp_reader *pfile, const unsigned char *const p, location_t *out)
320+{
321+ bidi::kind result = get_bidi_utf8_1 (p);
322+ if (result != bidi::kind::NONE)
323+ {
324+ /* We have a sequence of 3 bytes starting at P. */
325+ *out = get_location_for_byte_range_in_cur_line (pfile, p, 3);
326+ }
327+ return result;
328+}
329+
330 /* Parse a UCN where P points just past \u or \U and return its bidi code. */
331
332 static bidi::kind
333-get_bidi_ucn (const unsigned char *p, bool is_U)
334+get_bidi_ucn_1 (const unsigned char *p, bool is_U)
335 {
336 /* 6.4.3 Universal Character Names
337 \u hex-quad
338@@ -1412,6 +1495,62 @@ get_bidi_ucn (const unsigned char *p, bo
339 return bidi::kind::NONE;
340 }
341
342+/* Parse a UCN where P points just past \u or \U and return its bidi code.
343+ If the kind is not NONE, write the location to *OUT.*/
344+
345+static bidi::kind
346+get_bidi_ucn (cpp_reader *pfile, const unsigned char *p, bool is_U,
347+ location_t *out)
348+{
349+ bidi::kind result = get_bidi_ucn_1 (p, is_U);
350+ if (result != bidi::kind::NONE)
351+ {
352+ const unsigned char *start = p - 2;
353+ size_t num_bytes = 2 + (is_U ? 8 : 4);
354+ *out = get_location_for_byte_range_in_cur_line (pfile, start, num_bytes);
355+ }
356+ return result;
357+}
358+
359+/* Subclass of rich_location for reporting on unpaired UTF-8
360+ bidirectional control character(s).
361+ Escape the source lines on output, and show all unclosed
362+ bidi context, labelling everything. */
363+
364+class unpaired_bidi_rich_location : public rich_location
365+{
366+ public:
367+ class custom_range_label : public range_label
368+ {
369+ public:
370+ label_text get_text (unsigned range_idx) const FINAL OVERRIDE
371+ {
372+ /* range 0 is the primary location; each subsequent range i + 1
373+ is for bidi::vec[i]. */
374+ if (range_idx > 0)
375+ {
376+ const bidi::context &ctxt (bidi::vec[range_idx - 1]);
377+ return label_text::borrow (bidi::to_str (ctxt.m_kind));
378+ }
379+ else
380+ return label_text::borrow (_("end of bidirectional context"));
381+ }
382+ };
383+
384+ unpaired_bidi_rich_location (cpp_reader *pfile, location_t loc)
385+ : rich_location (pfile->line_table, loc, &m_custom_label)
386+ {
387+ set_escape_on_output (true);
388+ for (unsigned i = 0; i < bidi::vec.count (); i++)
389+ add_range (bidi::vec[i].m_loc,
390+ SHOW_RANGE_WITHOUT_CARET,
391+ &m_custom_label);
392+ }
393+
394+ private:
395+ custom_range_label m_custom_label;
396+};
397+
398 /* We're closing a bidi context, that is, we've encountered a newline,
399 are closing a C-style comment, or are at the end of a string literal,
400 character constant, or identifier. Warn if this context was not
401@@ -1427,11 +1566,17 @@ maybe_warn_bidi_on_close (cpp_reader *pf
402 const location_t loc
403 = linemap_position_for_column (pfile->line_table,
404 CPP_BUF_COLUMN (pfile->buffer, p));
405- rich_location rich_loc (pfile->line_table, loc);
406- rich_loc.set_escape_on_output (true);
407- cpp_warning_at (pfile, CPP_W_BIDIRECTIONAL, &rich_loc,
408- "unpaired UTF-8 bidirectional control character "
409- "detected");
410+ unpaired_bidi_rich_location rich_loc (pfile, loc);
411+ /* cpp_callbacks doesn't yet have a way to handle singular vs plural
412+ forms of a diagnostic, so fake it for now. */
413+ if (bidi::vec.count () > 1)
414+ cpp_warning_at (pfile, CPP_W_BIDIRECTIONAL, &rich_loc,
415+ "unpaired UTF-8 bidirectional control characters "
416+ "detected");
417+ else
418+ cpp_warning_at (pfile, CPP_W_BIDIRECTIONAL, &rich_loc,
419+ "unpaired UTF-8 bidirectional control character "
420+ "detected");
421 }
422 /* We're done with this context. */
423 bidi::on_close ();
424@@ -1439,12 +1584,13 @@ maybe_warn_bidi_on_close (cpp_reader *pf
425
426 /* We're at the beginning or in the middle of an identifier/comment/string
427 literal/character constant. Warn if we've encountered a bidi character.
428- KIND says which bidi character it was; P points to it in the character
429- stream. UCN_P is true iff this bidi character was written as a UCN. */
430+ KIND says which bidi control character it was; UCN_P is true iff this bidi
431+ control character was written as a UCN. LOC is the location of the
432+ character, but is only valid if KIND != bidi::kind::NONE. */
433
434 static void
435-maybe_warn_bidi_on_char (cpp_reader *pfile, const uchar *p, bidi::kind kind,
436- bool ucn_p)
437+maybe_warn_bidi_on_char (cpp_reader *pfile, bidi::kind kind,
438+ bool ucn_p, location_t loc)
439 {
440 if (__builtin_expect (kind == bidi::kind::NONE, 1))
441 return;
442@@ -1453,9 +1599,6 @@ maybe_warn_bidi_on_char (cpp_reader *pfi
443
444 if (warn_bidi != bidirectional_none)
445 {
446- const location_t loc
447- = linemap_position_for_column (pfile->line_table,
448- CPP_BUF_COLUMN (pfile->buffer, p));
449 rich_location rich_loc (pfile->line_table, loc);
450 rich_loc.set_escape_on_output (true);
451
452@@ -1467,9 +1610,12 @@ maybe_warn_bidi_on_char (cpp_reader *pfi
453 {
454 if (warn_bidi == bidirectional_unpaired
455 && bidi::current_ctx_ucn_p () != ucn_p)
456- cpp_warning_at (pfile, CPP_W_BIDIRECTIONAL, &rich_loc,
457- "UTF-8 vs UCN mismatch when closing "
458- "a context by \"%s\"", bidi::to_str (kind));
459+ {
460+ rich_loc.add_range (bidi::current_ctx_loc ());
461+ cpp_warning_at (pfile, CPP_W_BIDIRECTIONAL, &rich_loc,
462+ "UTF-8 vs UCN mismatch when closing "
463+ "a context by \"%s\"", bidi::to_str (kind));
464+ }
465 }
466 else if (warn_bidi == bidirectional_any)
467 {
468@@ -1484,7 +1630,7 @@ maybe_warn_bidi_on_char (cpp_reader *pfi
469 }
470 }
471 /* We're done with this context. */
472- bidi::on_char (kind, ucn_p);
473+ bidi::on_char (kind, ucn_p, loc);
474 }
475
476 /* Skip a C-style block comment. We find the end of the comment by
477@@ -1552,8 +1698,9 @@ _cpp_skip_block_comment (cpp_reader *pfi
478 a bidirectional control character. */
479 else if (__builtin_expect (c == bidi::utf8_start, 0) && warn_bidi_p)
480 {
481- bidi::kind kind = get_bidi_utf8 (cur - 1);
482- maybe_warn_bidi_on_char (pfile, cur, kind, /*ucn_p=*/false);
483+ location_t loc;
484+ bidi::kind kind = get_bidi_utf8 (pfile, cur - 1, &loc);
485+ maybe_warn_bidi_on_char (pfile, kind, /*ucn_p=*/false, loc);
486 }
487 }
488
489@@ -1586,9 +1733,9 @@ skip_line_comment (cpp_reader *pfile)
490 {
491 if (__builtin_expect (*buffer->cur == bidi::utf8_start, 0))
492 {
493- bidi::kind kind = get_bidi_utf8 (buffer->cur);
494- maybe_warn_bidi_on_char (pfile, buffer->cur, kind,
495- /*ucn_p=*/false);
496+ location_t loc;
497+ bidi::kind kind = get_bidi_utf8 (pfile, buffer->cur, &loc);
498+ maybe_warn_bidi_on_char (pfile, kind, /*ucn_p=*/false, loc);
499 }
500 buffer->cur++;
501 }
502@@ -1734,9 +1881,9 @@ forms_identifier_p (cpp_reader *pfile, i
503 if (__builtin_expect (*buffer->cur == bidi::utf8_start, 0)
504 && warn_bidi_p)
505 {
506- bidi::kind kind = get_bidi_utf8 (buffer->cur);
507- maybe_warn_bidi_on_char (pfile, buffer->cur, kind,
508- /*ucn_p=*/false);
509+ location_t loc;
510+ bidi::kind kind = get_bidi_utf8 (pfile, buffer->cur, &loc);
511+ maybe_warn_bidi_on_char (pfile, kind, /*ucn_p=*/false, loc);
512 }
513 if (_cpp_valid_utf8 (pfile, &buffer->cur, buffer->rlimit, 1 + !first,
514 state, &s))
515@@ -1748,10 +1895,12 @@ forms_identifier_p (cpp_reader *pfile, i
516 buffer->cur += 2;
517 if (warn_bidi_p)
518 {
519- bidi::kind kind = get_bidi_ucn (buffer->cur,
520- buffer->cur[-1] == 'U');
521- maybe_warn_bidi_on_char (pfile, buffer->cur, kind,
522- /*ucn_p=*/true);
523+ location_t loc;
524+ bidi::kind kind = get_bidi_ucn (pfile,
525+ buffer->cur,
526+ buffer->cur[-1] == 'U',
527+ &loc);
528+ maybe_warn_bidi_on_char (pfile, kind, /*ucn_p=*/true, loc);
529 }
530 if (_cpp_valid_ucn (pfile, &buffer->cur, buffer->rlimit, 1 + !first,
531 state, &s, NULL, NULL))
532@@ -2327,12 +2476,15 @@ lex_raw_string (cpp_reader *pfile, cpp_t
533 }
534 else if (__builtin_expect ((unsigned char) c == bidi::utf8_start, 0)
535 && warn_bidi_p)
536- maybe_warn_bidi_on_char (pfile, pos - 1, get_bidi_utf8 (pos - 1),
537- /*ucn_p=*/false);
538+ {
539+ location_t loc;
540+ bidi::kind kind = get_bidi_utf8 (pfile, cur - 1, &loc);
541+ maybe_warn_bidi_on_char (pfile, kind, /*ucn_p=*/false, loc);
542+ }
543 }
544
545 if (warn_bidi_p)
546- maybe_warn_bidi_on_close (pfile, pos);
547+ maybe_warn_bidi_on_close (pfile, cur);
548
549 if (CPP_OPTION (pfile, user_literals))
550 {
551@@ -2438,8 +2590,10 @@ lex_string (cpp_reader *pfile, cpp_token
552 {
553 if ((cur[0] == 'u' || cur[0] == 'U') && warn_bidi_p)
554 {
555- bidi::kind kind = get_bidi_ucn (cur + 1, cur[0] == 'U');
556- maybe_warn_bidi_on_char (pfile, cur, kind, /*ucn_p=*/true);
557+ location_t loc;
558+ bidi::kind kind = get_bidi_ucn (pfile, cur + 1, cur[0] == 'U',
559+ &loc);
560+ maybe_warn_bidi_on_char (pfile, kind, /*ucn_p=*/true, loc);
561 }
562 cur++;
563 }
564@@ -2467,8 +2621,9 @@ lex_string (cpp_reader *pfile, cpp_token
565 saw_NUL = true;
566 else if (__builtin_expect (c == bidi::utf8_start, 0) && warn_bidi_p)
567 {
568- bidi::kind kind = get_bidi_utf8 (cur - 1);
569- maybe_warn_bidi_on_char (pfile, cur - 1, kind, /*ucn_p=*/false);
570+ location_t loc;
571+ bidi::kind kind = get_bidi_utf8 (pfile, cur - 1, &loc);
572+ maybe_warn_bidi_on_char (pfile, kind, /*ucn_p=*/false, loc);
573 }
574 }
575