EDK II - Variadic Function Argument Mismatch in DumpErrorNotificationType
A copy-paste error at lines 199 and 201 of HestParser.c causes incorrect argument handling in variadic Print() calls.
- Advisory
- BYTERAY-2026-0241
- CWE
- CWE-688
- Vendor
- TianoCore
- Product
- EDK II
- Reported
- 2026-06-25
- Disclosure
- 2026-10-29
- Affected
- EDK II at commit 70741a15d9a714323a5598eac47727e60507e22f (master, 2026-06-21); affected code in ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Hest/HestParser.c.
- Credit
- Argus-Systems
Executive Summary
A copy-paste error at lines 199 and 201 of HestParser.c causes incorrect argument handling in variadic Print() calls. At line 201, Print(L"UNKNOWN(0x%x)", HestErrorNotificationStructureTypeStr[*Ptr]) passes a CONST CHAR16* pointer where the %x format specifier expects an integer. At line 199, Print(L"%s(0x%x)", HestErrorNotificationStructureTypeStr[*Ptr]) has two format specifiers (%s + %x) but only one argument, leaving %x to read an uninitialized stack slot. The intended arguments should include *Ptr (a UINT8 type value from the ACPI HEST table), as in the sibling calls EinjParser.c:241 and EinjParser.c:272 (Print(L"%s(0x%x)", Name, Value)). Line 201 also indexes the array out of bounds: it runs only when *Ptr is greater than EFI_ACPI_6_5_HARDWARE_ERROR_NOTIFICATION_SOFTWARE_DELEGATED_EXCEPTION (0x0B), while HestErrorNotificationStructureTypeStr (lines 28-41) has 12 entries, so for any type value from 0x0C to 0xFF it reads a pointer-sized value past the end of the array. That value is only printed with %x, never dereferenced.
This advisory is one of a set reported to VulnCheck on 2026-06-25 for coordinated disclosure to the EDK II maintainers. After several follow-ups over the following months no response was received. 126 days after the initial report, ByteRay is publishing the findings in good faith so that affected integrators can assess and remediate them. All findings were identified against EDK II commit 70741a15d9a714323a5598eac47727e60507e22f (master, 2026-06-21).
Affected Products and Versions
- Vendor: TianoCore
- Product: EDK II (
ShellPkg) - Affected commit:
70741a15d9a714323a5598eac47727e60507e22f(master, 2026-06-21). The code is present on that commit and later revisions that have not changed it. - Location:
ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Hest/HestParser.c:201,HestParser.c:199 - Function:
DumpErrorNotificationType - Category:
error_handling
Technical Details
Controllability: SEMI_TRUSTED — confidence: high
Data Flow
An operator invokes the acpiview -s HEST UEFI shell command at UefiShellAcpiViewCommandLib.c:356, causing AcpiView() to read ACPI tables from firmware memory. ProcessAcpiTable() at AcpiTableParser.c:181 receives a pointer to the ACPI HEST table buffer. The ParseAcpi() loop at AcpiParser.c:765 iterates parser entries and invokes the DumpErrorNotificationType PrintFormatter callback with Ptr pointing to the Type byte in the ACPI table. Inside DumpErrorNotificationType at HestParser.c:189, *Ptr reads the UINT8 Type byte from the ACPI HEST table. At line 199, Print(L"%s(0x%x)", HestErrorNotificationStructureTypeStr[*Ptr]) has two format specifiers but one argument, causing %x to read an uninitialized stack slot. At line 201, the vulnerable sink Print(L"UNKNOWN(0x%x)", HestErrorNotificationStructureTypeStr[*Ptr]) passes a CONST CHAR16* pointer where %x expects an integer — a copy-paste bug that should have used *Ptr. Because this branch is taken only for *Ptr > 0x0B, the index is always past the end of the 12-entry array, so the pointer printed is read out of bounds.
Affected Callers
ParseAcpi(AcpiParser.c:765, called forHestErrorNotificationParseratHestParser.c:459)
Sanitization / Security Controls
- UEFI Shell access requirement: The
acpiviewcommand is only available in the UEFI shell environment, requiring physical or console access to the machine. This is an effective control. - Trust boundary — self-injection: The operator running
acpiviewalready has full UEFI shell console access. The informational leak (pointer value printed as hex, uninitialized stack value on line 199) is displayed to the same operator who already holds equal or greater privilege. *Ptrrange check (HestParser.c:198): only selects between the twoPrintbranches; both are wrong, and the else branch still indexes the array with the out-of-range value. Ineffective.ValidateErrorNotificationTypevalidator (HestParser.c:242): runs after thePrintFormatterinParseAcpi(AcpiParser.c:791-798), so it cannot prevent the badPrint. Ineffective.- No sanitization points exist along the data flow path.
Reachability and Preconditions
Attacker position and trust level for this issue are stated in the Controllability line and Data Flow above, and the concrete trigger is in Reproduction below.
Exploitability: Low
Realism: Low
Reproduction
- Attacker has physical or remote console access to the UEFI Shell environment; machine must have a HEST table with Hardware Error Notification Structures (common on server/enterprise hardware).
- Run
acpiview -s HEST. - When a Hardware Error Notification Structure is encountered,
DumpErrorNotificationTypeis called. - For a type value 0x00-0x0B, line 199 prints an unrelated stack or register value for
%x; for a type value 0x0C-0xFF, line 201 reads a pointer past the end ofHestErrorNotificationStructureTypeStrand displays it as hex instead of the intended byte value.
Impact
Minimal — cosmetic garbage display, a potential stack value leak, and (for type values above 0x0B) a pointer-sized value read past the end of a static array, all printed only to the same operator who already has console access. No privilege escalation, code execution, or remote data exfiltration.
Remediation and Mitigation
As of commit 70741a15d9a714323a5598eac47727e60507e22f this issue is unfixed upstream and no CVE has been assigned. Pass the intended argument to the formatting routine and bound the array index used to select it. The specific control that is absent or ineffective is identified in the Sanitization / Security Controls list under Technical Details.
Timeline
- 2026-06-25 - Reported to VulnCheck for coordinated disclosure to the TianoCore / EDK II security team.
- 2026-07 to 2026-10 - Several follow-ups sent; no response received.
- 2026-10-29 - Public disclosure in good faith, 126 days after the initial report.
Credits
Discovered and reported by Argus-Systems.