ctypes.Structure superclass with bitfields do not parse properly when it doesn't end on a byte boundary
还没有人认领这个 Issue。
- 主要语言
- Python
- 星标
- 77.2k
- 派生
- 36k
- PR 合并指标
- PR 指标待抓取
描述
Bug report
Bug description:
I am trying to extend a ctypes Structure in a subclass but am running into some issues. My parent class defines bitfields that are intended to be expanded in the child class to fill the byte boundary.
import ctypes
class Parent(ctypes.BigEndianStructure):
_pack_ = 1
_fields_ = [
("field1", ctypes.c_uint8, 8),
("field2", ctypes.c_uint8, 6),
]
class Child(Parent):
_pack_ = 1
_fields_ = [
("field3", ctypes.c_uint8, 2), # fills the missing bits from the parent
("field4", ctypes.c_uint16, 16)
]
When I run the following to test, I am not getting the expected values.
data = b"\x12\x02\xAB\xCD\xEF"
child = Child.from_buffer_copy(data)
print(hex(child.field1)) # 0x12
print(hex(child.field2)) # 0x00
print(hex(child.field3)) # 0x02
print(hex(child.field4)) # 0xABCD
print(bytes(child))
0x12
0x0
0x2
0xcdef <--- we're missing the 3rd byte 0xAB, and shouldn't have 0xEF
b'\x12\x02\xab\xcd\xef'
I only have 4 bytes defined in the structure, but when trying to supply data with only 4 bytes, it throws an error
child = Child.from_buffer_copy(data)
ValueError: Buffer size too small (4 instead of at least 5 bytes)
When combining into just one struct it seems to work fine
class Combined(ctypes.BigEndianStructure):
_pack_ = 1
_fields_ = [
("field1", ctypes.c_uint8, 8),
("field2", ctypes.c_uint8, 6),
("field3", ctypes.c_uint8, 2),
("field4", ctypes.c_uint16, 16)
]
combined = Combined.from_buffer_copy(data)
print(hex(combined.field1)) # 0x12
print(hex(combined.field2)) # 0x00
print(hex(combined.field3)) # 0x02
print(hex(combined.field4)) # 0xAB
print(bytes(combined))
0x12
0x0
0x2
0xabcd
b'\x12\x02\xab\xcd'
and adjusting the sizes of the bitfields in the parent/child classes seems to change the behavior
class Parent(ctypes.BigEndianStructure):
_pack_ = 1
_fields_ = [
("field1", ctypes.c_uint8, 8),
("field2", ctypes.c_uint8, 4),
]
class Child(Parent):
_pack_ = 1
_fields_ = [
("field3", ctypes.c_uint8, 4),
("field4", ctypes.c_uint16, 16)
]
0x12
0x0
0xa
0xcdef
b'\x12\x02\xab\xcd\xef'
class Parent(ctypes.BigEndianStructure):
_pack_ = 1
_fields_ = [
("field1", ctypes.c_uint8, 8),
("field2", ctypes.c_uint8, 2),
]
class Child(Parent):
_pack_ = 1
_fields_ = [
("field3", ctypes.c_uint8, 6),
("field4", ctypes.c_uint16, 16)
]
0x12
0x0
0x2a
0xcdef
b'\x12\x02\xab\xcd\xef'
CPython versions tested on:
3.9, 3.11
Operating systems tested on:
Linux
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
首先通过继承 ctypes.BigEndianStructure 和 Child.from_buffer_copy() 重现该行为,并将子类的布局与报告中所示的 Combined 结构进行比较。跟踪继承的位域以及由此产生的缓冲区大小是如何计算的。完成的标准是子类占用预期的四字节布局,并产生与组合结构相同的字段值和字节。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- python
- 领域
- backend
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 停滞
- 描述清晰度
- 基本清楚
- 新手友好度
- 35/100