Skip to content

fix: records_from_file raises IndexError when magic number is unrecognised (closes #75) - #81

Open
seam0814 wants to merge 1 commit into
Semi-ATE:mainfrom
seam0814:fix-records-from-file-indexerror-no-magic
Open

fix: records_from_file raises IndexError when magic number is unrecognised (closes #75)#81
seam0814 wants to merge 1 commit into
Semi-ATE:mainfrom
seam0814:fix-records-from-file-indexerror-no-magic

Conversation

@seam0814

Copy link
Copy Markdown

Summary

`extension_from_magic_number_in_file()` returns an empty list when the
file's content does not match any recognised magic-number signature.
`records_from_file.init` then dereferenced `compression[0]`
unconditionally:

```python
compression = extension_from_magic_number_in_file(FileName)
if compression[0] == '.xz':
...
```

So any STDF file produced by older ATE tooling that does not carry the
`.stdf` magic header (or simply the wrong header) raised

```
IndexError: list index out of range
```

at the very first line of the constructor, before the file was ever
opened — exactly the symptom in #75.

Closes #75.

Change

```diff

  • compression = extension_from_magic_number_in_file(FileName)
  • if compression[0] == '.xz':
  • compression = extension_from_magic_number_in_file(FileName)
  • compression_ext = compression[0] if compression else None
  • if compression_ext == '.xz':
    ```

`compression[0]` was used at four call sites (`.xz`, `.bz2`, `.gz`,
`.zip`); each is rewritten against `compression_ext`. The empty-magic
case now falls through to the existing "assume standard binary stdf"
branch, which is already responsible for non-compressed files. No
behavioural change on any previously-handled magic value.

Test

Added `test_records_from_file_handles_unrecognised_magic_number` in
`tests/test_utils.py`. It uses `unittest.mock.patch` to force
`extension_from_magic_number_in_file` to return `[]` and then calls
`records_from_file` on a real FAR-only STDF blob, asserting the FAR
record round-trips without raising.

Full suite: 32 passed, 4 skipped, 0 failed.

Note on a latent follow-up

When the original `IndexError` fires inside `init`, `self.fd`
is never assigned, so the subsequent `del` raises a chained
`AttributeError: 'records_from_file' object has no attribute 'fd'`.
With the `IndexError` gone this path is no longer reachable from the
reported workflow, but `del` could still be made defensive in a
follow-up (`if getattr(self, 'fd', None) is not None: self.fd.close()`).
Happy to send that as a separate PR if you'd like.

Scope

Two-file change (`Semi_ATE/STDF/utils.py` + `tests/test_utils.py`),
no public API change, no behavioural change on any path that
previously worked.

…nised (closes Semi-ATE#75)

`extension_from_magic_number_in_file()` returns an empty list when the
file's content does not match any of the recognised magic-number
signatures. `records_from_file.__init__` then dereferenced
`compression[0]` unconditionally:

    compression = extension_from_magic_number_in_file(FileName)
    if compression[0] == '.xz':
        ...

so any STDF file produced by older ATE tooling that does not carry the
'.stdf' magic header (or simply the wrong header) raised

    IndexError: list index out of range

at the very first line of the constructor, before the file was ever
opened. The reporter's minimal "print all records" demo crashed for
exactly this reason.

Lift the optional index out into a local:

    compression_ext = compression[0] if compression else None
    if compression_ext == '.xz':
        ...
    else:
        # Assume standard binary stdf file
        ...

and route the empty-magic case through the existing "assume standard
binary stdf" fall-through branch. No code reshuffling beyond that —
behaviour on every previously-handled magic value is byte-identical.

Regression test in `tests/test_utils.py` uses `unittest.mock.patch` to
force `extension_from_magic_number_in_file` to return `[]` and then
calls `records_from_file` on a real FAR-only STDF blob, asserting the
FAR record round-trips without raising.

Full suite: 32 passed, 4 skipped.

Note on a latent secondary symptom: when the IndexError fires inside
`__init__`, `self.fd` is never assigned, so the subsequent
`__del__` raises a chained `AttributeError: 'records_from_file' object
has no attribute 'fd'`. With the IndexError gone this path is no
longer reachable from the reported workflow, but `__del__` could
still be made defensive in a follow-up.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@seam0814
seam0814 requested review from nerohmot and seimit as code owners June 21, 2026 10:42
@seam0814

Copy link
Copy Markdown
Author

Gentle nudge — small guard against IndexError on unknown magic bytes in records_from_file (closes #75). Happy to rebase or rework the error path.

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.

utils.py err msg

1 participant