#!/usr/bin/perl # # Look for "return xxx" which follows "free xxx". # # use strict; use warnings; use File::Find; # # Callbackup # sub wanted { # We're invoked with every file. Ignore directories. my $file = $File::Find::name; return if ( -d $file ); my $free = 0; my $fLine = ""; my $fc = 0; # # Open the file for reading # open( my $handle, "<", $file ) or die "Failed to open $file - $!"; foreach my $line (<$handle>) { # Remove trailing newline chomp $line; # Do we have a free? stored if ($free) { # If so is this a return-statement? # if ( $line =~ /return(.*)$/ ) { # ignore returns of -E* (i.e. "-ENOPERM", etc) # Ignore returns of 0 / NULL my $o = $1; if ( $o !~ /NULL/ && ( $o !~ /0/ ) && ( $o !~ /^;$/ ) && ( $o !~ /-EN/ ) ) { # Does the return-value reference the same thing # we recorded as the last free'd thing? if ( $o =~ /\Q$free\E/ ) { # Log it. print "File: $file\n"; print "\t$fLine\n"; print "\t$line\n"; } } # OK we hit a return - drop the reference to our # last free'd thing $free = ""; $fLine = ""; } else { # If we hit the end of a block then also reset if ( $line =~ /^\s*}\s*$/ ) { $free = ""; $fLine = ""; } } } else { # We found a free-something. Record the thing that is # free'd and the complete line. if ( $line =~ /free\(([^\)]+)\)/ ) { $free = $1; $fLine = $line; } } } close($handle); } # Run the find operation, calling `wanted` with each file/directory we find. find( { wanted => \&wanted, no_chdir => 1 }, "." ); # # All good # exit 0;