Skip to content

Commit e0f5315

Browse files
authored
Rollup merge of rust-lang#103521 - chenyukang:yukang/fix-103451-avoid-hang, r=jackh726,wesleywiser
Avoid possible infinite loop when next_point reaching the end of file Fixes rust-lang#103451 If we return a span with `lo` = `hi`, `span_to_snippet` will always get `Ok("")`, which may introduce infinite loop if we don't care. This PR make `find_width_of_character_at_span` return `width` with 1, so that `span_to_snippet` will get an `Err`.
2 parents 7b7a8c0 + 6d45529 commit e0f5315

File tree

4 files changed

+46
-10
lines changed

4 files changed

+46
-10
lines changed

compiler/rustc_span/src/source_map.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,8 @@ impl SourceMap {
855855
/// Returns a new span representing the next character after the end-point of this span.
856856
/// Special cases:
857857
/// - if span is a dummy one, returns the same span
858-
/// - if next_point reached the end of source, return span with lo = hi
858+
/// - if next_point reached the end of source, return a span exceeding the end of source,
859+
/// which means sm.span_to_snippet(next_point) will get `Err`
859860
/// - respect multi-byte characters
860861
pub fn next_point(&self, sp: Span) -> Span {
861862
if sp.is_dummy() {
@@ -864,9 +865,6 @@ impl SourceMap {
864865
let start_of_next_point = sp.hi().0;
865866

866867
let width = self.find_width_of_character_at_span(sp, true);
867-
if width == 0 {
868-
return Span::new(sp.hi(), sp.hi(), sp.ctxt(), None);
869-
}
870868
// If the width is 1, then the next span should only contain the next char besides current ending.
871869
// However, in the case of a multibyte character, where the width != 1, the next span should
872870
// span multiple bytes to include the whole character.
@@ -938,7 +936,7 @@ impl SourceMap {
938936
// Ensure indexes are also not malformed.
939937
if start_index > end_index || end_index > source_len - 1 {
940938
debug!("find_width_of_character_at_span: source indexes are malformed");
941-
return 0;
939+
return 1;
942940
}
943941

944942
let src = local_begin.sf.external_src.borrow();

compiler/rustc_span/src/source_map/tests.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -511,16 +511,17 @@ fn test_next_point() {
511511
assert_eq!(span.lo().0, 4);
512512
assert_eq!(span.hi().0, 5);
513513

514-
// A non-empty span at the last byte should advance to create an empty
515-
// span pointing at the end of the file.
514+
// Reaching to the end of file, return a span that will get error with `span_to_snippet`
516515
let span = Span::with_root_ctxt(BytePos(4), BytePos(5));
517516
let span = sm.next_point(span);
518517
assert_eq!(span.lo().0, 5);
519-
assert_eq!(span.hi().0, 5);
518+
assert_eq!(span.hi().0, 6);
519+
assert!(sm.span_to_snippet(span).is_err());
520520

521-
// Empty span pointing just past the last byte.
521+
// Reaching to the end of file, return a span that will get error with `span_to_snippet`
522522
let span = Span::with_root_ctxt(BytePos(5), BytePos(5));
523523
let span = sm.next_point(span);
524524
assert_eq!(span.lo().0, 5);
525-
assert_eq!(span.hi().0, 5);
525+
assert_eq!(span.hi().0, 6);
526+
assert!(sm.span_to_snippet(span).is_err());
526527
}

src/test/ui/parser/issue-103451.rs

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// error-pattern: this file contains an unclosed delimiter
2+
// error-pattern: expected value, found struct `R`
3+
struct R { }
4+
struct S {
5+
x: [u8; R
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error: this file contains an unclosed delimiter
2+
--> $DIR/issue-103451.rs:5:15
3+
|
4+
LL | struct S {
5+
| - unclosed delimiter
6+
LL | x: [u8; R
7+
| - ^
8+
| |
9+
| unclosed delimiter
10+
11+
error: this file contains an unclosed delimiter
12+
--> $DIR/issue-103451.rs:5:15
13+
|
14+
LL | struct S {
15+
| - unclosed delimiter
16+
LL | x: [u8; R
17+
| - ^
18+
| |
19+
| unclosed delimiter
20+
21+
error[E0423]: expected value, found struct `R`
22+
--> $DIR/issue-103451.rs:5:13
23+
|
24+
LL | struct R { }
25+
| ------------ `R` defined here
26+
LL | struct S {
27+
LL | x: [u8; R
28+
| ^ help: use struct literal syntax instead: `R {}`
29+
30+
error: aborting due to 3 previous errors
31+
32+
For more information about this error, try `rustc --explain E0423`.

0 commit comments

Comments
 (0)