#!/usr/bin/perl # Simple fuzz tester for JBIG-KIT decoder -- Markus Kuhn # # Usage example: # # $ ../libjbig/tstcodec t.pbm # $ ./pbmtojbg -f t.pbm | ./jbgfuzz.pl use strict; my $fntst = '/tmp/test.jbg'; # fuzz testing file to be generated my $fntmp = $fntst . '~'; # temporary file (for atomic update) my $fnvalid = '-'; # valid example BIE file my $pbmtools = '.'; # location of jbgtopbm and jbgtopbm85 my $count = "inf"; # how many times shall we try? my @decoders; my $prefix_len = 2000; my $rnd_suffix_len = 2000; my $mutation_rate = 10; # percentage of bytes substituted in prefix while ($_ = shift @ARGV) { if ($_ eq '-c') { $count = shift @ARGV; } elsif ($_ eq '-m') { $mutation_rate = shift @ARGV; } elsif ($_ eq '-p') { $prefix_len = shift @ARGV; } elsif ($_ eq '-r') { $rnd_suffix_len = shift @ARGV; } elsif ($_ eq '-d') { push @decoders, shift @ARGV; } elsif ($_ eq '-t') { $pbmtools = shift @ARGV; } else { $fnvalid = $_; } } @decoders = ('jbgtopbm', 'jbgtopbm85') unless @decoders; # read some bytes from a valid BIE my $valid_prefix; my $in; open($in, "<$fnvalid") || die("$fnvalid: $!\n"); read $in, $valid_prefix, $prefix_len; close $in || die("$fnvalid: $!\n"); # open a source of random bytes my $fn_rnd = '/dev/urandom'; my $rnd; open($rnd, '<', $fn_rnd) || die; for (my $i = 0; $i < $count; $i++) { my $out; open($out, '>', $fntmp) || die("$fntmp: $!\n"); my $prefix; # randomly substitute some prefix bytes with random bytes $prefix = $valid_prefix; if (length($prefix) != $prefix_len) { warn("Truncating requested $prefix_len byte prefix to available ". length($prefix)." bytes.\n"); $prefix_len = length($prefix); } #print "\nB: ".join(',', unpack('C4N3C4', substr($prefix, 0, 20)))."\n"; for (my $p = 0; $p < $prefix_len; $p++) { if (rand(100) < $mutation_rate) { substr($prefix, $p, 1) = chr(int(rand(256))); } } #print "A: ".join(',', unpack('C4N3C4', substr($prefix, 0, 20)))."\n"; # constrain header my ($dl,$d,$p,$res,$xd,$yd,$l0,$mx,$my,$order,$options,$rest) = unpack('C4N3C4a*', $prefix); redo if $xd * $yd > 1e9; # eliminate excessive image sizes $prefix = pack('C4N3C4a*', $dl,$d,$p,$res,$xd,$yd,$l0,$mx,$my, $order,$options,$rest); print $out $prefix; # append random suffix my $data; read $rnd, $data, $rnd_suffix_len; print $out $data; close($out) || die("$fntmp: $!\n"); rename($fntmp, $fntst) || die("mv $fntmp $fntst: $!\n"); # now feed fuzz input into decoder(s) for my $jbgtopbm (@decoders) { printf "%5d: ", $i; $_ = `$pbmtools/$jbgtopbm $fntst /dev/null 2>&1`; my $r = $?; if ($r == 0) { print "no error encountered\n"; next; } elsif ($r == 256) { my $err; if (/(\(error code.*\))/) { $err = $1; print $err, "\n"; } else { die("$_\nno error code found\n"); } } else { die("$_\nreturn value: $r\n"); } } }