Skip to content

ISO unpacker bugfix for files in root directory#750

Merged
paulnoalhyt merged 2 commits into
masterfrom
bugfix/iso_file_at_root
Jun 3, 2026
Merged

ISO unpacker bugfix for files in root directory#750
paulnoalhyt merged 2 commits into
masterfrom
bugfix/iso_file_at_root

Conversation

@paulnoalhyt
Copy link
Copy Markdown
Collaborator

@paulnoalhyt paulnoalhyt commented May 26, 2026

  • I have reviewed the OFRAK contributor guide and attest that this pull request is in accordance with it.
  • I have made or updated a changelog entry for the changes in this pull request.

One sentence summary of this PR (This should go in the CHANGELOG!)

Fix bug in ISO9660Unpacker for files in root directory

Link to Related Issue(s)

None.

Please describe the changes in your request.

When ISOs have files at the root level (like this alpine ISO I was working with), the ISO unpacker would create the following resource tree:

┌d58d0a39b8c54f769c61ab6bcb4d5084: [caption=(File: alpine-virt-3.23.4-aarch64.iso, ISO9660Image), attributes=(AttributesType[FilesystemEntry], Magic, ISO9660ImageAttributes), global_offset=(0x0-0x5987800), parent_offset=(0x0-0x0), data_hash=3ced796c]
...
└───┬23d87c85b80c427db443694dccc02fe6: [caption=(Folder: ), attributes=(AttributesType[FilesystemEntry]), global_offset=(0x0-0x0), parent_offset=(0x0-0x0), data_ascii=""]
    ├────11409fedde8e4105bb6f01031c3810d9: [caption=(ISO9660Entry, File: boot.catalog), attributes=(AttributesType[FilesystemEntry], AttributesType[ISO9660Entry]), global_offset=(0x0-0x800), parent_offset=(0x0-0x0), data_hash=6dda4cd1]
    └────42d79ad8ace3408da7666936e98fbeaa: [caption=(ISO9660Entry, File: .alpine-release), attributes=(AttributesType[FilesystemEntry], AttributesType[ISO9660Entry]), global_offset=(0x0-0x1a), parent_offset=(0x0-0x0), data_hex=616c70696e652d766972742d332e32332e34203236303431350a]

Notice that the files boot.catalog and .alpine-release are in the root directory in the ISO image, but here it creates a Folder without any name to contain them, which is wrong.

This lead to the following error:

ofrak.service.job_service_i.ComponentAutoRunFailure: Component ISO9660Unpacker failed when running on d58d0a39b8c54f769c61ab6bcb4d5084. Component was chosen because it matched filters (((ComponentTypeFilter(Unpacker) or ComponentTypeFilter(Identifier))) and ((ComponentTypeFilter(Identifier) and ComponentTargetFilter(FilesystemRoot, ISO9660Image)) or (ComponentTypeFilter(Analyzer) and ComponentTargetFilter(FilesystemRoot, ISO9660Image)) or (not ComponentTypeFilter(Identifier) and not ComponentTypeFilter(Analyzer) and (ComponentTargetFilter(ISO9660Image) then ComponentTargetFilter(FilesystemRoot)))))

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/iso_test.py", line 19, in <module>
    ofrak.run(main, args.file)
  File "/ofrak_core/src/ofrak/ofrak_context.py", line 206, in run
    asyncio.get_event_loop().run_until_complete(self.run_async(func, *args))
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 647, in run_until_complete
    return future.result()
  File "/ofrak_core/src/ofrak/ofrak_context.py", line 199, in run_async
    await func(ofrak_context, *args)
  File "/iso_test.py", line 9, in main
    await root_resource.unpack()
  File "/ofrak_core/src/ofrak/resource.py", line 463, in unpack
    return await self.auto_run(all_identifiers=True, all_unpackers=True)
  File "/ofrak_core/src/ofrak/resource.py", line 436, in auto_run
    components_result = await self._job_service.run_components(
  File "/ofrak_core/src/ofrak/service/job_service.py", line 277, in run_components
    individual_component_results = await self._auto_run_components(
  File "/ofrak_core/src/ofrak/service/job_service.py", line 471, in _auto_run_components
    raise component_run_error from ComponentAutoRunFailure(
  File "/ofrak_core/src/ofrak/service/job_service.py", line 133, in _run_component
    result = await component.run(
  File "/ofrak_core/src/ofrak/component/abstract.py", line 94, in run
    await self._run(resource, config)
  File "/ofrak_core/src/ofrak/component/unpacker.py", line 85, in _run
    await self._validate_unpacked_children(resource)
  File "/ofrak_core/src/ofrak/component/unpacker.py", line 147, in _validate_unpacked_children
    raise ValueError(
ValueError: Unpacker ISO9660Unpacker created resource 23d87c85b80c427db443694dccc02fe6 but its tags {FilesystemEntry, Folder} do not match any of the expected patterns this unpacker should create: ISO9660Entry

With this PR, the leading / in /boot.catalog is stripped, so the unpacker create the relevant files in the root directory:

┌b3f20e18721842b0aa51d40c26dc0c22: [caption=(File: alpine-virt-3.23.4-aarch64.iso, ISO9660Image), attributes=(AttributesType[FilesystemEntry], Magic, ISO9660ImageAttributes), global_offset=(0x0-0x5987800), parent_offset=(0x0-0x0), data_hash=3ced796c]
...
├────0bbb642e8f184661911e77c4b2c483c2: [caption=(ISO9660Entry, File: boot.catalog), attributes=(AttributesType[FilesystemEntry], AttributesType[ISO9660Entry]), global_offset=(0x0-0x800), parent_offset=(0x0-0x0), data_hash=6dda4cd1]
└────0c71ec1eb9a14e2e8be9aa2010e32a2e: [caption=(ISO9660Entry, File: .alpine-release), attributes=(AttributesType[FilesystemEntry], AttributesType[ISO9660Entry]), global_offset=(0x0-0x1a), parent_offset=(0x0-0x0), data_hex=616c70696e652d766972742d332e32332e34203236303431350a]

I added a regression test for this.

Anyone you think should look at this, specifically?

@rbs-jacob ?

Copy link
Copy Markdown
Member

@rbs-jacob rbs-jacob left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

@paulnoalhyt paulnoalhyt merged commit 3030b1b into master Jun 3, 2026
102 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants