ctypes.Structure superclass with bitfields do not parse properly when it doesn't end on a byte boundary
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Python
- Star
- 77.2k
- Fork
- 36k
- Chỉ số merge pull request
- Chỉ số pull request đang chờ
Mô tả
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
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu bằng cách tái hiện hành vi thông qua việc kế thừa ctypes.BigEndianStructure và Child.from_buffer_copy(), đồng thời so sánh layout của lớp con với cấu trúc Combined được nêu trong báo cáo. Theo dõi cách các bitfield được kế thừa và kích thước bộ đệm tương ứng được tính toán. Được xem là hoàn tất khi lớp con sử dụng layout bốn byte như mong đợi và tạo ra các giá trị trường cùng các byte giống với cấu trúc kết hợp.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- python
- Lĩnh vực
- backend
- Loại issue
- Lỗi
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 35/100