SAIP: make _split_der robust to truncated/malformed input
decode_saip_profile (used by make_profile --inspect on user files) could IndexError on a truncated tail. _split_der now stops at the last complete DER element and returns the valid prefix. Tests: +1; 109 pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
b64e9dbd54
commit
9a36b1a5fa
|
|
@ -142,7 +142,11 @@ def create_saip_profile(
|
|||
|
||||
|
||||
def _split_der(data: bytes):
|
||||
"""Yield byte-range slices of consecutive top-level DER TLVs in ``data``."""
|
||||
"""Yield byte-range slices of consecutive top-level DER TLVs in ``data``.
|
||||
|
||||
Stops cleanly at the last complete element so a truncated or malformed tail
|
||||
yields the valid prefix instead of raising.
|
||||
"""
|
||||
i, n = 0, len(data)
|
||||
while i < n:
|
||||
start = i
|
||||
|
|
@ -151,15 +155,21 @@ def _split_der(data: bytes):
|
|||
if first & 0x1F == 0x1F: # high-tag-number form: skip continuation octets
|
||||
while i < n and data[i] & 0x80:
|
||||
i += 1
|
||||
i += 1
|
||||
i += 1 # final tag byte
|
||||
if i >= n: # no room for a length octet
|
||||
return
|
||||
length_byte = data[i]
|
||||
i += 1
|
||||
if length_byte & 0x80: # long-form length
|
||||
num = length_byte & 0x7F
|
||||
if i + num > n:
|
||||
return
|
||||
length = int.from_bytes(data[i:i + num], "big")
|
||||
i += num
|
||||
else:
|
||||
length = length_byte
|
||||
if i + length > n: # truncated content
|
||||
return
|
||||
i += length
|
||||
yield data[start:i]
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,17 @@ class TestSaipEncoding:
|
|||
assert by["header"]["major-version"] == 3
|
||||
assert by["mf"]["ef-iccid"] == [("fillFileContent", enc_iccid(iccid))]
|
||||
|
||||
@saip_required
|
||||
def test_truncated_profile_yields_prefix_not_crash(self):
|
||||
pkg = saip.create_saip_profile("302720000000001", generate_ki(),
|
||||
b"\x22" * 16, generate_iccid())
|
||||
full = saip.decode_saip_profile(pkg)
|
||||
# Cutting mid-element must not raise; it returns the complete prefix.
|
||||
partial = saip.decode_saip_profile(pkg[:-3])
|
||||
assert len(partial) < len(full)
|
||||
assert [c for c, _ in partial] == [c for c, _ in full][:len(partial)]
|
||||
assert saip.decode_saip_profile(b"\xa0\x82") == [] # bogus length, no crash
|
||||
|
||||
@saip_required
|
||||
def test_imsi_embedded_in_usim(self):
|
||||
imsi = "302720123456789"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user