Skip to content

Commit 4c9143a

Browse files
authored
Rollup merge of rust-lang#119195 - asquared31415:named_asm_labels_fix, r=Amanieu
Make named_asm_labels lint not trigger on unicode and trigger on format args Someone showed me some cursed code that used format args to create named labels, and rustc wasn't linting on that. Additionally while fixing that, I noticed that Unicode alphabetic characters were being used as part of labels, when they are not actually permitted in labels. r? `@Amanieu`
2 parents d00fb50 + 87fed97 commit 4c9143a

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)