Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler hang with incomplete struct literal at end of file #103451

Closed
jruderman opened this issue Oct 23, 2022 · 8 comments · Fixed by #103521
Closed

Compiler hang with incomplete struct literal at end of file #103451

jruderman opened this issue Oct 23, 2022 · 8 comments · Fixed by #103521
Assignees
Labels
C-bug Category: This is a bug. I-hang Issue: The compiler never terminates, due to infinite loops, deadlock, livelock, etc. regression-from-stable-to-nightly Performance or correctness regression from stable to nightly.

Comments

@jruderman
Copy link
Contributor

jruderman commented Oct 23, 2022

This malformed code (playground) hangs the compiler:

struct R { }

struct S {
    x: [u8; R

Found by fuzzing with a modified fuzz-rustc.

The bug's edges

  • R must be defined as a named-field struct (not a tuple struct or unit struct), although it can have 0 fields.
  • R must be the last token to produce the hang:
    • No opening brace (note that braces are required for literals of named-field structs)
    • No closing delimiters
    • Not even a comment

Where it hangs

If I understand mj.sample.txt correctly, the hang occurs in LateResolutionVisitor, with try_lookup_name_relaxed never finishing (while calling various functions such as smart_resolve_context_dependent_help and span_to_snippet)

Additional example

This also hangs. I'm guessing it's the same bug.

struct R { }

fn f() {
    R

Version

rustc --version --verbose:

rustc 1.66.0-nightly (6e95b6da8 2022-10-22)
binary: rustc
commit-hash: 6e95b6da885f42a4e1314595089fa4295e329d11
commit-date: 2022-10-22
host: x86_64-apple-darwin
release: 1.66.0-nightly
LLVM version: 15.0.2

Regression

Bisected with:

cargo-bisect-rustc --start=2022-10-03 --end=nightly-2022-10-23 --preserve --script=./timeout.sh
timeout.sh

#!/bin/bash

# This script is wrong in several ways:
# - It will try to kill processes that might no longer exist
# - It may leave an orphan rustc process after the bisect (because it only kills the shell, not rustc)
# But it seems to be good enough for bisection to work

killall rustc
outershell=$$
(sleep 5; kill $outershell) &
rustc src/main.rs
true

@rustbot label +regression-from-stable-to-nightly +I-hang

@jruderman jruderman added the C-bug Category: This is a bug. label Oct 23, 2022
@rustbot rustbot added I-hang Issue: The compiler never terminates, due to infinite loops, deadlock, livelock, etc. regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Oct 23, 2022
@chenyukang
Copy link
Member

@rustbot claim

@chenyukang
Copy link
Member

I can not reproduce it with latest code, did I missed anything?

cat@LAPTOP-V6U0QKD4:~/code/rust$ cat hang.rs
struct R { }

struct S {
    x: [u8; R
cat@LAPTOP-V6U0QKD4:~/code/rust$ rustc -vV
rustc 1.66.0-nightly (7fcf850d7 2022-10-23)
binary: rustc
commit-hash: 7fcf850d7942804990a1d2e3fe036622a0fe4c74
commit-date: 2022-10-23
host: x86_64-unknown-linux-gnu
release: 1.66.0-nightly
LLVM version: 15.0.2
cat@LAPTOP-V6U0QKD4:~/code/rust$ rustc hang.rs
error: this file contains an unclosed delimiter
 --> hang.rs:4:15
  |
3 | struct S {
  |          - unclosed delimiter
4 |     x: [u8; R
  |        -      ^
  |        |
  |        unclosed delimiter

error[E0423]: expected value, found struct `R`
 --> hang.rs:4:13
  |
1 | struct R { }
  | ------------ `R` defined here
...
4 |     x: [u8; R
  |             ^ help: use struct literal syntax instead: `R {}`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0423`.

@chenyukang
Copy link
Member

chenyukang commented Oct 24, 2022

Great cactch @jruderman

Confirmed the error is only triggered by commit: 6e95b6da885f42a4e1314595089fa4295e329d11

The root cause is I changed the edge corner case in find_width_of_character_at_span:

        // Ensure indexes are also not malformed.
        if start_index > end_index || end_index > source_len - 1 {
            debug!("find_width_of_character_at_span: source indexes are malformed");
            return 0;  // Previous version is  `return 1`
        }

We think next_point won't return a span which outside of source file, so 0 is a valid one, then next_point will always return a valid span, and we get Ok("") from sm.span_to_snippet when reaching the end of source.

So, there is a loop in previous followed_by_brace, which will run infinitely loop:

sp = sm.next_point(sp);

Lucky, my another PR #101908 merged at last day, this PR refactored this function:
518d5eb#diff-2c81e6d8048a31a3ce43f30181aaa037e0ad0076e7aee67792ca993f28c75ac3L1108

@jruderman
Copy link
Contributor Author

Verif, I no longer get a hang after rollup 9be2f35

Do you want to add one or two of these as tests?

@chenyukang
Copy link
Member

Yes, we'd better add a testcase for it.

I'm thinking whether we sould return 1 in find_width_of_character_at_span when reaching to the end of source, so that sm.span_to_snippet may get an error.

@chenyukang
Copy link
Member

This testcase seems not easy to be added:

struct R { }

struct S {
    x: [u8; R //~ ERROR this file contains an unclosed delimiter
    //~| ERROR expected value

If so, the trigger point will do not exist, 😂

@jruderman
Copy link
Contributor Author

@rustbot label -I-prioritize

@rustbot rustbot removed the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label Oct 24, 2022
@estebank
Copy link
Contributor

If so, the trigger point will do not exist

There's an alternative kind of annotation for patterns that should work for this case: // error-pattern:this file contains an unclosed delimiter

GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Nov 7, 2022
…-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`.
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Nov 7, 2022
…-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`.
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Nov 8, 2022
…-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`.
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Nov 8, 2022
…-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`.
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Nov 8, 2022
…-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`.
Manishearth added a commit to Manishearth/rust that referenced this issue Nov 8, 2022
…-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`.
Manishearth added a commit to Manishearth/rust that referenced this issue Nov 8, 2022
…-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`.
Manishearth added a commit to Manishearth/rust that referenced this issue Nov 8, 2022
…-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`.
Manishearth added a commit to Manishearth/rust that referenced this issue Nov 9, 2022
…-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`.
@bors bors closed this as completed in 6d45529 Nov 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. I-hang Issue: The compiler never terminates, due to infinite loops, deadlock, livelock, etc. regression-from-stable-to-nightly Performance or correctness regression from stable to nightly.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants