Skip to content

Commit 87fed97

Browse files
committedDec 21, 2023
Make named_asm_labels lint not trigger on unicode and trigger on format args
1 parent 767453e commit 87fed97

File tree

3 files changed

+162
-24
lines changed

3 files changed

+162
-24
lines changed
 

‎compiler/rustc_lint/src/builtin.rs

+49-13
Original file line numberDiff line numberDiff line change
@@ -2734,10 +2734,13 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
27342734
#[allow(rustc::diagnostic_outside_of_impl)]
27352735
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
27362736
if let hir::Expr {
2737-
kind: hir::ExprKind::InlineAsm(hir::InlineAsm { template_strs, .. }),
2737+
kind: hir::ExprKind::InlineAsm(hir::InlineAsm { template_strs, options, .. }),
27382738
..
27392739
} = expr
27402740
{
2741+
// asm with `options(raw)` does not do replacement with `{` and `}`.
2742+
let raw = options.contains(InlineAsmOptions::RAW);
2743+
27412744
for (template_sym, template_snippet, template_span) in template_strs.iter() {
27422745
let template_str = template_sym.as_str();
27432746
let find_label_span = |needle: &str| -> Option<Span> {
@@ -2763,24 +2766,57 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
27632766
for statement in statements {
27642767
// If there's a comment, trim it from the statement
27652768
let statement = statement.find("//").map_or(statement, |idx| &statement[..idx]);
2769+
2770+
// In this loop, if there is ever a non-label, no labels can come after it.
27662771
let mut start_idx = 0;
2767-
for (idx, _) in statement.match_indices(':') {
2772+
'label_loop: for (idx, _) in statement.match_indices(':') {
27682773
let possible_label = statement[start_idx..idx].trim();
27692774
let mut chars = possible_label.chars();
2770-
let Some(c) = chars.next() else {
2771-
// Empty string means a leading ':' in this section, which is not a label
2772-
break;
2775+
2776+
let Some(start) = chars.next() else {
2777+
// Empty string means a leading ':' in this section, which is not a label.
2778+
break 'label_loop;
27732779
};
2774-
// A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $
2775-
if (c.is_alphabetic() || matches!(c, '.' | '_'))
2776-
&& chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$'))
2777-
{
2778-
found_labels.push(possible_label);
2779-
} else {
2780-
// If we encounter a non-label, there cannot be any further labels, so stop checking
2781-
break;
2780+
2781+
// Whether a { bracket has been seen and its } hasn't been found yet.
2782+
let mut in_bracket = false;
2783+
2784+
// A label starts with an ASCII alphabetic character or . or _
2785+
// A label can also start with a format arg, if it's not a raw asm block.
2786+
if !raw && start == '{' {
2787+
in_bracket = true;
2788+
} else if !(start.is_ascii_alphabetic() || matches!(start, '.' | '_')) {
2789+
break 'label_loop;
2790+
}
2791+
2792+
// Labels continue with ASCII alphanumeric characters, _, or $
2793+
for c in chars {
2794+
// Inside a template format arg, any character is permitted for the puproses of label detection
2795+
// because we assume that it can be replaced with some other valid label string later.
2796+
// `options(raw)` asm blocks cannot have format args, so they are excluded from this special case.
2797+
if !raw && in_bracket {
2798+
if c == '{' {
2799+
// Nested brackets are not allowed in format args, this cannot be a label.
2800+
break 'label_loop;
2801+
}
2802+
2803+
if c == '}' {
2804+
// The end of the format arg.
2805+
in_bracket = false;
2806+
}
2807+
} else if !raw && c == '{' {
2808+
// Start of a format arg.
2809+
in_bracket = true;
2810+
} else {
2811+
if !(c.is_ascii_alphanumeric() || matches!(c, '_' | '$')) {
2812+
// The potential label had an invalid character inside it, it cannot be a label.
2813+
break 'label_loop;
2814+
}
2815+
}
27822816
}
27832817

2818+
// If all characters passed the label checks, this is likely a label.
2819+
found_labels.push(possible_label);
27842820
start_idx = idx + 1;
27852821
}
27862822
}

‎tests/ui/asm/named-asm-labels.rs

+21
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,27 @@ fn main() {
120120
// is there an example that is valid x86 for this test?
121121
asm!(":bbb nop");
122122

123+
// non-ascii characters are not allowed in labels, so should not trigger the lint
124+
asm!("Ù: nop");
125+
asm!("testÙ: nop");
126+
asm!("_Ù_: nop");
127+
128+
// Format arguments should be conservatively assumed to be valid characters in labels
129+
// Would emit `test_rax:` or similar
130+
#[allow(asm_sub_register)]
131+
{
132+
asm!("test_{}: nop", in(reg) 10); //~ ERROR avoid using named labels
133+
}
134+
asm!("test_{}: nop", const 10); //~ ERROR avoid using named labels
135+
asm!("test_{}: nop", sym main); //~ ERROR avoid using named labels
136+
asm!("{}_test: nop", const 10); //~ ERROR avoid using named labels
137+
asm!("test_{}_test: nop", const 10); //~ ERROR avoid using named labels
138+
asm!("{}: nop", const 10); //~ ERROR avoid using named labels
139+
140+
asm!("{uwu}: nop", uwu = const 10); //~ ERROR avoid using named labels
141+
asm!("{0}: nop", const 10); //~ ERROR avoid using named labels
142+
asm!("{1}: nop", "/* {0} */", const 10, const 20); //~ ERROR avoid using named labels
143+
123144
// Test include_str in asm
124145
asm!(include_str!("named-asm-labels.s")); //~ ERROR avoid using named labels
125146

‎tests/ui/asm/named-asm-labels.stderr

+92-11
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,88 @@ LL | ab: nop // ab: does foo
245245
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
246246

247247
error: avoid using named labels in inline assembly
248-
--> $DIR/named-asm-labels.rs:124:14
248+
--> $DIR/named-asm-labels.rs:132:19
249+
|
250+
LL | asm!("test_{}: nop", in(reg) 10);
251+
| ^^^^^^^
252+
|
253+
= help: only local labels of the form `<number>:` should be used in inline asm
254+
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
255+
256+
error: avoid using named labels in inline assembly
257+
--> $DIR/named-asm-labels.rs:134:15
258+
|
259+
LL | asm!("test_{}: nop", const 10);
260+
| ^^^^^^^
261+
|
262+
= help: only local labels of the form `<number>:` should be used in inline asm
263+
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
264+
265+
error: avoid using named labels in inline assembly
266+
--> $DIR/named-asm-labels.rs:135:15
267+
|
268+
LL | asm!("test_{}: nop", sym main);
269+
| ^^^^^^^
270+
|
271+
= help: only local labels of the form `<number>:` should be used in inline asm
272+
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
273+
274+
error: avoid using named labels in inline assembly
275+
--> $DIR/named-asm-labels.rs:136:15
276+
|
277+
LL | asm!("{}_test: nop", const 10);
278+
| ^^^^^^^
279+
|
280+
= help: only local labels of the form `<number>:` should be used in inline asm
281+
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
282+
283+
error: avoid using named labels in inline assembly
284+
--> $DIR/named-asm-labels.rs:137:15
285+
|
286+
LL | asm!("test_{}_test: nop", const 10);
287+
| ^^^^^^^^^^^^
288+
|
289+
= help: only local labels of the form `<number>:` should be used in inline asm
290+
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
291+
292+
error: avoid using named labels in inline assembly
293+
--> $DIR/named-asm-labels.rs:138:15
294+
|
295+
LL | asm!("{}: nop", const 10);
296+
| ^^
297+
|
298+
= help: only local labels of the form `<number>:` should be used in inline asm
299+
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
300+
301+
error: avoid using named labels in inline assembly
302+
--> $DIR/named-asm-labels.rs:140:15
303+
|
304+
LL | asm!("{uwu}: nop", uwu = const 10);
305+
| ^^^^^
306+
|
307+
= help: only local labels of the form `<number>:` should be used in inline asm
308+
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
309+
310+
error: avoid using named labels in inline assembly
311+
--> $DIR/named-asm-labels.rs:141:15
312+
|
313+
LL | asm!("{0}: nop", const 10);
314+
| ^^^
315+
|
316+
= help: only local labels of the form `<number>:` should be used in inline asm
317+
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
318+
319+
error: avoid using named labels in inline assembly
320+
--> $DIR/named-asm-labels.rs:142:15
321+
|
322+
LL | asm!("{1}: nop", "/* {0} */", const 10, const 20);
323+
| ^^^
324+
|
325+
= help: only local labels of the form `<number>:` should be used in inline asm
326+
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
327+
328+
error: avoid using named labels in inline assembly
329+
--> $DIR/named-asm-labels.rs:145:14
249330
|
250331
LL | asm!(include_str!("named-asm-labels.s"));
251332
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -254,21 +335,21 @@ LL | asm!(include_str!("named-asm-labels.s"));
254335
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
255336

256337
warning: avoid using named labels in inline assembly
257-
--> $DIR/named-asm-labels.rs:134:19
338+
--> $DIR/named-asm-labels.rs:155:19
258339
|
259340
LL | asm!("warned: nop");
260341
| ^^^^^^
261342
|
262343
= help: only local labels of the form `<number>:` should be used in inline asm
263344
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
264345
note: the lint level is defined here
265-
--> $DIR/named-asm-labels.rs:132:16
346+
--> $DIR/named-asm-labels.rs:153:16
266347
|
267348
LL | #[warn(named_asm_labels)]
268349
| ^^^^^^^^^^^^^^^^
269350

270351
error: avoid using named labels in inline assembly
271-
--> $DIR/named-asm-labels.rs:143:20
352+
--> $DIR/named-asm-labels.rs:164:20
272353
|
273354
LL | unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
274355
| ^^^^^
@@ -277,7 +358,7 @@ LL | unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noret
277358
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
278359

279360
error: avoid using named labels in inline assembly
280-
--> $DIR/named-asm-labels.rs:149:20
361+
--> $DIR/named-asm-labels.rs:170:20
281362
|
282363
LL | unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
283364
| ^^^^^
@@ -286,7 +367,7 @@ LL | unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noret
286367
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
287368

288369
error: avoid using named labels in inline assembly
289-
--> $DIR/named-asm-labels.rs:157:20
370+
--> $DIR/named-asm-labels.rs:178:20
290371
|
291372
LL | unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) }
292373
| ^^^^^
@@ -295,7 +376,7 @@ LL | unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) }
295376
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
296377

297378
error: avoid using named labels in inline assembly
298-
--> $DIR/named-asm-labels.rs:167:24
379+
--> $DIR/named-asm-labels.rs:188:24
299380
|
300381
LL | unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) }
301382
| ^^^^^
@@ -304,7 +385,7 @@ LL | unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) }
304385
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
305386

