Skip to content

Commit c45c670

Browse files
committed
Fixed VLA/VSA for all types.
Null termination removed.
1 parent 16ea409 commit c45c670

File tree

1 file changed

+28
-12
lines changed

1 file changed

+28
-12
lines changed

dissect/cstruct/cstruct.py

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,7 @@ class Array(BaseType):
985985
When using the default C-style parser, the following syntax is supported:
986986
987987
x[3] -> 3 -> static length.
988-
x[] -> None -> null-terminated.
988+
x[] -> None -> length based on data buf length (to the end of buffer) (VLA/VSA).
989989
x[expr] -> expr -> dynamic length.
990990
"""
991991

@@ -1522,14 +1522,30 @@ def gen_struct_class(self, structure):
15221522
num = 'max(0, Expression(self.cstruct, "{expr}").evaluate(r))'.format(
15231523
expr=num.expr
15241524
)
1525-
1526-
struct_read += (
1527-
'r["{name}"] = []\n'
1528-
'for _ in xrange({num}):\n'
1529-
' r["{name}"].append(self.cstruct.{struct_name}._read(stream))\n'.format(
1530-
name=field.name, num=num, struct_name=ft.type.name
1525+
if ft.dynamic: #To the end of buffer
1526+
struct_read += (
1527+
'r["{name}"] = []\n'
1528+
'while True:\n'
1529+
' bufSize = stream.getbuffer().nbytes\n'
1530+
' bufPos = stream.tell()\n'
1531+
' try:'
1532+
' a = self.cstruct.{struct_name}._read(stream)\n'
1533+
' except:\n'
1534+
' if bufSize == bufPos:\n'
1535+
' break;\n'
1536+
' raise EOFError()\n'
1537+
' r["{name}"].append(a)\n'.format(
1538+
name=field.name, num=num, struct_name=ft.type.name
1539+
)
1540+
)
1541+
else:
1542+
struct_read += (
1543+
'r["{name}"] = []\n'
1544+
'for _ in xrange({num}):\n'
1545+
' r["{name}"].append(self.cstruct.{struct_name}._read(stream))\n'.format(
1546+
name=field.name, num=num, struct_name=ft.type.name
1547+
)
15311548
)
1532-
)
15331549
else:
15341550
struct_read += 'r["{name}"] = self.cstruct.{struct_name}._read(stream)\n'.format(
15351551
name=field.name, struct_name=ft.name
@@ -1713,14 +1729,14 @@ def gen_dynamic_block(self, field):
17131729
t = field.type.type
17141730
reader = None
17151731

1716-
if not field.type.count: # Null terminated
1732+
if not field.type.count: #To the end of buffer
17171733
if isinstance(t, PackedType):
17181734
reader = (
17191735
't = []\nwhile True:\n'
17201736
' d = stream.read({size})\n'
1737+
' if len(d) == 0: break\n'
17211738
' if len(d) != {size}: raise EOFError()\n'
17221739
' v = struct.unpack(self.cstruct.endian + "{packchar}", d)[0]\n'
1723-
' if v == 0: break\n'
17241740
' t.append(v)'.format(size=t.size, packchar=t.packchar)
17251741
)
17261742

@@ -1738,14 +1754,14 @@ def gen_dynamic_block(self, field):
17381754

17391755
if isinstance(t, WcharType):
17401756
reader += ".decode('utf-16-le' if self.cstruct.endian == '<' else 'utf-16-be')"
1741-
elif isinstance(t, BytesInteger):
1757+
elif isinstance(t, BytesInteger): #To the end of buffer
17421758
reader = (
17431759
't = []\n'
17441760
'while True:\n'
17451761
' d = stream.read({size})\n'
1762+
' if len(d) == 0: break\n'
17461763
' if len(d) != {size}: raise EOFError()\n'
17471764
' v = BytesInteger.parse(d, {size}, 1, {signed}, self.cstruct.endian)\n'
1748-
' if v == 0: break\n'
17491765
' t.append(v)'.format(size=t.size, signed=t.signed)
17501766
)
17511767

0 commit comments

Comments
 (0)