Skip to content

Commit

Permalink
od: incorrect file offsets after first 16 bytes
Browse files Browse the repository at this point in the history
* I observed the file offsets incorrectly jumped from 0 to 17, instead of 0 to 16
* When debugging this I discovered the formatting routines were modifying the value of $data by appending pad bytes
* Fix offsets issue by not modifying the value of $data
* Using global $len in the format routines is also not correct since the input loop was previously changed and $len will always be 1
* Remove global variable $upformat and provide the unpack format directly to unpack()
* Remove unsupported -a flag from the SYNOPSIS
  • Loading branch information
mknos authored Jan 31, 2024
1 parent 2f0ea85 commit 94eaee3
Showing 1 changed file with 44 additions and 26 deletions.
70 changes: 44 additions & 26 deletions bin/od
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use vars qw/ $opt_A $opt_b $opt_c $opt_d $opt_f $opt_i $opt_j $opt_l $opt_N
$opt_o $opt_v $opt_x /;

my ($offset1, $radix, $data, @arr, $len, $fh, $lim);
my ($lastline, $upformat, $pffmt, $strfmt, $ml);
my ($lastline, $pffmt, $strfmt, $ml);

my %charescs = (
0 => ' \0',
Expand Down Expand Up @@ -168,19 +168,17 @@ close $fh;
exit EX_SUCCESS;

sub octal1 {
$upformat = 'C*'; # for -b
$pffmt = '%.3o ';
@arr = unpack($upformat,$data);
@arr = unpack 'C*', $data;
$strfmt = $pffmt x (scalar @arr);
}

sub char1 {
$upformat = 'C*'; # for -c
$pffmt = '%s';
$strfmt = $pffmt;

@arr = ();
my @arr1 = unpack($upformat,$data);
my @arr1 = unpack 'C*', $data;
for my $val (@arr1) {
if (exists $charescs{$val}) {
$arr[0] .= $charescs{$val} . " ";
Expand All @@ -195,52 +193,72 @@ sub char1 {
}

sub udecimal {
$upformat = 'S*'; # for -d
$data .= "\0" if ($len & 1); # zero-fill 16 bit input
if (length($data) & 1) { # pad to 16 bit
@arr = unpack 'S*', $data . "\0";
}
else {
@arr = unpack 'S*', $data;
}
$pffmt = '%5u ';
@arr = unpack($upformat,$data);
$strfmt = $pffmt x (scalar @arr);
}

sub float {
$upformat = 'f*'; # for -f
my $remain = $len % 4;
$data .= "\0" x $remain if ($remain); # zero-fill 32 bit input
my $remain = length($data) % 4;
if ($remain) { # pad to 32 bit
my $pad = "\0" x $remain;
@arr = unpack 'f*', $data . $pad;
}
else {
@arr = unpack 'f*', $data;
}
$pffmt = '%6.6e ';
@arr = unpack($upformat,$data);
$strfmt = $pffmt x (scalar @arr);
}

sub decimal {
$upformat = 's*'; # for -i
$data .= "\0" if ($len & 1); # zero-fill 16 bit input
if (length($data) & 1) { # pad to 16 bit
@arr = unpack 's*', $data . "\0";
}
else {
@arr = unpack 's*', $data;
}
$pffmt = '%5d ';
@arr = unpack($upformat,$data);
$strfmt = $pffmt x (scalar @arr);
}

sub long {
$upformat = 'L*'; # for -l
my $remain = $len % 4;
$data .= "\0" x $remain if ($remain); # zero-fill 32 bit input
my $remain = length($data) % 4;
if ($remain) { # pad to 32 bit
my $pad = "\0" x $remain;
@arr = unpack 'L*', $data . $pad;
}
else {
@arr = unpack 'L*', $data;
}
$pffmt = '%10ld ';
@arr = unpack($upformat,$data);
$strfmt = $pffmt x (scalar @arr);
}

sub octal2 {
$upformat = 'S*'; # for -o
$data .= "\0" if ($len & 1); # zero-fill 16 bit input
if (length($data) & 1) { # pad to 16 bit
@arr = unpack 'S*', $data . "\0";
}
else {
@arr = unpack 'S*', $data;
}
$pffmt = '%.6o ';
@arr = unpack($upformat,$data);
$strfmt = $pffmt x (scalar @arr);
}

sub hex {
$upformat = 'S*'; # for -x
$data .= "\0" if ($len & 1); # zero-fill 16 bit input
if (length($data) & 1) { # pad to 16 bit
@arr = unpack 'S*', $data . "\0";
}
else {
@arr = unpack 'S*', $data;
}
$pffmt = '%.4x ';
@arr = unpack($upformat,$data);
$strfmt = $pffmt x (scalar @arr);
}

Expand All @@ -261,7 +279,7 @@ od - dump files in octal and other formats
=head1 SYNOPSIS
B<od> [ I<-abcdfiloxv> ] [I<-j skip_n_bytes>] [I<-N read_n_bytes>] [ I<-A radix> ] F<filename>
B<od> [ I<-bcdfiloxv> ] [I<-j skip_n_bytes>] [I<-N read_n_bytes>] [ I<-A radix> ] F<filename>
=head1 DESCRIPTION
Expand Down

0 comments on commit 94eaee3

Please sign in to comment.