Class: Omnizip::Formats::XzImpl::StreamHeaderParser

Inherits:
Object
  • Object
show all
Defined in:
lib/omnizip/formats/xz_impl/stream_header_parser.rb

Overview

XZ Stream Header parser

Stream Header format (12 bytes):

  • Magic: 0xFD 0x37 0x7A 0x58 0x5A 0x00 (6 bytes)
  • Stream Flags: check_type and reserved (2 bytes)
  • CRC32: of magic + flags (4 bytes, little-endian)

Reference: /tmp/xz-source/src/liblzma/common/stream_header_decoder.c

Constant Summary collapse

HEADER_MAGIC =

Stream header magic bytes

[0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00].freeze
HEADER_SIZE =

Stream header size in bytes

12

Class Method Summary collapse

Class Method Details

.parse(input) ⇒ Hash

Parse stream header from input stream

Parameters:

  • input (IO)

    Input stream positioned at stream start

Returns:

  • (Hash)

    Parsed header data with keys:

    • check_type: Integer (0=None, 1=CRC32, 4=CRC64, 10=SHA256)

Raises:

  • (RuntimeError)

    If header is invalid or CRC mismatch



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/omnizip/formats/xz_impl/stream_header_parser.rb', line 49

def self.parse(input)
  # Read 12 bytes
  header = input.read(HEADER_SIZE)
  if header.nil? || header.bytesize < HEADER_SIZE
    raise FormatError,
          "Unexpected end of file: incomplete stream header"
  end

  # Verify magic bytes (first 6 bytes)
  magic = header[0..5].bytes
  unless magic == HEADER_MAGIC
    raise FormatError, "Invalid XZ magic bytes: got #{magic.map do |b|
      b.to_s(16).upcase
    end.join(' ')}"
  end

  # Extract stream flags (bytes 6-7)
  flags = header[6..7]

  # Byte 6: reserved (must be 0)
  if flags.getbyte(0) != 0
    raise FormatError, "Invalid stream flags: reserved byte is non-zero"
  end

  # Byte 7: check type (low 4 bits) + reserved (high 4 bits)
  check_flags = flags.getbyte(1)
  check_type = check_flags & 0x0F
  reserved = (check_flags >> 4) & 0x0F

  if reserved != 0
    raise FormatError,
          "Invalid stream flags: reserved bits are non-zero"
  end

  # Validate check type (only 0, 1, 4, 10 are valid)
  unless [0, 1, 4, 10].include?(check_type)
    raise FormatError,
          "Unsupported check type: #{check_type} (not supported)"
  end

  # Verify CRC32 (bytes 8-11)
  # IMPORTANT: CRC is calculated ONLY over Stream Flags (2 bytes), NOT magic!
  # Reference: /tmp/xz-source/src/liblzma/common/stream_flags_decoder.c
  crc_data = flags # Only flags, not magic
  stored_crc = header[8..11].unpack1("V")
  actual_crc = Zlib.crc32(crc_data)

  if actual_crc != stored_crc
    raise FormatError,
          "Stream header CRC mismatch: expected #{stored_crc}, got #{actual_crc}"
  end

  { check_type: check_type }
end