From: Paul Eggert <eggert@cs.ucla.edu>
Date: Tue, 21 Apr 2026 10:05:02 -0700
Subject: Avoid null pointer derefence with bad hunks
Git-commit: e6d6a4e021660679d7fc9150f981d4920f722313
Patch-mainline: yes
References: bsc#1271167 CVE-2026-56288

Problem reported by Michał Majchrowicz.
* src/pch.c (another_hunk): Keep chars_read positive
even with malformed hunks.
---
 src/pch.c |   15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

--- a/src/pch.c
+++ b/src/pch.c
@@ -1731,7 +1731,8 @@ another_hunk (enum diff difftype, bool r
 		    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;
@@ -1748,7 +1749,8 @@ another_hunk (enum diff difftype, bool r
 		    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;
@@ -1768,7 +1770,8 @@ another_hunk (enum diff difftype, bool r
 		    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;
@@ -1855,7 +1858,8 @@ another_hunk (enum diff difftype, bool r
 	    if (buf[0] != '<' || (buf[1] != ' ' && buf[1] != '\t'))
 	      fatal ("'<' followed by space or tab expected at line %s of patch",
 		     format_linenum (numbuf0, 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 (buf + 2, chars_read);
 	    if (chars_read && ! p_line[i]) {
@@ -1900,7 +1904,8 @@ another_hunk (enum diff difftype, bool r
 	    if (buf[0] != '>' || (buf[1] != ' ' && buf[1] != '\t'))
 	      fatal ("'>' followed by space or tab expected at line %s of patch",
 		     format_linenum (numbuf0, 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 (buf + 2, chars_read);
 	    if (chars_read && ! p_line[i]) {
