diff mbox series

[scarthgap] libxpm: fix CVE-2026-4367

Message ID 20260721230248.1874697-1-enoch.ng@windriver.com
State Changes Requested, archived
Delegated to: Yoann Congal
Headers show
Series [scarthgap] libxpm: fix CVE-2026-4367 | expand

Commit Message

Enoch Ng July 21, 2026, 11:02 p.m. UTC
Backport the upstream fix fpr CVE-2026-4367, in which the
`xpmNextWord()` function could attempt to read beyond the file's
end due to improper validation of file boundaries.

Reference: https://nvd.nist.gov/vuln/detail/CVE-2026-4367

Signed-off-by: Enoch Ng <enoch.ng@windriver.com>
---
 ...67-Out-of-bounds-read-in-xpmNextWord.patch | 139 ++++++++++++++++++
 .../xorg-lib/libxpm_3.5.17.bb                 |   1 +
 2 files changed, 140 insertions(+)
 create mode 100644 meta/recipes-graphics/xorg-lib/libxpm/0001-Fix-CVE-2026-4367-Out-of-bounds-read-in-xpmNextWord.patch

Comments

patchtest@automation.yoctoproject.org July 21, 2026, 11:16 p.m. UTC | #1
Thank you for your submission. Patchtest identified one
or more issues with the patch. Please see the log below for
more information:

---
Testing patch /home/patchtest/share/mboxes/scarthgap-libxpm-fix-CVE-2026-4367.patch

FAIL: test CVE tag format: Missing or incorrectly formatted CVE tag in patch file. Correct or include the CVE tag in the patch with format: "CVE: CVE-YYYY-XXXX" (test_patch.TestPatch.test_cve_tag_format)

PASS: test CVE check ignore (test_metadata.TestMetadata.test_cve_check_ignore)
PASS: test Signed-off-by presence (test_mbox.TestMbox.test_signed_off_by_presence)
PASS: test Signed-off-by presence (test_patch.TestPatch.test_signed_off_by_presence)
PASS: test Upstream-Status presence (test_patch.TestPatch.test_upstream_status_presence_format)
PASS: test author valid (test_mbox.TestMbox.test_author_valid)
PASS: test commit message presence (test_mbox.TestMbox.test_commit_message_presence)
PASS: test commit message user tags (test_mbox.TestMbox.test_commit_message_user_tags)
PASS: test lic files chksum modified not mentioned (test_metadata.TestMetadata.test_lic_files_chksum_modified_not_mentioned)
PASS: test max line length (test_metadata.TestMetadata.test_max_line_length)
PASS: test mbox format (test_mbox.TestMbox.test_mbox_format)
PASS: test non-AUH upgrade (test_mbox.TestMbox.test_non_auh_upgrade)
PASS: test shortlog format (test_mbox.TestMbox.test_shortlog_format)
PASS: test shortlog length (test_mbox.TestMbox.test_shortlog_length)
PASS: test target mailing list (test_mbox.TestMbox.test_target_mailing_list)

SKIP: pretest pylint: No python related patches, skipping test (test_python_pylint.PyLint.pretest_pylint)
SKIP: pretest src uri left files: Patch cannot be merged (test_metadata.TestMetadata.pretest_src_uri_left_files)
SKIP: test bugzilla entry format: No bug ID found (test_mbox.TestMbox.test_bugzilla_entry_format)
SKIP: test lic files chksum presence: No added recipes, skipping test (test_metadata.TestMetadata.test_lic_files_chksum_presence)
SKIP: test license presence: No added recipes, skipping test (test_metadata.TestMetadata.test_license_presence)
SKIP: test pylint: No python related patches, skipping test (test_python_pylint.PyLint.test_pylint)
SKIP: test series merge on head: Merge test is disabled for now (test_mbox.TestMbox.test_series_merge_on_head)
SKIP: test src uri left files: Patch cannot be merged (test_metadata.TestMetadata.test_src_uri_left_files)
SKIP: test summary presence: No added recipes, skipping test (test_metadata.TestMetadata.test_summary_presence)

---

Please address the issues identified and
submit a new revision of the patch, or alternatively, reply to this
email with an explanation of why the patch should be accepted. If you
believe these results are due to an error in patchtest, please submit a
bug at https://bugzilla.yoctoproject.org/ (use the 'Patchtest' category
under 'Yocto Project Subprojects'). For more information on specific
failures, see: https://wiki.yoctoproject.org/wiki/Patchtest. Thank
you!
diff mbox series

