laforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/37137?usp=email )
Change subject: pySim.tlv: Correctly parse COMPREHENSION-TLV without comprehension bit ......................................................................
pySim.tlv: Correctly parse COMPREHENSION-TLV without comprehension bit
The uppermost bit of COMPREHENSION-TLV tags indicates whether the recipient is required to "comprehend" that IE or not. So every IE actually has two tag values: one with and one without that bit set.
As all our existing TLV definitions of COMPR_TLV_IE have that bit set, let's assume this is the default, but use the same definition also for the situation where that bit is not set.
Change-Id: I58d04ec13be0c12d9fb8cb3d5a0480d0defb6c95 --- M pySim/tlv.py 1 file changed, 33 insertions(+), 1 deletion(-)
Approvals: Jenkins Builder: Verified laforge: Looks good to me, approved osmith: Looks good to me, but someone else must approve
diff --git a/pySim/tlv.py b/pySim/tlv.py index 8bf43c6..5835d33 100644 --- a/pySim/tlv.py +++ b/pySim/tlv.py @@ -224,12 +224,16 @@ val = self.to_bytes(context=context) return self._encode_tag() + self._encode_len(val) + val
+ def is_tag_compatible(self, rawtag) -> bool: + """Is the given rawtag compatible with this class?""" + return rawtag == self._compute_tag() + def from_tlv(self, do: bytes, context: dict = {}): if len(do) == 0: return {}, b'' (rawtag, remainder) = self.__class__._parse_tag_raw(do) if rawtag: - if rawtag != self._compute_tag(): + if not self.is_tag_compatible(rawtag): raise ValueError("%s: Encountered tag %s doesn't match our supported tag %s" % (self, rawtag, self.tag)) (length, remainder) = self.__class__._parse_len(remainder) @@ -283,6 +287,15 @@ def _parse_len(cls, do: bytes) -> Tuple[int, bytes]: return bertlv_parse_len(do)
+ def is_tag_compatible(self, rawtag: int) -> bool: + """Override is_tag_compatible as we need to mask out the + comprehension bit when doing compares.""" + ctag = self._compute_tag() + if ctag > 0xff: + return ctag & 0x7fff == rawtag & 0x7fff + else: + return ctag & 0x7f == rawtag & 0x7f + def _encode_tag(self) -> bytes: return comprehensiontlv_encode_tag(self._compute_tag())
@@ -367,6 +380,8 @@ tag, _r = first._parse_tag_raw(remainder) if tag is None: break + if issubclass(first, COMPR_TLV_IE): + tag = tag | 0x80 # HACK: always assume comprehension if tag in self.members_by_tag: cls = self.members_by_tag[tag] # create an instance and parse accordingly