python / python/cpython

ctypes.Structure superclass with bitfields do not parse properly when it doesn't end on a byte boundary

Aberta
#117,942 0 comentários 0 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

topic-ctypes type-bug
Linguagem predominante
Python
Estrelas
77.2k
Forks
36k
Métricas de merge de PRs
Métricas de PR pendentes

Descrição

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

Guia de contribuição

Abrir o guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Direção de pesquisa

Comece reproduzindo o comportamento por meio da herança de ctypes.BigEndianStructure e de Child.from_buffer_copy(), comparando o layout da subclasse com a estrutura Combined mostrada no relatório. Rastreie como os campos de bits herdados e o tamanho resultante do buffer são calculados. O trabalho estará concluído quando a subclasse consumir o layout esperado de quatro bytes e produzir os mesmos valores de campo e bytes que a estrutura combinada.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
python
Domínio
backend
Tipo de issue
Bug
Dificuldade
4/5
Tempo estimado
3-5 dias
Status de atividade
Estagnada
Clareza
Razoavelmente clara
Facilidade para iniciantes
35/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.