105 lines
2.9 KiB
Perl
Executable file
105 lines
2.9 KiB
Perl
Executable file
#!/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");
|
|
}
|
|
}
|
|
}
|