Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests of existing broken parsePatch behaviour, to fix before next release #525

Merged
merged 1 commit into from
Jun 14, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions test/patch/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -425,5 +425,103 @@ Index: test2
}
]);
});

it('should tolerate patches with extra trailing newlines after hunks', () => {
// Regression test for https://github.com/kpdecker/jsdiff/issues/524
// Not only are these considered valid by GNU patch, but jsdiff's own formatPatch method
// emits patches like this, which jsdiff used to then be unable to parse!
const patchStr = `--- foo 2024-06-14 22:16:31.444276792 +0100
+++ bar 2024-06-14 22:17:14.910611219 +0100
@@ -1,7 +1,7 @@
first
second
third
-fourth
-fifth
+vierte
+fünfte
sixth
seventh

`;
expect(parsePatch(patchStr)).to.eql([{
oldFileName: 'foo',
oldHeader: '2024-06-14 22:16:31.444276792 +0100',
newFileName: 'bar',
newHeader: '2024-06-14 22:17:14.910611219 +0100',
hunks: [
{
oldStart: 1,
oldLines: 7,
newStart: 1,
newLines: 7,
lines: [
' first',
' second',
' third',
'-fourth',
'-fifth',
'+vierte',
'+fünfte',
' sixth',
' seventh'
]
}
]
}]);
});

it("shouldn't be caught out by removal/addition of lines starting with -- or ++", () => {
// The patch below is a valid patch generated by diffing this file, foo:

// first
// second
// third
// -- bla
// fifth
// sixth

// against this file, bar:

// first
// second
// third
// ++ bla
// fifth
// sixth
// seventh

// with the command `diff -u0 foo bar`. (All lines in `foo` and `bar` have no leading
// whitespace and a trailing LF.)

// This is effectively an adversarial example meant to catch out a parser that tries to
// detect the end of a file in a multi-file diff by looking for lines starting with '---',
// '+++', and then '@@'. jsdiff used to do this. However, as this example illustrates, it is
// unsound, since the '---' and '+++' lines might actually just represent the deletion and
// insertion of lines starting with '--' and '++'. The only way to disambiguate these
// interpretations is to heed the line counts in the @@ hunk headers; you *cannot* reliably
// determine where a hunk or file ends in a unified diff patch without heeding those line
// counts.

const patchStr = `--- foo 2024-06-14 21:57:04.341065736 +0100
+++ bar 2024-06-14 22:00:57.988080321 +0100
@@ -4 +4 @@
--- bla
+++ bla
@@ -6,0 +7 @@
+seventh
`;

expect(parsePatch(patchStr)).to.eql([{
oldFileName: 'foo 2024-06-14 21:57:04.341065736 +0100',
oldHeader: '',
newFileName: 'bar 2024-06-14 22:00:57.988080321 +0100',
newHeader: '',
hunks: [
{ oldStart: 4, oldLines: 1, newStart: 4, newLines: 1, lines: ['--- bla', '+++ bla'] },
{ oldStart: 7, oldLines: 0, newStart: 7, newLines: 1, lines: ['+seventh'] }
]
}]);
});
});
});