← 输入框|github.com|刷新
Skip to content

generateUnifiedDiff starts an empty hunk range one line too high #239

Open

Description

@DRMacIver

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. patch is macOS's (2.0-12u11-Apple, FreeBSD-derived), diff is Apple's, git is 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions