diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-04-03 11:49:23 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-04-03 11:49:23 +0000 |
| commit | 5b5ca0bd17febc252eb5f4e8d645c1c2ea060279 (patch) | |
| tree | 7c443e49fe92b2afda322912f23a9e87972359e0 | |
| parent | f6bf7a3e411b90385b796340bd99feff135f9a3a (diff) | |
| parent | feb8ccacba1d4e4ca01a5bd4aed80d4846724d08 (diff) | |
| download | rust-5b5ca0bd17febc252eb5f4e8d645c1c2ea060279.tar.gz rust-5b5ca0bd17febc252eb5f4e8d645c1c2ea060279.zip | |
Merge #11866
11866: fix: Prevent underflow in range conversion r=Veykril a=skyfmmf Previously, when line numbers of Rust spans were converted to LSP ranges, they could underflow resulting in very large line numbers. As an underflow is always wrong, prevent it and use 0 instead. This was noticed when opening an empty file in `src/bin/` of a library crate. In this case rustc produces a span with `"line_start": 0, "line_end": 0` resulting in the underflow. Co-authored-by: Felix Maurer <felix@felix-maurer.de>
| -rw-r--r-- | crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt | 64 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/diagnostics/to_proto.rs | 53 |
2 files changed, 115 insertions, 2 deletions
diff --git a/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt b/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt new file mode 100644 index 00000000000..df00b330b6e --- /dev/null +++ b/crates/rust-analyzer/src/diagnostics/test_data/reasonable_line_numbers_from_empty_file.txt @@ -0,0 +1,64 @@ +[ + MappedRustDiagnostic { + url: Url { + scheme: "file", + cannot_be_a_base: false, + username: "", + password: None, + host: None, + port: None, + path: "/test/src/bin/current.rs", + query: None, + fragment: None, + }, + diagnostic: Diagnostic { + range: Range { + start: Position { + line: 0, + character: 0, + }, + end: Position { + line: 0, + character: 0, + }, + }, + severity: Some( + Error, + ), + code: Some( + String( + "E0601", + ), + ), + code_description: Some( + CodeDescription { + href: Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "doc.rust-lang.org", + ), + ), + port: None, + path: "/error-index.html", + query: None, + fragment: Some( + "E0601", + ), + }, + }, + ), + source: Some( + "rustc", + ), + message: "`main` function not found in crate `current`\nconsider adding a `main` function to `src/bin/current.rs`", + related_information: None, + tags: None, + data: None, + }, + fix: None, + }, +] diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs index dd59923cb34..45e46c1a06b 100644 --- a/crates/rust-analyzer/src/diagnostics/to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs @@ -63,8 +63,14 @@ fn location( // FIXME: this doesn't handle UTF16 offsets correctly let range = lsp_types::Range::new( - lsp_types::Position::new(span.line_start as u32 - 1, span.column_start as u32 - 1), - lsp_types::Position::new(span.line_end as u32 - 1, span.column_end as u32 - 1), + lsp_types::Position::new( + (span.line_start as u32).saturating_sub(1), + (span.column_start as u32).saturating_sub(1), + ), + lsp_types::Position::new( + (span.line_end as u32).saturating_sub(1), + (span.column_end as u32).saturating_sub(1), + ), ); lsp_types::Location { uri, range } @@ -1674,4 +1680,47 @@ mod tests { expect_file!["./test_data/snap_multi_line_fix.txt"], ); } + + #[test] + fn reasonable_line_numbers_from_empty_file() { + check( + r##"{ + "message": "`main` function not found in crate `current`", + "code": { + "code": "E0601", + "explanation": "No `main` function was found in a binary crate.\n\nTo fix this error, add a `main` function:\n\n```\nfn main() {\n // Your program will start here.\n println!(\"Hello world!\");\n}\n```\n\nIf you don't know the basics of Rust, you can look at the\n[Rust Book][rust-book] to get started.\n\n[rust-book]: https://doc.rust-lang.org/book/\n" + }, + "level": "error", + "spans": [ + { + "file_name": "src/bin/current.rs", + "byte_start": 0, + "byte_end": 0, + "line_start": 0, + "line_end": 0, + "column_start": 1, + "column_end": 1, + "is_primary": true, + "text": [], + "label": null, + "suggested_replacement": null, + "suggestion_applicability": null, + "expansion": null + } + ], + "children": [ + { + "message": "consider adding a `main` function to `src/bin/current.rs`", + "code": null, + "level": "note", + "spans": [], + "children": [], + "rendered": null + } + ], + "rendered": "error[E0601]: `main` function not found in crate `current`\n |\n = note: consider adding a `main` function to `src/bin/current.rs`\n\n" + }"##, + expect_file!["./test_data/reasonable_line_numbers_from_empty_file.txt"], + ); + } } |
