mirror of
https://git.yoctoproject.org/poky
synced 2026-08-31 14:24:12 +00:00
libxpm: fix CVE-2026-4367
Backport the upstream fix for 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 (From OE-Core rev: b3f8956f38b2f2cb0f260ab8853e9d028831f420) Signed-off-by: Enoch Ng <enoch.ng@windriver.com> Signed-off-by: Yoann Congal <yoann.congal@smile.fr> Signed-off-by: Paul Barker <paul@pbarker.dev>
This commit is contained in:
+140
@@ -0,0 +1,140 @@
|
||||
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>
|
||||
|
||||
CVE: CVE-2026-4367
|
||||
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;
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user