To search for an erroneous pattern like this:
for (i = 0; i < n; i++) {}
...
if (i > n) ...This is wrong because at the end of the loop i equals n and cannot be greater than n. The most simple way to match this is:
gres -A40 "^ for \(" \
"for \( (@V) = @d ;
\1 < @d ;
\1 \+\+ \)
\{.8.\}
@n
if \( \1 > \3 \)"Also, @d has parentheses, that's why we have to use \3, not \2 for back-reference to match the second @d.
For me - I currently have kernel version 2.6.33-rc2 - this results after about 10 seconds in a match (simplified here):
---[ vi drivers/mmc/host/s3cmci.c +1209 ]---
/* Set clock */
for (mci_psc = 0; mci_psc < 255; mci_psc++) {
...
}
if (mci_psc > 255)
mci_psc = 255;
...Quite harmless so I left it. Let's extend the example, similar errors will occur with:
for (i = 0; i != MAX; i++) {}
...
if (i <= MAX) ...To catch such errors we could use a pattern like this:
gres -A40 "^ for \(" \
"for \( (@V) = (@d|@K) ;
\1 (<|\!=) (@d|@K) ;
(\+\+ \1|\1 \+\+|\1 = \1 \+ 1|\1 = 1 \+ \1) \)
\{.8.\}
@n
if \( \1 (>|<=) \5 \)"The @K matches definitions. This did not result in more errors in this kernel version, so lets extend it even more. Similar problems may occur when we have a pattern like:
while (foo() && ++i < MAX && bar()) {}
...
if (baz() || i > MAX) ...This can be matched by:
gres -A40 "^ (for|while) \(" \
"(for \([^;]*;|while \() @...&|@
\+* (@V) (<|\!=) (@d|@w) @&|...@
(; (\+\+ \6|\6 \+\+|\6 = \6 \+ 1|\6 = 1 \+ \6))? \)
\{.8.\}
@n
if \( @...&|@ \6 (>|<=) \8 @&|...@ \)"This results (after about half a minute on my computer) in the additional matches:
---[ vi arch/sparc/mm/init_64.c +786 ]---
...
start += PAGE_SIZE;
while (start < end) {
...
if (...)
break;
start += PAGE_SIZE;
}
if (start > end)
start = end;
...
---[ vi drivers/atm/horizon.c +626 ]---
while (...) ...
...
if (...) ...
...
while (div < CR_MAXD) {
div++;
if (...) {
...
goto got_it;
}
}
got_it:
if (div > CR_MAXD || ...) ...The second one was difficult to see in the output due to a prior while loop. The first one, in contrast, is a false positive: the addition of PAGE_SIZE can cause `start' to be bigger than `end'. In the case of a while loop the chosen pattern with `\+*' allows a postfix increment, but does not ensure that an increment occurs, an addition can occur just as well. We can exclude the false positive by adding an exclusion pattern:
gres -A40 "^ (for|while) \(" \
"while \( @...&|@ (@V) (<|\!=) (@d|@w) @&|...@ \) (\{\{-..\} \n)? \5 ([+*|]=|= \5 \+)@n
if \( @...&|@ \5 (>|<=) \7 @&|...@ \)" \
"(for \([^;]*;|while \() @...&|@
\+* (@V) (<|\!=) (@d|@w) @&|...@
(; (\+\+ \6|\6 \+\+|\6 = \6 \+ 1|\6 = 1 \+ \6))? \)
\{.8.\}
@n
if \( @...&|@ \6 (>|<=) \8 @&|...@ \)"Similarly one can define an erroneous pattern for decrementing loops:
gres -A40 "^ (for|while) \(" \
"while \( @...&|@ (@V) (>|\!=) (@d|@w) @&|...@ \) (\{\{-..\} \n)? \5 (-=|= \5 -)@n
if \( @...&|@ \5 (<|>=) \7 @&|...@ \)" \
"(for \([^;]*;|while \() @...&|@
-* (@V) (>|\!=) (@d|@w) @&|...@
(; (-- \6|\6 --|\6 = \6 - 1|\6 = 1 - \6))? \)
\{.8.\}
@n
if \( @...&|@ \6 (<|>=) \8 @&|...@ \)"