Skip to content

Commit 5714811

Browse files
committed
Rust: fix panic when the last character in a range is multi-byte
1 parent 1953e4f commit 5714811

File tree

4 files changed

+70
-7
lines changed

4 files changed

+70
-7
lines changed

rust/extractor/src/translate/base.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::trap::{Label, TrapClass};
33
use codeql_extractor::trap::{self};
44
use ra_ap_ide_db::line_index::{LineCol, LineIndex};
55
use ra_ap_syntax::ast::RangeItem;
6-
use ra_ap_syntax::{ast, SyntaxError, TextRange, TextSize};
6+
use ra_ap_syntax::{ast, SyntaxError, TextRange};
77
pub trait TextValue {
88
fn try_get_text(&self) -> Option<String>;
99
}
@@ -70,12 +70,21 @@ impl Translator {
7070
}
7171
pub fn location(&self, range: TextRange) -> (LineCol, LineCol) {
7272
let start = self.line_index.line_col(range.start());
73-
let end = self.line_index.line_col(
74-
range
75-
.end()
76-
.checked_sub(TextSize::new(1))
77-
.unwrap_or(range.end()),
78-
);
73+
let range_end = range.end();
74+
// QL end positions are inclusive, while TextRange offsets are exclusive and point at the position
75+
// right after the last character of the range. We need to shift the end offset one character to the left to
76+
// get the right inclusive QL position. Unfortunately, simply subtracting `1` from the end-offset may cause
77+
// the offset to point in the middle of a mult-byte character, resulting in a `panic`. Therefore we use `try_line_col`
78+
// with decreasing offsets to find the start of the last character included in the range.
79+
for i in 1..4 {
80+
if let Some(end) = range_end
81+
.checked_sub(i.into())
82+
.and_then(|x| self.line_index.try_line_col(x))
83+
{
84+
return (start, end);
85+
}
86+
}
87+
let end = self.line_index.line_col(range_end);
7988
(start, end)
8089
}
8190
pub fn emit_location<T: TrapClass>(&mut self, label: Label<T>, node: impl ast::AstNode) {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
| lib.rs:1:1:3:22 | SourceFile |
2+
| lib.rs:2:1:2:8 | Module |
3+
| lib.rs:2:5:2:7 | Name |
4+
| lib.rs:3:1:3:8 | Module |
5+
| lib.rs:3:5:3:8 | Name |
6+
| lib.rs:3:10:3:20 | NameRef |
7+
| lib.rs:3:10:3:20 | Path |
8+
| lib.rs:3:10:3:20 | PathSegment |
9+
| lib.rs:3:10:3:21 | MacroCall |
10+
| utf8-identifiers.rs:1:1:4:6 | foo |
11+
| utf8-identifiers.rs:1:1:12:2 | SourceFile |
12+
| utf8-identifiers.rs:1:4:1:6 | Name |
13+
| utf8-identifiers.rs:1:7:4:1 | GenericParamList |
14+
| utf8-identifiers.rs:2:5:2:6 | Lifetime |
15+
| utf8-identifiers.rs:2:5:2:6 | LifetimeParam |
16+
| utf8-identifiers.rs:3:5:3:5 | Name |
17+
| utf8-identifiers.rs:3:5:3:5 | TypeParam |
18+
| utf8-identifiers.rs:4:2:4:3 | ParamList |
19+
| utf8-identifiers.rs:4:5:4:6 | BlockExpr |
20+
| utf8-identifiers.rs:4:5:4:6 | StmtList |
21+
| utf8-identifiers.rs:6:1:8:1 | Struct |
22+
| utf8-identifiers.rs:6:8:6:8 | Name |
23+
| utf8-identifiers.rs:6:10:8:1 | RecordFieldList |
24+
| utf8-identifiers.rs:7:5:7:5 | Name |
25+
| utf8-identifiers.rs:7:5:7:13 | RecordField |
26+
| utf8-identifiers.rs:7:9:7:13 | NameRef |
27+
| utf8-identifiers.rs:7:9:7:13 | Path |
28+
| utf8-identifiers.rs:7:9:7:13 | PathSegment |
29+
| utf8-identifiers.rs:7:9:7:13 | PathType |
30+
| utf8-identifiers.rs:10:1:10:3 | Visibility |
31+
| utf8-identifiers.rs:10:1:12:1 | main |
32+
| utf8-identifiers.rs:10:8:10:11 | Name |
33+
| utf8-identifiers.rs:10:12:10:13 | ParamList |
34+
| utf8-identifiers.rs:10:15:12:1 | BlockExpr |
35+
| utf8-identifiers.rs:10:15:12:1 | StmtList |
36+
| utf8-identifiers.rs:11:5:11:24 | LetStmt |
37+
| utf8-identifiers.rs:11:9:11:9 | IdentPat |
38+
| utf8-identifiers.rs:11:9:11:9 | Name |
39+
| utf8-identifiers.rs:11:14:11:23 | LiteralExpr |
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import codeql.rust.elements
2+
3+
select any(AstNode n)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
fn foo<
2+
'β,
3+
γ
4+
>() {}
5+
6+
struct X {
7+
δ: usize
8+
}
9+
10+
pub fn main() {
11+
let α = 0.00001f64;
12+
}

0 commit comments

Comments
 (0)