306387
error: avoid using named labels in inline assembly
307-
--> $DIR/named-asm-labels.rs:176:15
388+
--> $DIR/named-asm-labels.rs:197:15
308389
|
309390
LL | asm!("closure1: nop");
310391
| ^^^^^^^^
@@ -313,7 +394,7 @@ LL | asm!("closure1: nop");
313394
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
314395

315396
error: avoid using named labels in inline assembly
316-
--> $DIR/named-asm-labels.rs:180:15
397+
--> $DIR/named-asm-labels.rs:201:15
317398
|
318399
LL | asm!("closure2: nop");
319400
| ^^^^^^^^
@@ -322,13 +403,13 @@ LL | asm!("closure2: nop");
322403
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
323404

324405
error: avoid using named labels in inline assembly
325-
--> $DIR/named-asm-labels.rs:190:19
406+
--> $DIR/named-asm-labels.rs:211:19
326407
|
327408
LL | asm!("closure3: nop");
328409
| ^^^^^^^^
329410
|
330411
= help: only local labels of the form `<number>:` should be used in inline asm
331412
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
332413

333-
error: aborting due to 35 previous errors; 1 warning emitted
414+
error: aborting due to 44 previous errors; 1 warning emitted
334415

0 commit comments

Comments
 (0)
Please sign in to comment.