Skip to content

Commit 3030b1b

Browse files
paulnoalhytPaul
andauthored
ISO unpacker bugfix for files in root directory (#750)
* Fix bug in ISO unpacker when files are in the root directory. Added regression test --------- Co-authored-by: Paul <paul@redballoonsecurity.com>
1 parent 958e0e5 commit 3030b1b

3 files changed

Lines changed: 41 additions & 1 deletion

File tree

ofrak_core/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
3737
- Fix bug in Segment Injector: favor regions with data when injecting data ([#682](https://github.com/redballoonsecurity/ofrak/pull/682))
3838
- Pass `usedforsecurity=False` to non-cryptographic `hashlib` calls to prevent failures when Python links against FIPS OpenSSL ([#744](https://github.com/redballoonsecurity/ofrak/pull/744))
3939
- Fix `chdir` in UEFI components causing failing tests. ([#747](https://github.com/redballoonsecurity/ofrak/pull/747))
40+
- Fix bug in `ISO9660Unpacker` for files in root directory. ([#750](https://github.com/redballoonsecurity/ofrak/pull/750))
4041

4142
## [3.3.0](https://github.com/redballoonsecurity/ofrak/compare/ofrak-v3.2.0...ofrak-v3.3.0) - 2025-10-03
4243

ofrak_core/src/ofrak/core/iso9660.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ async def unpack(self, resource: Resource, config=None):
257257
iso_version=iso_version,
258258
)
259259
await iso_resource.add_file(
260-
path,
260+
path.lstrip("/"),
261261
file_data,
262262
None,
263263
None,

ofrak_core/tests/components/test_iso_component.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import pytest
1414
from pycdlib import PyCdlib
1515

16+
from ofrak import OFRAKContext
1617
from ofrak.resource import Resource
1718
from ofrak.core.iso9660 import (
1819
ISO9660Entry,
@@ -167,3 +168,41 @@ def create_test_file(self, tmpdir):
167168
)
168169
iso.write(os.path.join(tmpdir, self.TEST_ISO_NAME))
169170
self._test_file = os.path.join(tmpdir, self.TEST_ISO_NAME)
171+
172+
173+
@pytest.mark.skipif_missing_deps([ISO9660Unpacker])
174+
class TestIso9660RootLevelFileUnpack:
175+
"""
176+
Test for an ISO that contains a file directly at the root (no enclosing directory).
177+
"""
178+
179+
TEST_ISO_NAME = "root_file.iso"
180+
ROOT_FILE_NAME = "ROOTFILE.TXT"
181+
ROOT_FILE_DATA = b"hello at the root\n"
182+
183+
@pytest.fixture
184+
def iso_with_root_level_file(self, tmpdir):
185+
iso = PyCdlib()
186+
iso.new(interchange_level=3)
187+
iso.add_fp(
188+
BytesIO(self.ROOT_FILE_DATA),
189+
len(self.ROOT_FILE_DATA),
190+
"/" + self.ROOT_FILE_NAME + ";1",
191+
)
192+
path = os.path.join(tmpdir, self.TEST_ISO_NAME)
193+
iso.write(path)
194+
iso.close()
195+
return path
196+
197+
async def test_unpack_iso_with_root_level_file(
198+
self, ofrak_context: OFRAKContext, iso_with_root_level_file
199+
):
200+
root_resource = await ofrak_context.create_root_resource_from_file(iso_with_root_level_file)
201+
await root_resource.unpack()
202+
203+
iso_resource = await root_resource.view_as(ISO9660Image)
204+
for descendant in await iso_resource.resource.get_descendants():
205+
assert ISO9660Entry in descendant.get_tags(), (
206+
f"Descendant {descendant.get_id().hex()} with tags {tags} is missing "
207+
f"ISO9660Entry"
208+
)

0 commit comments

Comments
 (0)