| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 | #!/usr/bin/perl# Check for malloc calls not shortly followed by initialisation.## Known limitations:# - false negative: can't see allocations spanning more than one line# - possible false negatives, see patterns# - false positive: malloc-malloc-init-init is not accepted# - false positives: "non-standard" init functions (eg, the things being# initialised is not the first arg, or initialise struct members)## Since false positives are expected, the results must be manually reviewed.## Typical usage: scripts/malloc-init.pl library/*.cuse warnings;use strict;use utf8;use open qw(:std utf8);my $limit = 7;my $inits = qr/memset|memcpy|_init|fread|base64_..code/;# cases to bear in mind:## 0. foo = malloc(...); memset( foo, ... );# 1. *foo = malloc(...); memset( *foo, ... );# 2. type *foo = malloc(...); memset( foo, ...);# 3. foo = malloc(...); foo_init( (type *) foo );# 4. foo = malloc(...); for(i=0..n) { init( &foo[i] ); }## The chosen patterns are a bit relaxed, but unlikely to cause false positives# in real code (initialising *foo or &foo instead of foo will likely be caught# by functional tests).#my $id = qr/([a-zA-Z-0-9_\->\.]*)/;my $prefix = qr/\s(?:\*?|\&?|\([a-z_]* \*\))\s*/;my $name;my $line;my @bad;die "Usage: $0 file.c [...]\n" unless @ARGV;while (my $file = shift @ARGV){    open my $fh, "<", $file or die "read $file failed: $!\n";    while (<$fh>)    {        if( /mbedtls_malloc\(/ ) {            if( /$id\s*=.*mbedtls_malloc\(/ ) {                push @bad, "$file:$line:$name" if $name;                $name = $1;                $line = $.;            } else {                push @bad, "$file:$.:???" unless /return mbedtls_malloc/;            }        } elsif( $name && /(?:$inits)\($prefix\Q$name\E\b/ ) {            undef $name;        } elsif( $name && $. - $line > $limit ) {            push @bad, "$file:$line:$name";            undef $name;            undef $line;        }    }    close $fh or die;}print "$_\n" for @bad;
 |