Skip to content

fix: bzip2 identify requires the stream block magic, not just "BZh<n>" - #61

Merged
nmatt0 merged 1 commit into
masterfrom
fix/bzip2-block-magic
Oct 17, 2026
Merged

nmatt0 merged 1 commit into
masterfrom
fix/bzip2-block-magic

Conversation

@nmatt0

@nmatt0 nmatt0 commented Oct 17, 2026

Copy link
Copy Markdown
Owner

Problem

The bzip2 signature matched on four bytes only: BZh plus an ASCII block-size
digit 1-9. A chance BZh<n> sequence in opaque or compressed data (for
example a modem flash image) satisfied that structural test and was reported as
a bzip2 finding, even though the bytes are not a bzip2 stream and fail to
decompress.

Fix

A real bzip2 stream carries a 48-bit block magic immediately after the 4-byte
header: 0x314159265359 for the first compressed block, or the end-of-stream
magic 0x177245385090 when the stream has no blocks. The signature now reads
those six bytes and requires one of the two, lifting the match from 4 bytes to
10. bzip2 stays at structural tier (no decode step); the change only removes
the false-positive class.

Result

  • A chance BZh7-plus-non-magic sequence in an opaque flash image is no longer
    identified as bzip2 (the spurious finding drops from the summary).
  • Genuine bzip2 streams, including an empty stream, are still identified, at
    offset 0 and at nonzero offsets.

Tests

  • New tests/test_bzip2.py (wired into run.sh): real and empty streams match;
    BZh<n>-plus-non-magic and 64 random post-header blobs are rejected.
  • Existing unit tests and the synthetic sample regression pass unchanged (the
    synthetic bzip2 sample already carries the block magic).

The bzip2 signature validated only four bytes: the "BZh" magic plus an ASCII
block-size digit (1-9). In a multi-megabyte opaque or compressed blob a chance
"BZh<n>" sequence satisfies that and was reported as a bzip2 finding, even
though the bytes are not a bzip2 stream and fail to decompress.

Require the 48-bit stream block magic that follows the 4-byte header: the first
compressed block's 0x314159265359, or the end-of-stream 0x177245385090 for a
stream with no blocks. That lifts the match from 4 bytes to 10 and removes the
false-positive class while still identifying real streams (empty streams
included). Still structural tier; no decode step added.

Adds tests/test_bzip2.py: real and empty streams identified at offset 0 and at
a nonzero offset; "BZh<n>" + non-magic and random post-header blobs rejected.
@nmatt0
nmatt0 merged commit 1a10a4f into master Oct 17, 2026
4 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.

1 participant