mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-16 17:03:35 +00:00
Auto merge of #117827 - Zalathar:bogus-macro-name-span, r=davidtwco
coverage: Avoid creating malformed macro name spans This is a workaround for #117788. It detects a particular scenario where we would create malformed coverage spans that might cause `llvm-cov` to immediately exit with an error, preventing the user from processing coverage reports. The patch has been kept as simple as possible so that it's trivial to backport to beta (or stable) if desired. --- The `maybe_push_macro_name_span` method is trying to detect macro invocations, so that it can split a span into two parts just after the `!` of the invocation. Under some circumstances (probably involving nested macros), it gets confused and produces a span that is larger than the original span, and possibly extends outside its enclosing function and even into an adjacent file. In extreme cases, that can result in malformed coverage mappings that cause `llvm-cov` to fail. For now, we at least want to detect these egregious cases and avoid them, so that coverage reports can still be produced.
This commit is contained in:
commit
b5cdb9631f
@ -381,6 +381,12 @@ impl<'a> CoverageSpansGenerator<'a> {
|
||||
|
||||
let merged_prefix_len = self.curr_original_span.lo() - curr.span.lo();
|
||||
let after_macro_bang = merged_prefix_len + BytePos(visible_macro.as_str().len() as u32 + 1);
|
||||
if self.curr().span.lo() + after_macro_bang > self.curr().span.hi() {
|
||||
// Something is wrong with the macro name span;
|
||||
// return now to avoid emitting malformed mappings.
|
||||
// FIXME(#117788): Track down why this happens.
|
||||
return;
|
||||
}
|
||||
let mut macro_name_cov = curr.clone();
|
||||
self.curr_mut().span = curr.span.with_lo(curr.span.lo() + after_macro_bang);
|
||||
macro_name_cov.span =
|
||||
|
10
tests/coverage/auxiliary/macro_name_span_helper.rs
Normal file
10
tests/coverage/auxiliary/macro_name_span_helper.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// edition: 2021
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! macro_that_defines_a_function {
|
||||
(fn $name:ident () $body:tt) => {
|
||||
fn $name () -> () $body
|
||||
}
|
||||
}
|
||||
|
||||
// Non-executable comment.
|
16
tests/coverage/macro_name_span.cov-map
Normal file
16
tests/coverage/macro_name_span.cov-map
Normal file
@ -0,0 +1,16 @@
|
||||
Function name: macro_name_span::affected_function
|
||||
Raw bytes (9): 0x[01, 01, 00, 01, 01, 06, 1b, 00, 20]
|
||||
Number of files: 1
|
||||
- file 0 => global file 1
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 1
|
||||
- Code(Counter(0)) at (prev + 6, 27) to (start + 0, 32)
|
||||
|
||||
Function name: macro_name_span::main
|
||||
Raw bytes (9): 0x[01, 02, 00, 01, 01, 0b, 01, 02, 02]
|
||||
Number of files: 1
|
||||
- file 0 => global file 2
|
||||
Number of expressions: 0
|
||||
Number of file 0 mappings: 1
|
||||
- Code(Counter(0)) at (prev + 11, 1) to (start + 2, 2)
|
||||
|
39
tests/coverage/macro_name_span.coverage
Normal file
39
tests/coverage/macro_name_span.coverage
Normal file
@ -0,0 +1,39 @@
|
||||
$DIR/auxiliary/macro_name_span_helper.rs:
|
||||
LL| |// edition: 2021
|
||||
LL| |
|
||||
LL| |#[macro_export]
|
||||
LL| |macro_rules! macro_that_defines_a_function {
|
||||
LL| | (fn $name:ident () $body:tt) => {
|
||||
LL| 1| fn $name () -> () $body
|
||||
LL| | }
|
||||
LL| |}
|
||||
LL| |
|
||||
LL| |// Non-executable comment.
|
||||
|
||||
$DIR/macro_name_span.rs:
|
||||
LL| |// edition: 2021
|
||||
LL| |
|
||||
LL| |// Regression test for <https://github.com/rust-lang/rust/issues/117788>.
|
||||
LL| |// Under some circumstances, the heuristics that detect macro name spans can
|
||||
LL| |// get confused and produce incorrect spans beyond the bounds of the span
|
||||
LL| |// being processed.
|
||||
LL| |
|
||||
LL| |// aux-build: macro_name_span_helper.rs
|
||||
LL| |extern crate macro_name_span_helper;
|
||||
LL| |
|
||||
LL| 1|fn main() {
|
||||
LL| 1| affected_function();
|
||||
LL| 1|}
|
||||
LL| |
|
||||
LL| |macro_rules! macro_with_an_unreasonably_and_egregiously_long_name {
|
||||
LL| | () => {
|
||||
LL| | println!("hello");
|
||||
LL| | };
|
||||
LL| |}
|
||||
LL| |
|
||||
LL| |macro_name_span_helper::macro_that_defines_a_function! {
|
||||
LL| | fn affected_function() {
|
||||
LL| | macro_with_an_unreasonably_and_egregiously_long_name!();
|
||||
LL| | }
|
||||
LL| |}
|
||||
|
25
tests/coverage/macro_name_span.rs
Normal file
25
tests/coverage/macro_name_span.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// edition: 2021
|
||||
|
||||
// Regression test for <https://github.com/rust-lang/rust/issues/117788>.
|
||||
// Under some circumstances, the heuristics that detect macro name spans can
|
||||
// get confused and produce incorrect spans beyond the bounds of the span
|
||||
// being processed.
|
||||
|
||||
// aux-build: macro_name_span_helper.rs
|
||||
extern crate macro_name_span_helper;
|
||||
|
||||
fn main() {
|
||||
affected_function();
|
||||
}
|
||||
|
||||
macro_rules! macro_with_an_unreasonably_and_egregiously_long_name {
|
||||
() => {
|
||||
println!("hello");
|
||||
};
|
||||
}
|
||||
|
||||
macro_name_span_helper::macro_that_defines_a_function! {
|
||||
fn affected_function() {
|
||||
macro_with_an_unreasonably_and_egregiously_long_name!();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user