From c11f205622bb6c49a8b597ee9cceb050d0c19491 Mon Sep 17 00:00:00 2001 From: youdie006 Date: Thu, 27 Aug 2026 11:57:41 +0900 Subject: [PATCH] Reject a chunk that ends exactly at the end of the target verifyChunk compares last, an index, against target.size(), a count: if (position + fuzz > target.size() || last - fuzz > target.size()) The loop below reads target.get(last - fuzz), so it needs last - fuzz < target.size(). Rejecting only > lets the exactly-one-past case through, and List.get throws: chunk covering target indices 7..10, target of length 10 -> IndexOutOfBoundsException: Index 10 out of bounds for length 10 applyTo and DiffUtils.patch document PatchFailedException for a patch that cannot be applied, and the neighbouring case (target two short) already returns POSITION_OUT_OF_TARGET, so a target one short should too. The first disjunct stays >: an InsertDelta appending at end of file has an empty source chunk with position == target.size(), and >= there would reject a valid append. An empty chunk has last == position - 1, so the second disjunct is already correct for it. No test referenced POSITION_OUT_OF_TARGET; ChunkTest covered OK and CONTENT_DOES_NOT_MATCH_TARGET only. --- .../src/main/java/com/github/difflib/patch/Chunk.java | 2 +- .../test/java/com/github/difflib/patch/ChunkTest.java | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/java-diff-utils/src/main/java/com/github/difflib/patch/Chunk.java b/java-diff-utils/src/main/java/com/github/difflib/patch/Chunk.java index b5b2f31..760f569 100644 --- a/java-diff-utils/src/main/java/com/github/difflib/patch/Chunk.java +++ b/java-diff-utils/src/main/java/com/github/difflib/patch/Chunk.java @@ -113,7 +113,7 @@ public VerifyChunk verifyChunk(List target, int fuzz, int position) throws Pa int lastIndex = size() - fuzz; int last = position + size() - 1; - if (position + fuzz > target.size() || last - fuzz > target.size()) { + if (position + fuzz > target.size() || last - fuzz >= target.size()) { return VerifyChunk.POSITION_OUT_OF_TARGET; } for (int i = startIndex; i < lastIndex; i++) { diff --git a/java-diff-utils/src/test/java/com/github/difflib/patch/ChunkTest.java b/java-diff-utils/src/test/java/com/github/difflib/patch/ChunkTest.java index 46eb727..0dae455 100644 --- a/java-diff-utils/src/test/java/com/github/difflib/patch/ChunkTest.java +++ b/java-diff-utils/src/test/java/com/github/difflib/patch/ChunkTest.java @@ -31,6 +31,16 @@ void verifyChunk() throws PatchFailedException { VerifyChunk.CONTENT_DOES_NOT_MATCH_TARGET, chunk.verifyChunk(toCharList("prefix suffix"), 1, 7)); } + @Test + void verifyChunkAtTheEndOfTheTarget() throws PatchFailedException { + // chunk covers target indices 7..10, so it needs a target of at least 11 + Chunk chunk = new Chunk<>(7, toCharList("test")); + + assertEquals(VerifyChunk.OK, chunk.verifyChunk(toCharList("prefix test"), 0, 7)); + assertEquals(VerifyChunk.POSITION_OUT_OF_TARGET, chunk.verifyChunk(toCharList("prefix tes"), 0, 7)); + assertEquals(VerifyChunk.POSITION_OUT_OF_TARGET, chunk.verifyChunk(toCharList("prefix te"), 0, 7)); + } + private List toCharList(String str) { return str.chars().mapToObj(x -> (char) x).collect(Collectors.toList()); }