Decode EF_IMPU/IMPI/DOMAIN empty records as empty, not text
_decode_nai (decode.py) only treated an all-0xFF record as empty.
A record that is a lone identity tag, or a tag with a zero-length
value (e.g. 80 00 + FF erase filler — a standard unused EF_IMPU
record) slipped through to an ascii fallback and rendered as garbage
text (the "Text: �" artifact).
- Treat a lone tag (80 / 81) or tag+zero-length-value (80 00 / 81 00)
as empty.
- Only decode the TLV *value* bytes (UTF-8); never feed the TLV header
or trailing FF filler to the text decoder. Drop the fragile
raw.rstrip(...).decode('ascii','replace') fallback.
Tests: +4 (empty 80 00+FF record, all-FF, real SIP URI, lone tag).
Backend-only; stays on 1.22.0.
This commit is contained in:
1 parent
6887e53144
commit
e4ac80fb34
2 files changed
+40
-8
No files matched your search
@@ -3370,19 +3370,26 @@ def _decode_psloci(raw, p1=None):
|
|||||||
|
|
||||||
|
|
||||||
def _decode_nai(raw, p1=None):
|
def _decode_nai(raw, p1=None):
|
||||||
"""ISIM identity files (EF_IMPI/DOMAIN/IMPU): BER-TLV tag 0x80 + ASCII value."""
|
"""ISIM identity files (EF_IMPI/DOMAIN/IMPU): BER-TLV tag 0x80/0x81 + value.
|
||||||
|
|
||||||
|
An erased or unused record is all-0xFF, or a lone identity tag, or a
|
||||||
|
tag with a zero-length value (e.g. ``80 00`` + FF filler) — these are
|
||||||
|
reported as empty rather than decoded as text. Only the TLV *value*
|
||||||
|
bytes are decoded (UTF-8 for a SIP/TEL URI); the TLV header and any
|
||||||
|
trailing erase filler are never fed to the text decoder.
|
||||||
|
"""
|
||||||
if not raw or all(b == 0xff for b in raw):
|
if not raw or all(b == 0xff for b in raw):
|
||||||
return {'empty': True}
|
return {'empty': True}
|
||||||
|
data = bytes(raw).rstrip(b'\xff') # drop erase filler
|
||||||
|
if not data or (data[0] in (0x80, 0x81) and len(data) <= 2):
|
||||||
|
return {'empty': True} # lone tag, or tag + zero-length value = unused
|
||||||
texts = []
|
texts = []
|
||||||
for tag, _length, value in parse_tlv(raw):
|
for tag, _length, value in parse_tlv(data):
|
||||||
if tag == 0x80:
|
if tag in (0x80, 0x81) and value:
|
||||||
txt = value.decode('utf-8', 'replace').rstrip('\xff')
|
texts.append(value.decode('utf-8', 'replace'))
|
||||||
if txt:
|
|
||||||
texts.append(txt)
|
|
||||||
if texts:
|
if texts:
|
||||||
return {'text': texts[0] if len(texts) == 1 else ', '.join(texts)}
|
return {'text': texts[0] if len(texts) == 1 else ', '.join(texts)}
|
||||||
txt = raw.rstrip(b'\xff').decode('ascii', 'replace').strip()
|
return {'raw': raw.hex().upper()}
|
||||||
return {'text': txt} if txt else {'raw': raw.hex().upper()}
|
|
||||||
|
|
||||||
|
|
||||||
def _decode_epsnsc(raw, p1=None):
|
def _decode_epsnsc(raw, p1=None):
|
||||||
|
|||||||
@@ -1017,6 +1017,31 @@ class TestFileDecoders(unittest.TestCase):
|
|||||||
f = _decode_file_data('6f05', b'enru')
|
f = _decode_file_data('6f05', b'enru')
|
||||||
self.assertEqual(f['languages'], ['en', 'ru'])
|
self.assertEqual(f['languages'], ['en', 'ru'])
|
||||||
|
|
||||||
|
def test_ef_impu_empty_record(self):
|
||||||
|
# EF_IMPU record that is an unused identity: tag 0x80, zero-length
|
||||||
|
# value, FF erase filler. Must be reported empty, NOT decoded as text.
|
||||||
|
from simtrace2_pysniff.server.decode import _decode_file_data
|
||||||
|
f = _decode_file_data('6f04', bytes.fromhex('8000' + 'ff' * 73))
|
||||||
|
self.assertIn('empty', f)
|
||||||
|
self.assertNotIn('text', f)
|
||||||
|
|
||||||
|
def test_ef_impu_all_ff(self):
|
||||||
|
from simtrace2_pysniff.server.decode import _decode_file_data
|
||||||
|
f = _decode_file_data('6f04', b'\xff' * 75)
|
||||||
|
self.assertIn('empty', f)
|
||||||
|
|
||||||
|
def test_ef_impu_sip_uri(self):
|
||||||
|
from simtrace2_pysniff.server.decode import _decode_file_data
|
||||||
|
payload = b'\x80' + bytes([len(b'sip:alice@example.com')]) + b'sip:alice@example.com'
|
||||||
|
f = _decode_file_data('6f04', payload)
|
||||||
|
self.assertEqual(f.get('text'), 'sip:alice@example.com')
|
||||||
|
|
||||||
|
def test_ef_impu_lone_tag(self):
|
||||||
|
# A record containing only the identity tag (no length/value) is empty.
|
||||||
|
from simtrace2_pysniff.server.decode import _decode_file_data
|
||||||
|
f = _decode_file_data('6f04', b'\x80')
|
||||||
|
self.assertIn('empty', f)
|
||||||
|
|
||||||
def test_adn(self):
|
def test_adn(self):
|
||||||
from simtrace2_pysniff.server.decode import _decode_file_data
|
from simtrace2_pysniff.server.decode import _decode_file_data
|
||||||
f = _decode_file_data('6f3a', bytes.fromhex(
|
f = _decode_file_data('6f3a', bytes.fromhex(
|
||||||
|
|||||||
Reference in new issue
Block a user