Patch

diff --git a/meta/recipes-graphics/xorg-lib/libxpm/0001-Fix-CVE-2026-4367-Out-of-bounds-read-in-xpmNextWord.patch b/meta/recipes-graphics/xorg-lib/libxpm/0001-Fix-CVE-2026-4367-Out-of-bounds-read-in-xpmNextWord.patch
new file mode 100644
index 0000000000..e1320b597d
--- /dev/null
+++ b/meta/recipes-graphics/xorg-lib/libxpm/0001-Fix-CVE-2026-4367-Out-of-bounds-read-in-xpmNextWord.patch
@@ -0,0 +1,139 @@ 
+From 5448e1bd7252780b16db869c2253d24e0fe0ae18 Mon Sep 17 00:00:00 2001
+From: Olivier Fourdan <ofourdan@redhat.com>
+Date: Tue, 17 Feb 2026 11:59:56 +0100
+Subject: [PATCH libXpm] Fix CVE-2026-4367: Out-of-bounds read in xpmNextWord()
+
+xpmNextWord() checks for the terminator character to detect the end of
+the file, but a very small malformed XPM file may cause the function to
+read past the end of the buffer, causing out-of-bound reads:
+
+  == Invalid read of size 1
+  ==    at 0x48AD3A4: xpmParseColors (parse.c:239)
+  ==    by 0x48AF9D8: xpmParseData (parse.c:783)
+  ==    by 0x48B1C18: XpmCreateXpmImageFromBuffer (CrIFrBuf.c:101)
+  ==    by 0x4005A6: main ()
+  ==  Address 0x4c413bf is 0 bytes after a block of size 15 alloc'd
+  ==    at 0x4841B26: malloc (vg_replace_malloc.c:447)
+  ==    by 0x48B2809: XpmReadFileToBuffer (RdFToBuf.c:96)
+  ==    by 0x400554: main ()
+  ==
+  == Invalid read of size 1
+  ==    at 0x48AC8D5: xpmNextWord.constprop.0 (data.c:262)
+  ==    by 0x48AD492: xpmParseColors (parse.c:266)
+  ==    by 0x48AF9D8: xpmParseData (parse.c:783)
+  ==    by 0x48B1C18: XpmCreateXpmImageFromBuffer (CrIFrBuf.c:101)
+  ==    by 0x4005A6: main ()
+  ==  Address 0x4c413c0 is 1 bytes after a block of size 15 alloc'd
+  ==    at 0x4841B26: malloc (vg_replace_malloc.c:447)
+  ==    by 0x48B2809: XpmReadFileToBuffer (RdFToBuf.c:96)
+  ==    by 0x400554: main ()
+  ==
+  == Invalid read of size 1
+  ==    at 0x48AC965: xpmNextWord.constprop.0 (data.c:265)
+  ==    by 0x48AD492: xpmParseColors (parse.c:266)
+  ==    by 0x48AF9D8: xpmParseData (parse.c:783)
+  ==    by 0x48B1C18: XpmCreateXpmImageFromBuffer (CrIFrBuf.c:101)
+  ==    by 0x4005A6: main ()
+  ==  Address 0x4c413c0 is 1 bytes after a block of size 15 alloc'd
+  ==    at 0x4841B26: malloc (vg_replace_malloc.c:447)
+  ==    by 0x48B2809: XpmReadFileToBuffer (RdFToBuf.c:96)
+  ==    by 0x400554: main ()
+
+The problem actually comes from xpmNextString() and xpmParseColors():
+
+1) xpmNextString() checks for the NULL terminator when looking for the
+   end of the string (Eos) but not when looking for the beginning of the
+   next string (Bos).
+
+2) xpmParseColors() does not check the return value from xpmNextString()
+   and continues even when xpmNextString() raised an invalid XPM file.
+
+To avoid the issue, fix xpmNextString() to check for the NULL string
+terminator when looking for the beginning of the next string and fix
+xpmParseColors() to stop when xpmNextString() reported an invalid XPM
+error.
+
+CVE-2026-4367
+
+This vulnerability was discovered by:
+Naoki Wakamatsu
+
+v2: Fix the XPM 1 code path the same.
+
+Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
+Part-of: <https://gitlab.freedesktop.org/xorg/lib/libxpm/-/merge_requests/31>
+
+Upstream-Status: Backport [https://gitlab.freedesktop.org/xorg/lib/libxpm/-/commit/5448e1bd7252780b16db869c2253d24e0fe0ae18]
+Signed-off-by: Enoch Ng <enoch.ng@windriver.com>
+
+---
+
+ src/data.c  |  3 +++
+ src/parse.c | 19 ++++++++++++++-----
+ 2 files changed, 17 insertions(+), 5 deletions(-)
+
+diff --git a/src/data.c b/src/data.c
+index 6e87455..a2b4acc 100644
+--- a/src/data.c
++++ b/src/data.c
+@@ -210,6 +210,9 @@ xpmNextString(xpmData *data)
+ 	    while ((c = *data->cptr++) && c != data->Bos && c != '\0')
+ 		if (data->Bcmt && c == data->Bcmt[0])
+ 		    ParseComment(data);
++
++	    if (c == '\0')
++		return XpmFileInvalid;
+ 	} else if (data->Bcmt) {	/* XPM2 natural */
+ 	    while (((c = *data->cptr++) == data->Bcmt[0]) && c != '\0')
+ 		ParseComment(data);
+diff --git a/src/parse.c b/src/parse.c
+index cd923f9..268954d 100644
+--- a/src/parse.c
++++ b/src/parse.c
+@@ -216,7 +216,9 @@ xpmParseColors(
+ 
+     if (!data->format) {		/* XPM 2 or 3 */
+ 	for (a = 0, color = colorTable; a < ncolors; a++, color++) {
+-	    xpmNextString(data);	/* skip the line */
++	    ErrorStatus = xpmNextString(data);         /* skip the line */
++	    if (ErrorStatus != XpmSuccess)
++		goto error;
+ 
+ 	    /*
+ 	     * read pixel value
+@@ -314,7 +316,9 @@ xpmParseColors(
+ 	/* get to the beginning of the first string */
+ 	data->Bos = '"';
+ 	data->Eos = '\0';
+-	xpmNextString(data);
++	ErrorStatus = xpmNextString(data);
++	if (ErrorStatus != XpmSuccess)
++	    goto error;
+ 	data->Eos = '"';
+ 	for (a = 0, color = colorTable; a < ncolors; a++, color++) {
+ 
+@@ -354,7 +358,9 @@ xpmParseColors(
+ 	    /*
+ 	     * read color values
+ 	     */
+-	    xpmNextString(data);	/* get to the next string */
++	    ErrorStatus = xpmNextString(data);	/* get to the next string */
++	    if (ErrorStatus != XpmSuccess)
++		goto error;
+ 	    *curbuf = '\0';		/* init curbuf */
+ 	    while ((l = xpmNextWord(data, buf, BUFSIZ))) {
+ 		if (*curbuf != '\0') {
+@@ -378,8 +384,11 @@ xpmParseColors(
+ 	    memcpy(s, curbuf, len);
+ 	    color->c_color = s;
+ 	    *curbuf = '\0';		/* reset curbuf */
+-	    if (a < ncolors - 1)	/* can we trust ncolors -> leave data's bounds */
+-		xpmNextString(data);	/* get to the next string */
++	    if (a < ncolors - 1) {	/* can we trust ncolors -> leave data's bounds */
++		ErrorStatus = xpmNextString(data);	/* get to the next string */
++		if (ErrorStatus != XpmSuccess)
++		    goto error;
++	    }
+ 	}
+     }
+     *colorTablePtr = colorTable;
diff --git a/meta/recipes-graphics/xorg-lib/libxpm_3.5.17.bb b/meta/recipes-graphics/xorg-lib/libxpm_3.5.17.bb
index 8e15ecc0d4..9d1dd47742 100644
--- a/meta/recipes-graphics/xorg-lib/libxpm_3.5.17.bb
+++ b/meta/recipes-graphics/xorg-lib/libxpm_3.5.17.bb
@@ -22,6 +22,7 @@  PACKAGES =+ "sxpm cxpm"
 FILES:cxpm = "${bindir}/cxpm"
 FILES:sxpm = "${bindir}/sxpm"
 
+SRC_URI += " file://0001-Fix-CVE-2026-4367-Out-of-bounds-read-in-xpmNextWord.patch"
 SRC_URI[sha256sum] = "64b31f81019e7d388c822b0b28af8d51c4622b83f1f0cb6fa3fc95e271226e43"
 
 BBCLASSEXTEND = "native"