From 101a805510356092a6d2a864bb18d440fec57f0a Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Tue, 21 Apr 2026 10:05:02 -0700
Subject: [PATCH] Avoid null pointer derefence with bad hunks
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Problem reported by Michał Majchrowicz.
* src/pch.c (another_hunk): Keep chars_read positive
even with malformed hunks.

CVE: CVE-2026-56288
Upstream-Status: Backport [https://cgit.git.savannah.gnu.org/cgit/patch.git/commit/?id=e6d6a4e021660679d7fc9150f981d4920f722313]

(cherry picked from commit e6d6a4e021660679d7fc9150f981d4920f722313)
Signed-off-by: Hetvi Thakar <hthakar@cisco.com>
---
 src/pch.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/pch.c b/src/pch.c
index d9f5c61..41150fe 100644
--- a/src/pch.c
+++ b/src/pch.c
@@ -1694,7 +1694,8 @@ another_hunk (enum diff difftype, bool rev)
 		    p_end = filldst-1;
 		    malformed ();
 		}
-		chars_read -= fillsrc == p_ptrn_lines && incomplete_line ();
+		chars_read -= (1 < chars_read && fillsrc == p_ptrn_lines
+			       && incomplete_line ());
 		p_Char[fillsrc] = ch;
 		p_line[fillsrc] = s;
 		p_len[fillsrc++] = chars_read;
@@ -1711,7 +1712,8 @@ another_hunk (enum diff difftype, bool rev)
 		    malformed ();
 		}
 		context++;
-		chars_read -= fillsrc == p_ptrn_lines && incomplete_line ();
+		chars_read -= (1 < chars_read && fillsrc == p_ptrn_lines
+			       && incomplete_line ());
 		p_Char[fillsrc] = ch;
 		p_line[fillsrc] = s;
 		p_len[fillsrc++] = chars_read;
@@ -1725,7 +1727,8 @@ another_hunk (enum diff difftype, bool rev)
 		    p_end = fillsrc-1;
 		    malformed ();
 		}
-		chars_read -= filldst == p_end && incomplete_line ();
+		chars_read -= (1 < chars_read && filldst == p_end
+			       && incomplete_line ());
 		p_Char[filldst] = ch;
 		p_line[filldst] = s;
 		p_len[filldst++] = chars_read;
@@ -1808,7 +1811,8 @@ another_hunk (enum diff difftype, bool rev)
 	      fatal (("'<' followed by space or tab expected"
 		      " at line %td of patch"),
 		     p_input_line);
-	    chars_read -= 2 + (i == p_ptrn_lines && incomplete_line ());
+	    chars_read -= 2 + (3 < chars_read && i == p_ptrn_lines
+			       && incomplete_line ());
 	    p_len[i] = chars_read;
 	    p_line[i] = savebuf (patchbuf + 2, chars_read);
 	    p_Char[i] = '-';
@@ -1833,7 +1837,8 @@ another_hunk (enum diff difftype, bool rev)
 	      fatal (("'>' followed by space or tab expected"
 		      " at line %td of patch"),
 		     p_input_line);
-	    chars_read -= 2 + (i == p_end && incomplete_line ());
+	    chars_read -= 2 + (3 < chars_read && i == p_end
+			       && incomplete_line ());
 	    p_len[i] = chars_read;
 	    p_line[i] = savebuf (patchbuf + 2, chars_read);
 	    p_Char[i] = '+';
