Wireshark-dev: Re: [Wireshark-dev] checkett.pl anyone?
From: Dirk Jagdmann <doj@xxxxxxxxx>
Date: Thu, 21 Feb 2013 00:05:17 -0800
Anyone able to create a checkett.pl script to check for this?

Note that checkAPI.pl contains code to check etts, but it is currently disabled, because it generates lots of false positives. I've written a naive approach to also check for etts (see attachment), but using it with the dissector sources again produces a lot of false positives. Lots of dissectors register more than one ett array. They often assign ett values around into local variables, which will again report false positives.

Since the proto_item_add_subtree() function has a DISSECTOR_ASSERT() to check for a valid ett value, that's probably a better approach. It is not a static code analysis, but if our users report on issues, it's easy to fix them.

--
---> Dirk Jagdmann
----> http://cubic.org/~doj
-----> http://llg.cubic.org
#!/usr/bin/env perl

use strict;

die "usage: checkett.pl <file name>+" unless $#ARGV >= 0;

my $ret = 0;
foreach my $fn (@ARGV)
{
    $ret += check_ett($fn);
}
exit !!$ret;

sub check_ett
{
    my ($fn) = @_;
    die "$fn not found" unless -f $fn;

    # read complete file into $c without newlines
    open(A, $fn) or die "could not open $fn: $!";
    my $c='';
    while (<A>)
    {
	chomp;			# remove newline characters
	s!//.+$!!; # remove C++ comments, however this doesn't work if // is used inside a string
	s!^#\s*line\s+\d+.*$!!; # remove #line ...
	next if /^\s+$/;	# skip empty lines
	$c .= $_;		# append to $c
    }
    close(A);

    # remove C comments
    $c =~ s!/\*.*?\*/!!g;

    # remove #if 0
    $c =~ s!#\s*if\s+0.*?#\s*endif!!g;

    my %ett;
    while ($c =~ /proto_item_add_subtree\s*\(\s*\w+\s*,\s*(\w+)\)/g)
    {
	$ett{$1}=1;
    }

    # get ett array variable name
    $c =~ /proto_register_subtree_array\s*\((\w+)\s*,/;
    my $ett_array_name = $1;

    # get ett array
    $c =~ /$ett_array_name\s*\[\d*\]\s*=\s*\{([\w\&,\s\[\]\(\)\.]+)\}/;
    my $ett_array = $1;
    $ett_array =~ s/\&|\s//g;	# remove & and whitespace

    # remove any ett variable used in the array from %ett
    foreach my $e (split(/,/, $ett_array))
    {
	delete $ett{$e};
    }

    # if no entries left in %ett return success
    return 0 if scalar(keys %ett) == 0;

    foreach my $e (keys %ett)
    {
	print "$fn: uninitialized ett variable: $e\n";
    }

    return 1;
}