Repository navigation
generateUnifiedDiff starts an empty hunk range one line too high #239
Description
This bug was found by an automated program we have running that writes tests with hegel (but I have personally reviewed it). More details at the bottom, but the short version is that I am not personally affected by this bug, and if that's not welcome then please feel free to disregard it.
Describe the bug
When one side of a hunk is empty (an insertion written with no context lines, or the deletion of a whole file), generateUnifiedDiff starts that range one line later than diff -U0 and git diff -U0 do: appending x to a three-line file gives @@ -4,0 +4,1 @@ where both tools write @@ -3,0 +4,1 @@, and deleting all three lines gives @@ -1,3 +1,0 @@ where both write @@ -1,3 +0,0 @@. patch refuses the first diff, since the original has no line 4. The same append with one line of context is numbered correctly.
To Reproduce
import com.github.difflib.DiffUtils;
import com.github.difflib.UnifiedDiffUtils;
import java.util.Arrays;
import java.util.List;
public class Main {
static void show(List<String> orig, List<String> rev, int context) {
UnifiedDiffUtils.generateUnifiedDiff("f", "f", orig, DiffUtils.diff(orig, rev), context).forEach(System.out::println);
System.out.println();
}
public static void main(String[] args) {
List<String> abc = Arrays.asList("a", "b", "c");
show(abc, Arrays.asList("a", "b", "c", "x"), 0);
show(abc, Arrays.asList("a", "b", "c", "x"), 1);
show(abc, Arrays.asList(), 3);
}
}Output:
--- f
+++ f
@@ -4,0 +4,1 @@
+x
--- f
+++ f
@@ -3,1 +3,2 @@
c
+x
--- f
+++ f
@@ -1,3 +1,0 @@
-a
-b
-c
Saving the first diff as append.diff and applying it to a file f containing the lines a, b, c:
$ patch f append.diff
patching file f
No such line 4 in input file, ignoring
patch: **** misordered hunks! output would be garbled
With the header changed to @@ -3,0 +4,1 @@, patch applies it and f ends in x. patch does accept the @@ -1,3 +1,0 @@ deletion, but diff -u and git diff both write @@ -1,3 +0,0 @@ for that change.
Expected behavior
An empty range to start at the line before the change, as diff -U0 and git diff -U0 write it: @@ -3,0 +4,1 @@ for the append and @@ -1,3 +0,0 @@ for the deletion, so that patch applies the generated diff.
System
- Java: OpenJDK 27
- Version: java-diff-utils 4.17 from Maven Central, and 4.18-SNAPSHOT built from current
master(0643852); the output is identical on both.patchis macOS's (2.0-12u11-Apple, FreeBSD-derived),diffis Apple's,gitis 2.50.1.
As mentioned at the top, this was found by an automated program that writes property-based tests for various open source projects using hegel, and the report was reviewed by hand before filing. We've also potentially found (but not yet hand validated) 8 other bugs in java-diff-utils. You can see the tests at https://github.com/hegeldev/hegel-zoo/tree/main/targets/java/java-diff-utils. Let us know if you would like us to file the other bugs found and/or contribute the tests. NB the tests are currently LLM generated and probably not yet suitable for inclusion as is, but we're happy to help get them into a better state if you want them.
Activity