Skip to content

GHSA-559w-7676-3xrq on Cyberus Linux 26.05

Aliases: GHSA-559w-7676-3xrq, CVE-2026-87875

Packages: cups

Status: Plausible

Advisory Information

Summary

cupsUTF32ToUTF8() (cups/transcode.c) has no source-length parameter and reads until it finds a zero word or exhausts its output budget. Reachable from backend/snmp-supplies.c's SNMP supply-description parser with a 1025-byte fixed buffer and attacker-controlled content, this causes a heap out-of-bounds read — reproduced end-to-end with AddressSanitizer against current master.

Details

backend_walk_cb() in backend/snmp-supplies.c (~line 885-892) converts an SNMP-supplied "supply description" string according to the printer-reported character set:

case CUPS_TC_csUCS4 :
case CUPS_TC_csUTF32 :
case CUPS_TC_csUTF32BE :
case CUPS_TC_csUTF32LE :
    cupsUTF32ToUTF8((cups_utf8_t *)supplies[i - 1].name,
                    (cups_utf32_t *)packet->object_value.string.bytes,
                    sizeof(supplies[0].name));
    break;
cupsUTF32ToUTF8() (cups/transcode.c:555) takes no source-length parameter; its loop (:598) reads until it hits a zero-valued cups_utf32_t word or the maxout output budget is exhausted.

Important detail found only during dynamic verification: cups_utf32_t is typedef unsigned long (cups/transcode.h:32). On LP64 platforms (all 64-bit Linux, incl. x86_64/aarch64), unsigned long is 8 bytes, not the 4 bytes the name "UTF32" implies. So on 64-bit builds this function actually reads 8-byte words, and each low-codepoint (<0x80) word consumes only 1 unit of the maxout output budget while consuming 8 source bytes — widening the possible overread.

packet->object_value.string.bytes is a fixed 1025-byte (CUPS_SNMP_MAX_STRING+1) array embedded in a stack-local cups_snmp_t packet (_cupsSNMPWalk(), cups/snmp.c:541, reused across polling iterations). asn1_get_string() only writes a single terminating '\0' after the copied content — it does not zero-fill the remainder of the buffer. An attacker (malicious/compromised printer) fully controls this string's bytes; as long as no 8-byte-aligned word in it is all-zero, cupsUTF32ToUTF8() keeps reading past the 1025-byte boundary into adjacent memory.

charset (the switch selector) is fully attacker-controlled: charset = packet.object_value.integer; is set directly from the printer's prtLocalizationCharacterSet SNMP OID (backend/snmp-supplies.c:650).

Why this isn't a duplicate of CVE-2026-41079 / GHSA-6wpw-g8g6-wvrv: that advisory's root cause is asn1_decode_snmp() in cups/snmp.c setting packet->object_value.string.num_bytes without clamping it to what asn1_get_string() actually copied — but it only affects the CUPS_TC_csUTF16BE/csUTF16LE branch, which calls utf16_to_utf8(), a helper that does accept a source-length parameter (the bug was a wrong value being passed in). The fix commit d7fe0f5 (2026-04-13) only touches cups/snmp.c/snmp-private.h and never touches backend/snmp-supplies.c. cupsUTF32ToUTF8() has no source-length parameter at all — a structurally different root cause the CVE-2026-41079 fix could not have addressed even in principle.

PoC

Isolated PoC linking the real cupsUTF32ToUTF8() (ASAN build of current master libcups.a): heap-allocate a 1025-byte buffer (matching packet->object_value.string.bytes's real size), fill it with repeating 8-byte little-endian words of value 1 (valid codepoint, non-zero — i.e. no terminator, exactly what an attacker-controlled full-length SNMP string looks like), call cupsUTF32ToUTF8(dest, src, 1025) exactly as the real call site does:

[*] sizeof(cups_utf32_t) = 8
==ERROR== AddressSanitizer: heap-buffer-overflow
READ of size 8 at 0x519000000480 thread T0
    #0 cupsUTF32ToUTF8 cups/transcode.c:598:24    <- ch = *src++
    #1 main
0x519000000481 is located 0 bytes after 1025-byte region [0x519000000080,0x519000000481)
allocated by thread T0 here:
    #0 malloc
    #1 main
SUMMARY: AddressSanitizer: heap-buffer-overflow ... in cupsUTF32ToUTF8
Full harness source and ASAN log available on request.

Impact

Heap out-of-bounds read triggered by a malicious or compromised network printer's SNMP response during supply-level polling (e.g. lpinfo or automatic backend polling). Discloses adjacent heap memory content into the converted string / can crash the backend process. No authentication or user interaction required beyond the CUPS host polling the malicious printer over the network.

CVSS score commentary

Availability is not affected.

Fixes

[2.4.x 2b1dc178a2d23] [master 0c6842fc615e8afa2841]

Updates

2026-09-10 21:48 CEST

Metadata changes:

  • Status for package cups: “Plausible

2026-09-10 21:47 CEST

Metadata changes:

  • Status for package cups: “New