dissect.cstruct 4.6.dev4__tar.gz → 4.6.dev6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/PKG-INFO +1 -1
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/parser.py +2 -2
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/tools/stubgen.py +3 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/structure.py +39 -9
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect.cstruct.egg-info/PKG-INFO +1 -1
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_parser.py +16 -1
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_tools_stubgen.py +20 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/.git-blame-ignore-revs +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/.gitattributes +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/CHANGELOG.md +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/COPYRIGHT +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/LICENSE +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/MANIFEST.in +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/README.md +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/__init__.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/bitbuffer.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/compiler.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/cstruct.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/exceptions.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/expression.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/tools/__init__.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/__init__.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/base.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/char.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/enum.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/flag.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/int.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/leb128.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/packed.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/pointer.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/void.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/types/wchar.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect/cstruct/utils.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect.cstruct.egg-info/SOURCES.txt +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect.cstruct.egg-info/dependency_links.txt +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect.cstruct.egg-info/entry_points.txt +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect.cstruct.egg-info/requires.txt +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect.cstruct.egg-info/top_level.txt +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/examples/disk.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/examples/mirai.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/examples/pe.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/examples/protobuf.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/examples/secdesc.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/pyproject.toml +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/setup.cfg +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/__init__.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/_data/testdef.txt +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/_docs/Makefile +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/_docs/__init__.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/_docs/conf.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/_docs/index.rst +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/conftest.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_align.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_annotations.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_basic.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_bitbuffer.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_bitfield.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_compiler.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_ctypes.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_expression.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_base.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_char.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_custom.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_enum.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_flag.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_int.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_leb128.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_packed.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_pointer.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_structure.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_union.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_void.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_types_wchar.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/test_utils.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tests/utils.py +0 -0
- {dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dissect.cstruct
|
|
3
|
-
Version: 4.6.
|
|
3
|
+
Version: 4.6.dev6
|
|
4
4
|
Summary: A Dissect module implementing a parser for C-like structures: structure parsing in Python made easy
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License: Apache License 2.0
|
|
@@ -314,11 +314,11 @@ class TokenParser(Parser):
|
|
|
314
314
|
tokens.eol()
|
|
315
315
|
break
|
|
316
316
|
|
|
317
|
-
if tokens.next not in (self.TOK.NAME, self.TOK.DEFS):
|
|
317
|
+
if tokens.next not in (self.TOK.NAME, self.TOK.DEFS, self.TOK.IDENTIFIER):
|
|
318
318
|
break
|
|
319
319
|
|
|
320
320
|
ntoken = tokens.consume()
|
|
321
|
-
if ntoken
|
|
321
|
+
if ntoken in (self.TOK.NAME, self.TOK.IDENTIFIER):
|
|
322
322
|
names.append(ntoken.value.strip())
|
|
323
323
|
elif ntoken == self.TOK.DEFS:
|
|
324
324
|
names.extend([name.strip() for name in ntoken.value.strip().split(",")])
|
|
@@ -92,6 +92,9 @@ def generate_cstruct_stub(cs: cstruct, module_prefix: str = "", cls_name: str =
|
|
|
92
92
|
stub = f"{name}: TypeAlias = {typedef.__name__}"
|
|
93
93
|
elif issubclass(typedef, (types.Enum, types.Flag)):
|
|
94
94
|
stub = generate_enum_stub(typedef, cs_prefix=cs_prefix, module_prefix=module_prefix)
|
|
95
|
+
elif issubclass(typedef, types.Pointer):
|
|
96
|
+
typehint = generate_typehint(typedef, prefix=cs_prefix, module_prefix=module_prefix)
|
|
97
|
+
stub = f"{name}: TypeAlias = {typehint}"
|
|
95
98
|
elif issubclass(typedef, types.Structure):
|
|
96
99
|
stub = generate_structure_stub(typedef, cs_prefix=cs_prefix, module_prefix=module_prefix)
|
|
97
100
|
elif issubclass(typedef, types.BaseType):
|
|
@@ -828,13 +828,13 @@ def _generate_structure__init__(fields: list[Field]) -> FunctionType:
|
|
|
828
828
|
Args:
|
|
829
829
|
fields: List of field names.
|
|
830
830
|
"""
|
|
831
|
-
|
|
831
|
+
mapping = _generate_co_mapping(fields)
|
|
832
832
|
|
|
833
|
-
template: FunctionType = _make_structure__init__(len(
|
|
833
|
+
template: FunctionType = _make_structure__init__(len(fields))
|
|
834
834
|
return type(template)(
|
|
835
835
|
template.__code__.replace(
|
|
836
|
-
co_names=
|
|
837
|
-
co_varnames=(
|
|
836
|
+
co_names=_remap_co_values(template.__code__.co_names, mapping),
|
|
837
|
+
co_varnames=_remap_co_values(template.__code__.co_varnames, mapping),
|
|
838
838
|
),
|
|
839
839
|
template.__globals__ | {f"__{field._name}_default__": field.type.__default__() for field in fields},
|
|
840
840
|
argdefs=template.__defaults__,
|
|
@@ -847,20 +847,50 @@ def _generate_union__init__(fields: list[Field]) -> FunctionType:
|
|
|
847
847
|
Args:
|
|
848
848
|
fields: List of field names.
|
|
849
849
|
"""
|
|
850
|
-
|
|
850
|
+
mapping = _generate_co_mapping(fields)
|
|
851
851
|
|
|
852
|
-
template: FunctionType = _make_union__init__(len(
|
|
852
|
+
template: FunctionType = _make_union__init__(len(fields))
|
|
853
853
|
return type(template)(
|
|
854
854
|
template.__code__.replace(
|
|
855
|
-
co_consts=(
|
|
856
|
-
co_names=(
|
|
857
|
-
co_varnames=(
|
|
855
|
+
co_consts=_remap_co_values(template.__code__.co_consts, mapping),
|
|
856
|
+
co_names=_remap_co_values(template.__code__.co_names, mapping),
|
|
857
|
+
co_varnames=_remap_co_values(template.__code__.co_varnames, mapping),
|
|
858
858
|
),
|
|
859
859
|
template.__globals__ | {f"__{field._name}_default__": field.type.__default__() for field in fields},
|
|
860
860
|
argdefs=template.__defaults__,
|
|
861
861
|
)
|
|
862
862
|
|
|
863
863
|
|
|
864
|
+
def _generate_co_mapping(fields: list[Field]) -> dict[str, str]:
|
|
865
|
+
"""Generates a mapping of generated code object names to field names.
|
|
866
|
+
|
|
867
|
+
The generated code uses names like ``_0``, ``_1``, etc. for fields, and ``_0_default``, ``_1_default``, etc.
|
|
868
|
+
for default initializer values. Return a mapping of these names to the actual field names.
|
|
869
|
+
|
|
870
|
+
Args:
|
|
871
|
+
fields: List of field names.
|
|
872
|
+
"""
|
|
873
|
+
return {
|
|
874
|
+
key: value
|
|
875
|
+
for i, field in enumerate(fields)
|
|
876
|
+
for key, value in [(f"_{i}", field._name), (f"_{i}_default", f"__{field._name}_default__")]
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
def _remap_co_values(value: tuple[Any, ...], mapping: dict[str, str]) -> tuple[Any, ...]:
|
|
881
|
+
"""Remaps code object values using a mapping.
|
|
882
|
+
|
|
883
|
+
This is used to replace generated code object names with actual field names.
|
|
884
|
+
|
|
885
|
+
Args:
|
|
886
|
+
value: The original code object values.
|
|
887
|
+
mapping: A mapping of generated code object names to field names.
|
|
888
|
+
"""
|
|
889
|
+
# Only attempt to remap if the value is a string, otherwise return it as is
|
|
890
|
+
# This is to avoid issues with trying to remap non-hashable types, and we only need to replace strings anyway
|
|
891
|
+
return tuple(mapping.get(v, v) if isinstance(v, str) else v for v in value)
|
|
892
|
+
|
|
893
|
+
|
|
864
894
|
def _generate__eq__(fields: list[str]) -> FunctionType:
|
|
865
895
|
"""Generates an ``__eq__`` method for a class with the specified fields.
|
|
866
896
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dissect.cstruct
|
|
3
|
-
Version: 4.6.
|
|
3
|
+
Version: 4.6.dev6
|
|
4
4
|
Summary: A Dissect module implementing a parser for C-like structures: structure parsing in Python made easy
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License: Apache License 2.0
|
|
@@ -7,7 +7,7 @@ import pytest
|
|
|
7
7
|
|
|
8
8
|
from dissect.cstruct.exceptions import ParserError
|
|
9
9
|
from dissect.cstruct.parser import TokenParser
|
|
10
|
-
from dissect.cstruct.types import BaseArray, Pointer
|
|
10
|
+
from dissect.cstruct.types import BaseArray, Pointer, Structure
|
|
11
11
|
from tests.utils import verify_compiled
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
@@ -149,3 +149,18 @@ def test_includes(cs: cstruct) -> None:
|
|
|
149
149
|
assert cs.myStruct.__name__ == "myStruct"
|
|
150
150
|
assert len(cs.myStruct.fields) == 1
|
|
151
151
|
assert cs.myStruct.fields.get("charVal")
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def test_typedef_pointer(cs: cstruct) -> None:
|
|
155
|
+
cdef = """
|
|
156
|
+
typedef struct _IMAGE_DATA_DIRECTORY {
|
|
157
|
+
DWORD VirtualAddress;
|
|
158
|
+
DWORD Size;
|
|
159
|
+
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
|
|
160
|
+
"""
|
|
161
|
+
cs.load(cdef)
|
|
162
|
+
|
|
163
|
+
assert issubclass(cs._IMAGE_DATA_DIRECTORY, Structure)
|
|
164
|
+
assert cs.IMAGE_DATA_DIRECTORY is cs._IMAGE_DATA_DIRECTORY
|
|
165
|
+
assert issubclass(cs.PIMAGE_DATA_DIRECTORY, Pointer)
|
|
166
|
+
assert cs.PIMAGE_DATA_DIRECTORY.type == cs._IMAGE_DATA_DIRECTORY
|
|
@@ -319,6 +319,26 @@ def test_generate_structure_stub(cs: cstruct, cdef: str, expected: str) -> None:
|
|
|
319
319
|
""",
|
|
320
320
|
id="define literals",
|
|
321
321
|
),
|
|
322
|
+
pytest.param(
|
|
323
|
+
"""
|
|
324
|
+
typedef struct _Test {
|
|
325
|
+
uint8 a;
|
|
326
|
+
} Test, *pTest;
|
|
327
|
+
""",
|
|
328
|
+
"""
|
|
329
|
+
class cstruct(cstruct):
|
|
330
|
+
class _Test(Structure):
|
|
331
|
+
a: cstruct.uint8
|
|
332
|
+
@overload
|
|
333
|
+
def __init__(self, a: cstruct.uint8 | None = ...): ...
|
|
334
|
+
@overload
|
|
335
|
+
def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ...
|
|
336
|
+
|
|
337
|
+
Test: TypeAlias = _Test
|
|
338
|
+
pTest: TypeAlias = Pointer[cstruct._Test]
|
|
339
|
+
""",
|
|
340
|
+
id="pointer alias",
|
|
341
|
+
),
|
|
322
342
|
],
|
|
323
343
|
)
|
|
324
344
|
def test_generate_cstruct_stub(cs: cstruct, cdef: str, expected: str) -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect.cstruct.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect.cstruct.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
{dissect_cstruct-4.6.dev4 → dissect_cstruct-4.6.dev6}/dissect.cstruct.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|