[PATCH v2 1/3] checkpatch: Fix preprocessor guard handling in context tracker functions
From: Julius Werner
Date: Wed May 26 2021 - 22:26:46 EST
The preprocessor guard tracking in ctx_statement_block() is (and seems
to have always been) subtly broken whenever tracking over an #else: the
code is supposed to restore state from the current top of the stack
(like and #endif just without removing it). However, it indexes the
stack at [$#stack - 1]. In Perl, $# does not give you the length of an
array, it gives you the highest valid index. Therefore, the correct
index should just be [$#stack].
The preprocessor guard tracking also gets confused when
ctx_statement_block() was called on a line that is already inside a
preprocessor guard, and steps out of it within the same statement. This
happens commonly with constructs like this:
#if CONFIG_XXX
for (a = first_a(); !a_finished(); a = next_a()) {
#else
for (b = first_b(); !b_finished(); b = next_b()) {
#endif
... loop body ...
The best course of action in this case is to not try to restore any
previous state (which we don't have) at all, so we should just keep our
current state if $#stack is already 0.
Also fix an analogous problem in ctx_block_get().
Signed-off-by: Julius Werner <jwerner@xxxxxxxxxxxx>
---
scripts/checkpatch.pl | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index df8b23dc1eb0af..4aab2450ad629e 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1530,15 +1530,13 @@ sub ctx_statement_block {
my $type = '';
my $level = 0;
- my @stack = ();
+ my @stack = (['', $level]);
my $p;
my $c;
my $len = 0;
my $remainder;
while (1) {
- @stack = (['', 0]) if ($#stack == -1);
-
#warn "CSB: blk<$blk> remain<$remain>\n";
# If we are about to drop off the end, pull in more
# context.
@@ -1572,9 +1570,9 @@ sub ctx_statement_block {
# Handle nested #if/#else.
if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) {
push(@stack, [ $type, $level ]);
- } elsif ($remainder =~ /^#\s*(?:else|elif)\b/) {
- ($type, $level) = @{$stack[$#stack - 1]};
- } elsif ($remainder =~ /^#\s*endif\b/) {
+ } elsif ($remainder =~ /^#\s*(?:else|elif)\b/ && $#stack > 0) {
+ ($type, $level) = @{$stack[$#stack]};
+ } elsif ($remainder =~ /^#\s*endif\b/ && $#stack > 0) {
($type, $level) = @{pop(@stack)};
}
@@ -1744,9 +1742,9 @@ sub ctx_block_get {
# Handle nested #if/#else.
if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
push(@stack, $level);
- } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
- $level = $stack[$#stack - 1];
- } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
+ } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/ && $#stack > 0) {
+ $level = $stack[$#stack];
+ } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/ && $#stack > 0) {
$level = pop(@stack);
}
--
2.29.2