Skip to content

Commit 4d60e3c

Browse files
authored
Fix inode checksum calculation (#12)
* Switch to crc32c * Bump version * Add missing offset, fix checksum logic * Switch back to crcmod * Clamp * Remove unneeded initialization * Add missing data * Move to helper * Normalize imports
1 parent 290185a commit 4d60e3c

5 files changed

Lines changed: 37 additions & 8 deletions

File tree

ext4/extent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
from ctypes import c_uint16
33
from ctypes import sizeof
44

5-
from .struct import Ext4Struct
65
from .struct import crc32c
6+
from .struct import Ext4Struct
77

88

99
class ExtentBlocks(object):

ext4/inode.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111

1212
from ._compat import override
1313

14-
from .struct import Ext4Struct
1514
from .struct import crc32c
15+
from .struct import Ext4Struct
1616
from .struct import MagicError
1717

1818
from .enum import EXT4_OS
@@ -189,6 +189,16 @@ def __init__(self, volume, offset, i_no):
189189
super().__init__(volume, offset)
190190
self.tree = ExtentTree(self)
191191

192+
@property
193+
def extra_inode_data(self) -> bytes:
194+
if not self.has_hi:
195+
return b""
196+
197+
size = sizeof(self)
198+
assert size == self.EXT2_GOOD_OLD_INODE_SIZE + self.i_extra_isize
199+
_ = self.volume.seek(self.offset + size)
200+
return self.volume.read(self.superblock.s_inode_size - size)
201+
192202
@property
193203
def superblock(self):
194204
return self.volume.superblock
@@ -248,7 +258,12 @@ def checksum(self):
248258
csum = crc32c(b"\0" * Inode.i_checksum_hi.size, csum)
249259
offset += Inode.i_checksum_hi.size
250260

251-
csum = crc32c(data[offset:], csum)
261+
csum = crc32c(
262+
data[offset:],
263+
csum,
264+
)
265+
if self.superblock.s_inode_size - len(data) > 0:
266+
csum = crc32c(self.extra_inode_data, csum)
252267

253268
if not self.has_hi:
254269
csum &= 0xFFFF

ext4/xattr.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
from ctypes import c_uint8
66
from ctypes import sizeof
77

8-
from .struct import Ext4Struct
9-
from .struct import crc32c
10-
from .enum import EXT4_FL
11-
from .enum import EXT4_FEATURE_INCOMPAT
128
from ._compat import override
139

10+
from .enum import EXT4_FEATURE_INCOMPAT
11+
from .enum import EXT4_FL
12+
13+
from .struct import crc32c
14+
from .struct import Ext4Struct
15+
1416

1517
class ExtendedAttributeError(Exception):
1618
pass

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "ext4"
3-
version = "1.2.1"
3+
version = "1.2.2"
44
authors = [
55
{ name="Eeems", email="eeems@eeems.email" },
66
]

test.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,18 @@ def _assert(source: str):
6565

6666
# Extract specific file
6767
volume = ext4.Volume(f, offset=offset)
68+
69+
try:
70+
print("Validate root inode: ", end="")
71+
volume.root.validate()
72+
print("pass")
73+
74+
except ext4.struct.ChecksumError as e:
75+
FAILED = True
76+
print("fail")
77+
print(" ", end="")
78+
print(e)
79+
6880
inode = cast(ext4.File, volume.inode_at("/test.txt"))
6981
_assert("isinstance(inode, ext4.File)")
7082
b = inode.open()

0 commit comments

Comments
 (0)