Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

ARM:LE:32:v7 and v8 segfault translating a coprocessor STC word (v6 raises BadDataError)

未关闭
#294 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
48/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
活跃
技术栈
cpp, python

调研方向

首先,通过使用 746b69cd 调用 pypcode.Context("ARM:LE:32:v7").translate 重现崩溃,然后比较 SLEIGH 支持的解码器中 ARM v6、v7 和 v8 的翻译路径。跟踪 v7 和 v8 为什么以 SIGSEGV 终止,而不是引发 BadDataError,并验证复现程序能够在不崩溃的情况下以预期的异常完成。

由索引模型根据 Issue 内容生成。

描述

THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS

ARM:LE:32:v7 and ARM:LE:32:v8 segfault translating a single 4-byte word.
ARM:LE:32:v6 rejects the same word cleanly with BadDataError, so the correct
failure mode already exists next door in the same processor family.

Reproducer

import pypcode
pypcode.Context("ARM:LE:32:v7").translate(bytes.fromhex("746b69cd"), 0x1000)

Four bytes, one call, no flags, no other state. Deterministic: 10/10 runs,
SIGSEGV (exit 139). Same for ARM:LE:32:v8.

Expected behaviour

A raised exception, not a crash. BadDataError is the right outcome here — the
word is not valid code for this language, and ARM:LE:32:v6 already returns
exactly that for the identical input:

BadDataError: r0x00001000: Unable to resolve constructor

The distinction matters to a caller, not just aesthetically. An exception is
catchable: a tool sweeping an image can skip the offending block and carry on.
SIGSEGV takes the process out with no opportunity to recover, no partial
results, and no indication of which address was responsible. So the ask is that
v7/v8 fail the way v6 does, whatever the underlying cause turns out to be.

Behaviour across the ARM variants

Each in its own child process, so the matrix survives:

import subprocess, sys, pypcode

WORD  = "746b69cd"   # little-endian 0xcd696b74
CHILD = "import pypcode,sys; pypcode.Context(sys.argv[1]).translate(bytes.fromhex(sys.argv[2]), 0x1000)"

print(f"pypcode {pypcode.__version__}")
for lang in ("ARM:LE:32:v5", "ARM:LE:32:v6", "ARM:LE:32:v7",
             "ARM:LE:32:v8", "ARM:LE:32:Cortex", "ARM:BE:32:v7"):
    rc = subprocess.run([sys.executable, "-c", CHILD, lang, WORD], capture_output=True).returncode
    print(f"  {lang:18} {'SIGSEGV' if rc in (-11, 139) else f'ok (rc={rc})'}")
language result
ARM:LE:32:v5 ok — decodes as stclgt p11,cr6,[r9,#-0x1d0]!
ARM:LE:32:v6 BadDataError: r0x00001000: Unable to resolve constructor
ARM:LE:32:v7 SIGSEGV
ARM:LE:32:v8 SIGSEGV
ARM:LE:32:Cortex ok — decodes as Thumb (ldr / ldmia)
ARM:BE:32:v7 ok — different word under the other byte order

The word

0xcd696b74 decodes (per ARM:LE:32:v5) as:

stclgt p11, cr6, [r9, #-0x1d0]!

A coprocessor store, predicated GT, pre-indexed with writeback, targeting
p11 — the VFP double-precision coprocessor. Field breakdown:

cond=0xc(GT)  op=0b110  P=1 U=0 D=1 W=1 L=0
Rn=r9  CRd=c6  coproc=p11  imm8=116 (byte offset 464)

The split lines up with VFP modelling: v5 has no VFP model and takes it as a
plain STCL; v6 refuses it; v7/v8 model VFP/NEON and die. That v6 raises
where v7 crashes is the part I would weight most — it suggests something in the
newer VFP/NEON decode path rather than a general gap in coprocessor handling.

Where the bytes came from

Not synthesised. The word occurs five times inside kallsyms_names — the
compressed kallsyms symbol-name table — in Debian's linux-image-2.6.37-2-versatile
(armel). The crashing decode is at 0xc02b6410, kallsyms_names + 0x8e70. That
build's System.map types kallsyms_names as T, so the table sits in the text
region, and a sweep of executable ranges decodes it as instructions.

To be exact about the artifact: Debian's regular (non-dbg) armel package ships a
compressed /boot/vmlinuz, not an ELF, so the bytes were read from the
decompressed kernel image out of that zImage — stock Debian content, in a
container rebuilt locally. The word does not appear in the armhf -dbg images I
also have (4.9.0-19-armmp, 4.18.0-3-armmp), so this is specific to that
build, and I would not want to overstate how common it is.

That is the practical impact: a consumer pointed at an arbitrary ARM binary
cannot know whether a given word is code before lifting it, and a segfault gives
no opportunity to skip the block. Refusing invalid input is fine — v6 already
does exactly that.

Environment

pypcode   4.0.0   (PyPI wheel, cp313-cp313-manylinux_2_27_x86_64)
python    3.13.7
platform  Linux-5.10.16.3-microsoft-standard-WSL2-x86_64-with-glibc2.35
machine   x86_64

Tested against the 4.0.0 release wheel, not against master — happy to
retest there or against a candidate fix if that is useful.

Related

Same class as #293 (segfaults on short inputs for JVM, NDS32, SPARC) and #292
(PowerPC vaddubm heap corruption), but a different language and not covered by
either, so filing separately. Unlike the three in #293, this word is not a
synthetic sequence — it occurs in a real distribution kernel.

主要语言
C++
星标
224
派生
33
平均合并
7 小时 18 分钟
30 天内合并 PR
10

环境准备

这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

angr/pypcode 的其他 Issue

查看 angr/pypcode 的全部 Issue

相似的 Issue

更多 C++ Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。