Skip to content

Commit 71d1681

Browse files
authored
patch: improve validation of normal diffs (briandfoy#952)
* patch: improve validation of normal diffs * A normal diff can contain (a)dd, (c)hange and (d)elete commands * For the Add command, a single target address is expected to be prefixed before "a" * Diff utils output data in form of XaY,Z and not X,YaZ (so in practice the error condition should not happen) * GNU diffutils manual described and Add command as "LaR", where L is a single line number and R is a range (e.g. 3,4) [1] * Make this version of patch reject malformed Add commands * Print the offending input data and line number * Calling $patch->reject() is needed for setting the correct exit code * When the exit code will indicate failure, avoid printing "done" message after preceding error messages * I created an invalid input file manually to test this 1. https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Normal.html * previous commit missed loop construct for c and d diff commands
1 parent de00a20 commit 71d1681

File tree

1 file changed

+12
-3
lines changed

1 file changed

+12
-3
lines changed

bin/patch

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use constant EX_SUCCESS => 0;
2424
use constant EX_REJECTS => 1;
2525
use constant EX_FAILURE => 2;
2626

27-
my $VERSION = '0.34';
27+
my $VERSION = '0.35';
2828

2929
$|++;
3030

@@ -200,8 +200,16 @@ while (<PATCH>) {
200200
} elsif (/^(\s*)((\d+)(?:,(\d+))?([acd])(\d+)(?:,(\d+))?\n)/) {
201201
# NORMAL DIFF
202202
my ($space, $range, $i_start, $i_end, $cmd, $o_start, $o_end) =
203-
($1, $2, $3, $4 || $3, $5, $6, $7 || $6);
203+
($1, $2, $3, $4, $5, $6, $7 || $6);
204204
$patch->bless('normal') or next PATCH;
205+
if ($cmd eq 'a' && defined($i_end)) { # invalid input "X,YaZ"
206+
my $input = $_;
207+
chomp $input;
208+
$patch->note("Malformed input at line $.: $input\n");
209+
$patch->reject($range);
210+
last;
211+
}
212+
$i_end = $i_start unless defined $i_end; # for input "XcY,Z" and "XdY,Z"
205213
my (@d_hunk, @a_hunk);
206214
my $d_re = qr/^$space< /;
207215
my $a_re = qr/^$space> /;
@@ -278,8 +286,9 @@ if (ref $patch eq 'Patch') {
278286
$patch->end;
279287
}
280288

289+
exit(EX_REJECTS) if $patch->error;
281290
$patch->note("done\n");
282-
exit($patch->error ? EX_REJECTS : EX_SUCCESS);
291+
exit EX_SUCCESS;
283292

284293
END {
285294
close STDOUT || die "$0: can't close stdout: $!\n";

0 commit comments

Comments
 (0)