Skip to content

Commit 75a8fff

Browse files
authored
fix: ensure safe text slicing boundaries with multi-byte characters (#631)
1 parent d3beb21 commit 75a8fff

File tree

2 files changed

+192
-2
lines changed

2 files changed

+192
-2
lines changed

src/diagnostics.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,21 @@ impl Diagnostic for DocDiagnostic {
110110
}
111111

112112
fn snippet(&self) -> Option<DiagnosticSnippet<'_>> {
113+
let start_byte_index = self.location.byte_index;
114+
let start_char_len = &self.text_info.text()[start_byte_index..]
115+
.chars()
116+
.next()
117+
.map(|ch| ch.len_utf8())
118+
.unwrap_or(1);
113119
Some(DiagnosticSnippet {
114120
source: Cow::Borrowed(&self.text_info),
115121
highlights: vec![DiagnosticSnippetHighlight {
116122
style: DiagnosticSnippetHighlightStyle::Error,
117123
range: DiagnosticSourceRange {
118-
start: DiagnosticSourcePos::ByteIndex(self.location.byte_index),
119-
end: DiagnosticSourcePos::ByteIndex(self.location.byte_index + 1),
124+
start: DiagnosticSourcePos::ByteIndex(start_byte_index),
125+
end: DiagnosticSourcePos::ByteIndex(
126+
start_byte_index + start_char_len,
127+
),
120128
},
121129
description: None,
122130
}],
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
# mod.ts
2+
// 插件描述文件 `pmimp.json`
3+
export interface 插件描述 {
4+
pmim_version: string;
5+
插件信息: {
6+
名称: string;
7+
描述: string;
8+
版本: string;
9+
URL: string;
10+
};
11+
}
12+
13+
# diagnostics
14+
error[missing-jsdoc]: exported symbol is missing JSDoc documentation
15+
--> /mod.ts:2:1
16+
|
17+
2 | export interface 插件描述 {
18+
| ^
19+
20+
21+
error[missing-jsdoc]: exported symbol is missing JSDoc documentation
22+
--> /mod.ts:3:3
23+
|
24+
3 | pmim_version: string;
25+
| ^
26+
27+
28+
error[missing-jsdoc]: exported symbol is missing JSDoc documentation
29+
--> /mod.ts:4:3
30+
|
31+
4 | 插件信息: {
32+
| ^^
33+
34+
# output.txt
35+
Defined in file:///mod.ts:2:1
36+
37+
interface 插件描述
38+
39+
pmim_version: string
40+
插件信息: { 名称: string; 描述: string; 版本: string; URL: string; }
41+
42+
43+
# output.json
44+
[
45+
{
46+
"name": "插件描述",
47+
"isDefault": false,
48+
"location": {
49+
"filename": "file:///mod.ts",
50+
"line": 2,
51+
"col": 0,
52+
"byteIndex": 35
53+
},
54+
"declarationKind": "export",
55+
"kind": "interface",
56+
"interfaceDef": {
57+
"extends": [],
58+
"constructors": [],
59+
"methods": [],
60+
"properties": [
61+
{
62+
"name": "pmim_version",
63+
"location": {
64+
"filename": "file:///mod.ts",
65+
"line": 3,
66+
"col": 2,
67+
"byteIndex": 69
68+
},
69+
"params": [],
70+
"computed": false,
71+
"optional": false,
72+
"tsType": {
73+
"repr": "string",
74+
"kind": "keyword",
75+
"keyword": "string"
76+
},
77+
"typeParams": []
78+
},
79+
{
80+
"name": "插件信息",
81+
"location": {
82+
"filename": "file:///mod.ts",
83+
"line": 4,
84+
"col": 2,
85+
"byteIndex": 93
86+
},
87+
"params": [],
88+
"computed": false,
89+
"optional": false,
90+
"tsType": {
91+
"repr": "",
92+
"kind": "typeLiteral",
93+
"typeLiteral": {
94+
"constructors": [],
95+
"methods": [],
96+
"properties": [
97+
{
98+
"name": "名称",
99+
"location": {
100+
"filename": "file:///mod.ts",
101+
"line": 5,
102+
"col": 4,
103+
"byteIndex": 113
104+
},
105+
"params": [],
106+
"computed": false,
107+
"optional": false,
108+
"tsType": {
109+
"repr": "string",
110+
"kind": "keyword",
111+
"keyword": "string"
112+
},
113+
"typeParams": []
114+
},
115+
{
116+
"name": "描述",
117+
"location": {
118+
"filename": "file:///mod.ts",
119+
"line": 6,
120+
"col": 4,
121+
"byteIndex": 133
122+
},
123+
"params": [],
124+
"computed": false,
125+
"optional": false,
126+
"tsType": {
127+
"repr": "string",
128+
"kind": "keyword",
129+
"keyword": "string"
130+
},
131+
"typeParams": []
132+
},
133+
{
134+
"name": "版本",
135+
"location": {
136+
"filename": "file:///mod.ts",
137+
"line": 7,
138+
"col": 4,
139+
"byteIndex": 153
140+
},
141+
"params": [],
142+
"computed": false,
143+
"optional": false,
144+
"tsType": {
145+
"repr": "string",
146+
"kind": "keyword",
147+
"keyword": "string"
148+
},
149+
"typeParams": []
150+
},
151+
{
152+
"name": "URL",
153+
"location": {
154+
"filename": "file:///mod.ts",
155+
"line": 8,
156+
"col": 4,
157+
"byteIndex": 173
158+
},
159+
"params": [],
160+
"computed": false,
161+
"optional": false,
162+
"tsType": {
163+
"repr": "string",
164+
"kind": "keyword",
165+
"keyword": "string"
166+
},
167+
"typeParams": []
168+
}
169+
],
170+
"callSignatures": [],
171+
"indexSignatures": []
172+
}
173+
},
174+
"typeParams": []
175+
}
176+
],
177+
"callSignatures": [],
178+
"indexSignatures": [],
179+
"typeParams": []
180+
}
181+
}
182+
]

0 commit comments

Comments
 (0)