From 5924f9f81076bda203fd7075342d40c26cf180d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 12 Nov 2014 22:27:18 +0100 Subject: [PATCH] Add script to find malloc() not followed by init --- scripts/malloc-init.pl | 70 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100755 scripts/malloc-init.pl diff --git a/scripts/malloc-init.pl b/scripts/malloc-init.pl new file mode 100755 index 000000000..1fa1cf315 --- /dev/null +++ b/scripts/malloc-init.pl @@ -0,0 +1,70 @@ +#!/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/*.c + +use 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( /polarssl_malloc\(/ ) { + if( /$id\s*=.*polarssl_malloc\(/ ) { + push @bad, "$file:$line:$name" if $name; + $name = $1; + $line = $.; + } else { + push @bad, "$file:$.:???" unless /return polarssl_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;