codekingpro/portable-devtools
115k
1#2# This file is part of pyasn1 software.3#4# Copyright (c) 2005-2020, Ilya Etingof <etingof@gmail.com>5# License: https://pyasn1.readthedocs.io/en/latest/license.html6#7import io8import os9import sys10import warnings11 12from pyasn1 import debug13from pyasn1 import error14from pyasn1.codec.ber import eoo15from pyasn1.codec.streaming import asSeekableStream16from pyasn1.codec.streaming import isEndOfStream17from pyasn1.codec.streaming import peekIntoStream18from pyasn1.codec.streaming import readFromStream19from pyasn1.compat import _MISSING20from pyasn1.error import PyAsn1Error21from pyasn1.type import base22from pyasn1.type import char23from pyasn1.type import tag24from pyasn1.type import tagmap25from pyasn1.type import univ26from pyasn1.type import useful27 28__all__ = ['StreamingDecoder', 'Decoder', 'decode']29 30LOG = debug.registerLoggee(__name__, flags=debug.DEBUG_DECODER)31 32noValue = base.noValue33 34SubstrateUnderrunError = error.SubstrateUnderrunError35 36# Maximum number of continuation octets (high-bit set) allowed per OID arc.37# 20 octets allows up to 140-bit integers, supporting UUID-based OIDs38MAX_OID_ARC_CONTINUATION_OCTETS = 2039MAX_NESTING_DEPTH = 10040 41# Maximum number of bytes in a BER length field (8 bytes = up to 2^64-1)42MAX_LENGTH_OCTETS = 843 44 45class AbstractPayloadDecoder(object):46 protoComponent = None47 48 def valueDecoder(self, substrate, asn1Spec,49 tagSet=None, length=None, state=None,50 decodeFun=None, substrateFun=None,51 **options):52 """Decode value with fixed byte length.53 54 The decoder is allowed to consume as many bytes as necessary.55 """56 raise error.PyAsn1Error('SingleItemDecoder not implemented for %s' % (tagSet,)) # TODO: Seems more like an NotImplementedError?57 58 def indefLenValueDecoder(self, substrate, asn1Spec,59 tagSet=None, length=None, state=None,60 decodeFun=None, substrateFun=None,61 **options):62 """Decode value with undefined length.63 64 The decoder is allowed to consume as many bytes as necessary.65 """66 raise error.PyAsn1Error('Indefinite length mode decoder not implemented for %s' % (tagSet,)) # TODO: Seems more like an NotImplementedError?67 68 @staticmethod69 def _passAsn1Object(asn1Object, options):70 if 'asn1Object' not in options:71 options['asn1Object'] = asn1Object72 73 return options74 75 76class AbstractSimplePayloadDecoder(AbstractPayloadDecoder):77 @staticmethod78 def substrateCollector(asn1Object, substrate, length, options):79 for chunk in readFromStream(substrate, length, options):80 yield chunk81 82 def _createComponent(self, asn1Spec, tagSet, value, **options):83 if options.get('native'):84 return value85 elif asn1Spec is None:86 return self.protoComponent.clone(value, tagSet=tagSet)87 elif value is noValue:88 return asn1Spec89 else:90 return asn1Spec.clone(value)91 92 93class RawPayloadDecoder(AbstractSimplePayloadDecoder):94 protoComponent = univ.Any('')95 96 def valueDecoder(self, substrate, asn1Spec,97 tagSet=None, length=None, state=None,98 decodeFun=None, substrateFun=None,99 **options):100 if substrateFun:101 asn1Object = self._createComponent(asn1Spec, tagSet, '', **options)102 103 for chunk in substrateFun(asn1Object, substrate, length, options):104 yield chunk105 106 return107 108 for value in decodeFun(substrate, asn1Spec, tagSet, length, **options):109 yield value110 111 def indefLenValueDecoder(self, substrate, asn1Spec,112 tagSet=None, length=None, state=None,113 decodeFun=None, substrateFun=None,114 **options):115 if substrateFun:116 asn1Object = self._createComponent(asn1Spec, tagSet, '', **options)117 118 for chunk in substrateFun(asn1Object, substrate, length, options):119 yield chunk120 121 return122 123 while True:124 for value in decodeFun(125 substrate, asn1Spec, tagSet, length,126 allowEoo=True, **options):127 128 if value is eoo.endOfOctets:129 return130 131 yield value132 133 134rawPayloadDecoder = RawPayloadDecoder()135 136 137class IntegerPayloadDecoder(AbstractSimplePayloadDecoder):138 protoComponent = univ.Integer(0)139 140 def valueDecoder(self, substrate, asn1Spec,141 tagSet=None, length=None, state=None,142 decodeFun=None, substrateFun=None,143 **options):144 145 if tagSet[0].tagFormat != tag.tagFormatSimple:146 raise error.PyAsn1Error('Simple tag format expected')147 148 for chunk in readFromStream(substrate, length, options):149 if isinstance(chunk, SubstrateUnderrunError):150 yield chunk151 152 if chunk:153 value = int.from_bytes(bytes(chunk), 'big', signed=True)154 155 else:156 value = 0157 158 yield self._createComponent(asn1Spec, tagSet, value, **options)159 160 161class BooleanPayloadDecoder(IntegerPayloadDecoder):162 protoComponent = univ.Boolean(0)163 164 def _createComponent(self, asn1Spec, tagSet, value, **options):165 return IntegerPayloadDecoder._createComponent(166 self, asn1Spec, tagSet, value and 1 or 0, **options)167 168 169class BitStringPayloadDecoder(AbstractSimplePayloadDecoder):170 protoComponent = univ.BitString(())171 supportConstructedForm = True172 173 def valueDecoder(self, substrate, asn1Spec,174 tagSet=None, length=None, state=None,175 decodeFun=None, substrateFun=None,176 **options):177 178 if substrateFun:179 asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options)180 181 for chunk in substrateFun(asn1Object, substrate, length, options):182 yield chunk183 184 return185 186 if not length:187 raise error.PyAsn1Error('Empty BIT STRING substrate')188 189 for chunk in isEndOfStream(substrate):190 if isinstance(chunk, SubstrateUnderrunError):191 yield chunk192 193 if chunk:194 raise error.PyAsn1Error('Empty BIT STRING substrate')195 196 if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check?197 198 for trailingBits in readFromStream(substrate, 1, options):199 if isinstance(trailingBits, SubstrateUnderrunError):200 yield trailingBits201 202 trailingBits = ord(trailingBits)203 if trailingBits > 7:204 raise error.PyAsn1Error(205 'Trailing bits overflow %s' % trailingBits206 )207 208 for chunk in readFromStream(substrate, length - 1, options):209 if isinstance(chunk, SubstrateUnderrunError):210 yield chunk211 212 value = self.protoComponent.fromOctetString(213 chunk, internalFormat=True, padding=trailingBits)214 215 yield self._createComponent(asn1Spec, tagSet, value, **options)216 217 return218 219 if not self.supportConstructedForm:220 raise error.PyAsn1Error('Constructed encoding form prohibited '221 'at %s' % self.__class__.__name__)222 223 if LOG:224 LOG('assembling constructed serialization')225 226 # All inner fragments are of the same type, treat them as octet string227 substrateFun = self.substrateCollector228 229 bitString = self.protoComponent.fromOctetString(b'', internalFormat=True)230 231 current_position = substrate.tell()232 233 while substrate.tell() - current_position < length:234 for component in decodeFun(235 substrate, self.protoComponent, substrateFun=substrateFun,236 **options):237 if isinstance(component, SubstrateUnderrunError):238 yield component239 240 trailingBits = component[0]241 if trailingBits > 7:242 raise error.PyAsn1Error(243 'Trailing bits overflow %s' % trailingBits244 )245 246 bitString = self.protoComponent.fromOctetString(247 component[1:], internalFormat=True,248 prepend=bitString, padding=trailingBits249 )250 251 yield self._createComponent(asn1Spec, tagSet, bitString, **options)252 253 def indefLenValueDecoder(self, substrate, asn1Spec,254 tagSet=None, length=None, state=None,255 decodeFun=None, substrateFun=None,256 **options):257 258 if substrateFun:259 asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options)260 261 for chunk in substrateFun(asn1Object, substrate, length, options):262 yield chunk263 264 return265 266 # All inner fragments are of the same type, treat them as octet string267 substrateFun = self.substrateCollector268 269 bitString = self.protoComponent.fromOctetString(b'', internalFormat=True)270 271 while True: # loop over fragments272 273 for component in decodeFun(274 substrate, self.protoComponent, substrateFun=substrateFun,275 allowEoo=True, **options):276 277 if component is eoo.endOfOctets:278 break279 280 if isinstance(component, SubstrateUnderrunError):281 yield component282 283 if component is eoo.endOfOctets:284 break285 286 trailingBits = component[0]287 if trailingBits > 7:288 raise error.PyAsn1Error(289 'Trailing bits overflow %s' % trailingBits290 )291 292 bitString = self.protoComponent.fromOctetString(293 component[1:], internalFormat=True,294 prepend=bitString, padding=trailingBits295 )296 297 yield self._createComponent(asn1Spec, tagSet, bitString, **options)298 299 300class OctetStringPayloadDecoder(AbstractSimplePayloadDecoder):301 protoComponent = univ.OctetString('')302 supportConstructedForm = True303 304 def valueDecoder(self, substrate, asn1Spec,305 tagSet=None, length=None, state=None,306 decodeFun=None, substrateFun=None,307 **options):308 if substrateFun:309 asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options)310 311 for chunk in substrateFun(asn1Object, substrate, length, options):312 yield chunk313 314 return315 316 if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check?317 for chunk in readFromStream(substrate, length, options):318 if isinstance(chunk, SubstrateUnderrunError):319 yield chunk320 321 yield self._createComponent(asn1Spec, tagSet, chunk, **options)322 323 return324 325 if not self.supportConstructedForm:326 raise error.PyAsn1Error('Constructed encoding form prohibited at %s' % self.__class__.__name__)327 328 if LOG:329 LOG('assembling constructed serialization')330 331 # All inner fragments are of the same type, treat them as octet string332 substrateFun = self.substrateCollector333 334 header = b''335 336 original_position = substrate.tell()337 # head = popSubstream(substrate, length)338 while substrate.tell() - original_position < length:339 for component in decodeFun(340 substrate, self.protoComponent, substrateFun=substrateFun,341 **options):342 if isinstance(component, SubstrateUnderrunError):343 yield component344 345 header += component346 347 yield self._createComponent(asn1Spec, tagSet, header, **options)348 349 def indefLenValueDecoder(self, substrate, asn1Spec,350 tagSet=None, length=None, state=None,351 decodeFun=None, substrateFun=None,352 **options):353 if substrateFun and substrateFun is not self.substrateCollector:354 asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options)355 356 for chunk in substrateFun(asn1Object, substrate, length, options):357 yield chunk358 359 return360 361 # All inner fragments are of the same type, treat them as octet string362 substrateFun = self.substrateCollector363 364 header = b''365 366 while True: # loop over fragments367 368 for component in decodeFun(369 substrate, self.protoComponent, substrateFun=substrateFun,370 allowEoo=True, **options):371 372 if isinstance(component, SubstrateUnderrunError):373 yield component374 375 if component is eoo.endOfOctets:376 break377 378 if component is eoo.endOfOctets:379 break380 381 header += component382 383 yield self._createComponent(asn1Spec, tagSet, header, **options)384 385 386class NullPayloadDecoder(AbstractSimplePayloadDecoder):387 protoComponent = univ.Null('')388 389 def valueDecoder(self, substrate, asn1Spec,390 tagSet=None, length=None, state=None,391 decodeFun=None, substrateFun=None,392 **options):393 394 if tagSet[0].tagFormat != tag.tagFormatSimple:395 raise error.PyAsn1Error('Simple tag format expected')396 397 for chunk in readFromStream(substrate, length, options):398 if isinstance(chunk, SubstrateUnderrunError):399 yield chunk400 401 component = self._createComponent(asn1Spec, tagSet, '', **options)402 403 if chunk:404 raise error.PyAsn1Error('Unexpected %d-octet substrate for Null' % length)405 406 yield component407 408 409class ObjectIdentifierPayloadDecoder(AbstractSimplePayloadDecoder):410 protoComponent = univ.ObjectIdentifier(())411 412 def valueDecoder(self, substrate, asn1Spec,413 tagSet=None, length=None, state=None,414 decodeFun=None, substrateFun=None,415 **options):416 if tagSet[0].tagFormat != tag.tagFormatSimple:417 raise error.PyAsn1Error('Simple tag format expected')418 419 for chunk in readFromStream(substrate, length, options):420 if isinstance(chunk, SubstrateUnderrunError):421 yield chunk422 423 if not chunk:424 raise error.PyAsn1Error('Empty substrate')425 426 oid = ()427 index = 0428 substrateLen = len(chunk)429 while index < substrateLen:430 subId = chunk[index]431 index += 1432 if subId < 128:433 oid += (subId,)434 elif subId > 128:435 # Construct subid from a number of octets436 nextSubId = subId437 subId = 0438 continuationOctetCount = 0439 while nextSubId >= 128:440 continuationOctetCount += 1441 if continuationOctetCount > MAX_OID_ARC_CONTINUATION_OCTETS:442 raise error.PyAsn1Error(443 'OID arc exceeds maximum continuation octets limit (%d) '444 'at position %d' % (MAX_OID_ARC_CONTINUATION_OCTETS, index)445 )446 subId = (subId << 7) + (nextSubId & 0x7F)447 if index >= substrateLen:448 raise error.SubstrateUnderrunError(449 'Short substrate for sub-OID past %s' % (oid,)450 )451 nextSubId = chunk[index]452 index += 1453 oid += ((subId << 7) + nextSubId,)454 elif subId == 128:455 # ASN.1 spec forbids leading zeros (0x80) in OID456 # encoding, tolerating it opens a vulnerability. See457 # https://www.esat.kuleuven.be/cosic/publications/article-1432.pdf458 # page 7459 raise error.PyAsn1Error('Invalid octet 0x80 in OID encoding')460 461 # Decode two leading arcs462 if 0 <= oid[0] <= 39:463 oid = (0,) + oid464 elif 40 <= oid[0] <= 79:465 oid = (1, oid[0] - 40) + oid[1:]466 elif oid[0] >= 80:467 oid = (2, oid[0] - 80) + oid[1:]468 else:469 raise error.PyAsn1Error('Malformed first OID octet: %s' % chunk[0])470 471 yield self._createComponent(asn1Spec, tagSet, oid, **options)472 473 474class RelativeOIDPayloadDecoder(AbstractSimplePayloadDecoder):475 protoComponent = univ.RelativeOID(())476 477 def valueDecoder(self, substrate, asn1Spec,478 tagSet=None, length=None, state=None,479 decodeFun=None, substrateFun=None,480 **options):481 if tagSet[0].tagFormat != tag.tagFormatSimple:482 raise error.PyAsn1Error('Simple tag format expected')483 484 for chunk in readFromStream(substrate, length, options):485 if isinstance(chunk, SubstrateUnderrunError):486 yield chunk487 488 if not chunk:489 raise error.PyAsn1Error('Empty substrate')490 491 reloid = ()492 index = 0493 substrateLen = len(chunk)494 while index < substrateLen:495 subId = chunk[index]496 index += 1497 if subId < 128:498 reloid += (subId,)499 elif subId > 128:500 # Construct subid from a number of octets501 nextSubId = subId502 subId = 0503 continuationOctetCount = 0504 while nextSubId >= 128:505 continuationOctetCount += 1506 if continuationOctetCount > MAX_OID_ARC_CONTINUATION_OCTETS:507 raise error.PyAsn1Error(508 'RELATIVE-OID arc exceeds maximum continuation octets limit (%d) '509 'at position %d' % (MAX_OID_ARC_CONTINUATION_OCTETS, index)510 )511 subId = (subId << 7) + (nextSubId & 0x7F)512 if index >= substrateLen:513 raise error.SubstrateUnderrunError(514 'Short substrate for sub-OID past %s' % (reloid,)515 )516 nextSubId = chunk[index]517 index += 1518 reloid += ((subId << 7) + nextSubId,)519 elif subId == 128:520 # ASN.1 spec forbids leading zeros (0x80) in OID521 # encoding, tolerating it opens a vulnerability. See522 # https://www.esat.kuleuven.be/cosic/publications/article-1432.pdf523 # page 7524 raise error.PyAsn1Error('Invalid octet 0x80 in RELATIVE-OID encoding')525 526 yield self._createComponent(asn1Spec, tagSet, reloid, **options)527 528 529class RealPayloadDecoder(AbstractSimplePayloadDecoder):530 protoComponent = univ.Real()531 532 def valueDecoder(self, substrate, asn1Spec,533 tagSet=None, length=None, state=None,534 decodeFun=None, substrateFun=None,535 **options):536 if tagSet[0].tagFormat != tag.tagFormatSimple:537 raise error.PyAsn1Error('Simple tag format expected')538 539 for chunk in readFromStream(substrate, length, options):540 if isinstance(chunk, SubstrateUnderrunError):541 yield chunk542 543 if not chunk:544 yield self._createComponent(asn1Spec, tagSet, 0.0, **options)545 return546 547 fo = chunk[0]548 chunk = chunk[1:]549 if fo & 0x80: # binary encoding550 if not chunk:551 raise error.PyAsn1Error("Incomplete floating-point value")552 553 if LOG:554 LOG('decoding binary encoded REAL')555 556 n = (fo & 0x03) + 1557 558 if n == 4:559 n = chunk[0]560 chunk = chunk[1:]561 562 eo, chunk = chunk[:n], chunk[n:]563 564 if not eo or not chunk:565 raise error.PyAsn1Error('Real exponent screwed')566 567 e = eo[0] & 0x80 and -1 or 0568 569 while eo: # exponent570 e <<= 8571 e |= eo[0]572 eo = eo[1:]573 574 b = fo >> 4 & 0x03 # base bits575 576 if b > 2:577 raise error.PyAsn1Error('Illegal Real base')578 579 if b == 1: # encbase = 8580 e *= 3581 582 elif b == 2: # encbase = 16583 e *= 4584 p = 0585 586 while chunk: # value587 p <<= 8588 p |= chunk[0]589 chunk = chunk[1:]590 591 if fo & 0x40: # sign bit592 p = -p593 594 sf = fo >> 2 & 0x03 # scale bits595 p *= 2 ** sf596 value = (p, 2, e)597 598 elif fo & 0x40: # infinite value599 if LOG:600 LOG('decoding infinite REAL')601 602 value = fo & 0x01 and '-inf' or 'inf'603 604 elif fo & 0xc0 == 0: # character encoding605 if not chunk:606 raise error.PyAsn1Error("Incomplete floating-point value")607 608 if LOG:609 LOG('decoding character encoded REAL')610 611 try:612 if fo & 0x3 == 0x1: # NR1613 value = (int(chunk), 10, 0)614 615 elif fo & 0x3 == 0x2: # NR2616 value = float(chunk)617 618 elif fo & 0x3 == 0x3: # NR3619 value = float(chunk)620 621 else:622 raise error.SubstrateUnderrunError(623 'Unknown NR (tag %s)' % fo624 )625 626 except ValueError:627 raise error.SubstrateUnderrunError(628 'Bad character Real syntax'629 )630 631 else:632 raise error.SubstrateUnderrunError(633 'Unknown encoding (tag %s)' % fo634 )635 636 yield self._createComponent(asn1Spec, tagSet, value, **options)637 638 639class AbstractConstructedPayloadDecoder(AbstractPayloadDecoder):640 protoComponent = None641 642 643class ConstructedPayloadDecoderBase(AbstractConstructedPayloadDecoder):644 protoRecordComponent = None645 protoSequenceComponent = None646 647 def _getComponentTagMap(self, asn1Object, idx):648 raise NotImplementedError649 650 def _getComponentPositionByType(self, asn1Object, tagSet, idx):651 raise NotImplementedError652 653 def _decodeComponentsSchemaless(654 self, substrate, tagSet=None, decodeFun=None,655 length=None, **options):656 657 asn1Object = None658 659 components = []660 componentTypes = set()661 662 original_position = substrate.tell()663 664 while length == -1 or substrate.tell() < original_position + length:665 for component in decodeFun(substrate, **options):666 if isinstance(component, SubstrateUnderrunError):667 yield component668 669 if length == -1 and component is eoo.endOfOctets:670 break671 672 components.append(component)673 componentTypes.add(component.tagSet)674 675 # Now we have to guess is it SEQUENCE/SET or SEQUENCE OF/SET OF676 # The heuristics is:677 # * 1+ components of different types -> likely SEQUENCE/SET678 # * otherwise -> likely SEQUENCE OF/SET OF679 if len(componentTypes) > 1:680 protoComponent = self.protoRecordComponent681 682 else:683 protoComponent = self.protoSequenceComponent684 685 asn1Object = protoComponent.clone(686 # construct tagSet from base tag from prototype ASN.1 object687 # and additional tags recovered from the substrate688 tagSet=tag.TagSet(protoComponent.tagSet.baseTag, *tagSet.superTags)689 )690 691 if LOG:692 LOG('guessed %r container type (pass `asn1Spec` to guide the '693 'decoder)' % asn1Object)694 695 for idx, component in enumerate(components):696 asn1Object.setComponentByPosition(697 idx, component,698 verifyConstraints=False,699 matchTags=False, matchConstraints=False700 )701 702 yield asn1Object703 704 def valueDecoder(self, substrate, asn1Spec,705 tagSet=None, length=None, state=None,706 decodeFun=None, substrateFun=None,707 **options):708 if tagSet[0].tagFormat != tag.tagFormatConstructed:709 raise error.PyAsn1Error('Constructed tag format expected')710 711 original_position = substrate.tell()712 713 if substrateFun:714 if asn1Spec is not None:715 asn1Object = asn1Spec.clone()716 717 elif self.protoComponent is not None:718 asn1Object = self.protoComponent.clone(tagSet=tagSet)719 720 else:721 asn1Object = self.protoRecordComponent, self.protoSequenceComponent722 723 for chunk in substrateFun(asn1Object, substrate, length, options):724 yield chunk725 726 return727 728 if asn1Spec is None:729 for asn1Object in self._decodeComponentsSchemaless(730 substrate, tagSet=tagSet, decodeFun=decodeFun,731 length=length, **options):732 if isinstance(asn1Object, SubstrateUnderrunError):733 yield asn1Object734 735 if substrate.tell() < original_position + length:736 if LOG:737 for trailing in readFromStream(substrate, context=options):738 if isinstance(trailing, SubstrateUnderrunError):739 yield trailing740 741 LOG('Unused trailing %d octets encountered: %s' % (742 len(trailing), debug.hexdump(trailing)))743 744 yield asn1Object745 746 return747 748 asn1Object = asn1Spec.clone()749 asn1Object.clear()750 751 options = self._passAsn1Object(asn1Object, options)752 753 if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId):754 755 namedTypes = asn1Spec.componentType756 757 isSetType = asn1Spec.typeId == univ.Set.typeId758 isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault759 760 if LOG:761 LOG('decoding %sdeterministic %s type %r chosen by type ID' % (762 not isDeterministic and 'non-' or '', isSetType and 'SET' or '',763 asn1Spec))764 765 seenIndices = set()766 idx = 0767 while substrate.tell() - original_position < length:768 if not namedTypes:769 componentType = None770 771 elif isSetType:772 componentType = namedTypes.tagMapUnique773 774 else:775 try:776 if isDeterministic:777 componentType = namedTypes[idx].asn1Object778 779 elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted:780 componentType = namedTypes.getTagMapNearPosition(idx)781 782 else:783 componentType = namedTypes[idx].asn1Object784 785 except IndexError:786 raise error.PyAsn1Error(787 'Excessive components decoded at %r' % (asn1Spec,)788 )789 790 for component in decodeFun(substrate, componentType, **options):791 if isinstance(component, SubstrateUnderrunError):792 yield component793 794 if not isDeterministic and namedTypes:795 if isSetType:796 idx = namedTypes.getPositionByType(component.effectiveTagSet)797 798 elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted:799 idx = namedTypes.getPositionNearType(component.effectiveTagSet, idx)800 801 asn1Object.setComponentByPosition(802 idx, component,803 verifyConstraints=False,804 matchTags=False, matchConstraints=False805 )806 807 seenIndices.add(idx)808 idx += 1809 810 if LOG:811 LOG('seen component indices %s' % seenIndices)812 813 if namedTypes:814 if not namedTypes.requiredComponents.issubset(seenIndices):815 raise error.PyAsn1Error(816 'ASN.1 object %s has uninitialized '817 'components' % asn1Object.__class__.__name__)818 819 if namedTypes.hasOpenTypes:820 821 openTypes = options.get('openTypes', {})822 823 if LOG:824 LOG('user-specified open types map:')825 826 for k, v in openTypes.items():827 LOG('%s -> %r' % (k, v))828 829 if openTypes or options.get('decodeOpenTypes', False):830 831 for idx, namedType in enumerate(namedTypes.namedTypes):832 if not namedType.openType:833 continue834 835 if namedType.isOptional and not asn1Object.getComponentByPosition(idx).isValue:836 continue837 838 governingValue = asn1Object.getComponentByName(839 namedType.openType.name840 )841 842 try:843 openType = openTypes[governingValue]844 845 except KeyError:846 847 if LOG:848 LOG('default open types map of component '849 '"%s.%s" governed by component "%s.%s"'850 ':' % (asn1Object.__class__.__name__,851 namedType.name,852 asn1Object.__class__.__name__,853 namedType.openType.name))854 855 for k, v in namedType.openType.items():856 LOG('%s -> %r' % (k, v))857 858 try:859 openType = namedType.openType[governingValue]860 861 except KeyError:862 if LOG:863 LOG('failed to resolve open type by governing '864 'value %r' % (governingValue,))865 continue866 867 if LOG:868 LOG('resolved open type %r by governing '869 'value %r' % (openType, governingValue))870 871 containerValue = asn1Object.getComponentByPosition(idx)872 873 if containerValue.typeId in (874 univ.SetOf.typeId, univ.SequenceOf.typeId):875 876 for pos, containerElement in enumerate(877 containerValue):878 879 stream = asSeekableStream(containerValue[pos].asOctets())880 881 for component in decodeFun(stream, asn1Spec=openType, **options):882 if isinstance(component, SubstrateUnderrunError):883 yield component884 885 containerValue[pos] = component886 887 else:888 stream = asSeekableStream(asn1Object.getComponentByPosition(idx).asOctets())889 890 for component in decodeFun(stream, asn1Spec=openType, **options):891 if isinstance(component, SubstrateUnderrunError):892 yield component893 894 asn1Object.setComponentByPosition(idx, component)895 896 else:897 inconsistency = asn1Object.isInconsistent898 if inconsistency:899 raise error.PyAsn1Error(900 f"ASN.1 object {asn1Object.__class__.__name__} is inconsistent")901 902 else:903 componentType = asn1Spec.componentType904 905 if LOG:906 LOG('decoding type %r chosen by given `asn1Spec`' % componentType)907 908 idx = 0909 910 while substrate.tell() - original_position < length:911 for component in decodeFun(substrate, componentType, **options):912 if isinstance(component, SubstrateUnderrunError):913 yield component914 915 asn1Object.setComponentByPosition(916 idx, component,917 verifyConstraints=False,918 matchTags=False, matchConstraints=False919 )920 921 idx += 1922 923 yield asn1Object924 925 def indefLenValueDecoder(self, substrate, asn1Spec,926 tagSet=None, length=None, state=None,927 decodeFun=None, substrateFun=None,928 **options):929 if tagSet[0].tagFormat != tag.tagFormatConstructed:930 raise error.PyAsn1Error('Constructed tag format expected')931 932 if substrateFun is not None:933 if asn1Spec is not None:934 asn1Object = asn1Spec.clone()935 936 elif self.protoComponent is not None:937 asn1Object = self.protoComponent.clone(tagSet=tagSet)938 939 else:940 asn1Object = self.protoRecordComponent, self.protoSequenceComponent941 942 for chunk in substrateFun(asn1Object, substrate, length, options):943 yield chunk944 945 return946 947 if asn1Spec is None:948 for asn1Object in self._decodeComponentsSchemaless(949 substrate, tagSet=tagSet, decodeFun=decodeFun,950 length=length, **dict(options, allowEoo=True)):951 if isinstance(asn1Object, SubstrateUnderrunError):952 yield asn1Object953 954 yield asn1Object955 956 return957 958 asn1Object = asn1Spec.clone()959 asn1Object.clear()960 961 options = self._passAsn1Object(asn1Object, options)962 963 if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId):964 965 namedTypes = asn1Object.componentType966 967 isSetType = asn1Object.typeId == univ.Set.typeId968 isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault969 970 if LOG:971 LOG('decoding %sdeterministic %s type %r chosen by type ID' % (972 not isDeterministic and 'non-' or '', isSetType and 'SET' or '',973 asn1Spec))974 975 seenIndices = set()976 977 idx = 0978 979 while True: # loop over components980 if len(namedTypes) <= idx:981 asn1Spec = None982 983 elif isSetType:984 asn1Spec = namedTypes.tagMapUnique985 986 else:987 try:988 if isDeterministic:989 asn1Spec = namedTypes[idx].asn1Object990 991 elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted:992 asn1Spec = namedTypes.getTagMapNearPosition(idx)993 994 else:995 asn1Spec = namedTypes[idx].asn1Object996 997 except IndexError:998 raise error.PyAsn1Error(999 'Excessive components decoded at %r' % (asn1Object,)1000 )1001 1002 for component in decodeFun(substrate, asn1Spec, allowEoo=True, **options):1003 1004 if isinstance(component, SubstrateUnderrunError):1005 yield component1006 1007 if component is eoo.endOfOctets:1008 break1009 1010 if component is eoo.endOfOctets:1011 break1012 1013 if not isDeterministic and namedTypes:1014 if isSetType:1015 idx = namedTypes.getPositionByType(component.effectiveTagSet)1016 1017 elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted:1018 idx = namedTypes.getPositionNearType(component.effectiveTagSet, idx)1019 1020 asn1Object.setComponentByPosition(1021 idx, component,1022 verifyConstraints=False,1023 matchTags=False, matchConstraints=False1024 )1025 1026 seenIndices.add(idx)1027 idx += 11028 1029 if LOG:1030 LOG('seen component indices %s' % seenIndices)1031 1032 if namedTypes:1033 if not namedTypes.requiredComponents.issubset(seenIndices):1034 raise error.PyAsn1Error(1035 'ASN.1 object %s has uninitialized '1036 'components' % asn1Object.__class__.__name__)1037 1038 if namedTypes.hasOpenTypes:1039 1040 openTypes = options.get('openTypes', {})1041 1042 if LOG:1043 LOG('user-specified open types map:')1044 1045 for k, v in openTypes.items():1046 LOG('%s -> %r' % (k, v))1047 1048 if openTypes or options.get('decodeOpenTypes', False):1049 1050 for idx, namedType in enumerate(namedTypes.namedTypes):1051 if not namedType.openType:1052 continue1053 1054 if namedType.isOptional and not asn1Object.getComponentByPosition(idx).isValue:1055 continue1056 1057 governingValue = asn1Object.getComponentByName(1058 namedType.openType.name1059 )1060 1061 try:1062 openType = openTypes[governingValue]1063 1064 except KeyError:1065 1066 if LOG:1067 LOG('default open types map of component '1068 '"%s.%s" governed by component "%s.%s"'1069 ':' % (asn1Object.__class__.__name__,1070 namedType.name,1071 asn1Object.__class__.__name__,1072 namedType.openType.name))1073 1074 for k, v in namedType.openType.items():1075 LOG('%s -> %r' % (k, v))1076 1077 try:1078 openType = namedType.openType[governingValue]1079 1080 except KeyError:1081 if LOG:1082 LOG('failed to resolve open type by governing '1083 'value %r' % (governingValue,))1084 continue1085 1086 if LOG:1087 LOG('resolved open type %r by governing '1088 'value %r' % (openType, governingValue))1089 1090 containerValue = asn1Object.getComponentByPosition(idx)1091 1092 if containerValue.typeId in (1093 univ.SetOf.typeId, univ.SequenceOf.typeId):1094 1095 for pos, containerElement in enumerate(1096 containerValue):1097 1098 stream = asSeekableStream(containerValue[pos].asOctets())1099 1100 for component in decodeFun(stream, asn1Spec=openType,1101 **dict(options, allowEoo=True)):1102 if isinstance(component, SubstrateUnderrunError):1103 yield component1104 1105 if component is eoo.endOfOctets:1106 break1107 1108 containerValue[pos] = component1109 1110 else:1111 stream = asSeekableStream(asn1Object.getComponentByPosition(idx).asOctets())1112 for component in decodeFun(stream, asn1Spec=openType,1113 **dict(options, allowEoo=True)):1114 if isinstance(component, SubstrateUnderrunError):1115 yield component1116 1117 if component is eoo.endOfOctets:1118 break1119 1120 asn1Object.setComponentByPosition(idx, component)1121 1122 else:1123 inconsistency = asn1Object.isInconsistent1124 if inconsistency:1125 raise error.PyAsn1Error(1126 f"ASN.1 object {asn1Object.__class__.__name__} is inconsistent")1127 1128 else:1129 componentType = asn1Spec.componentType1130 1131 if LOG:1132 LOG('decoding type %r chosen by given `asn1Spec`' % componentType)1133 1134 idx = 01135 1136 while True:1137 1138 for component in decodeFun(1139 substrate, componentType, allowEoo=True, **options):1140 1141 if isinstance(component, SubstrateUnderrunError):1142 yield component1143 1144 if component is eoo.endOfOctets:1145 break1146 1147 if component is eoo.endOfOctets:1148 break1149 1150 asn1Object.setComponentByPosition(1151 idx, component,1152 verifyConstraints=False,1153 matchTags=False, matchConstraints=False1154 )1155 1156 idx += 11157 1158 yield asn1Object1159 1160 1161class SequenceOrSequenceOfPayloadDecoder(ConstructedPayloadDecoderBase):1162 protoRecordComponent = univ.Sequence()1163 protoSequenceComponent = univ.SequenceOf()1164 1165 1166class SequencePayloadDecoder(SequenceOrSequenceOfPayloadDecoder):1167 protoComponent = univ.Sequence()1168 1169 1170class SequenceOfPayloadDecoder(SequenceOrSequenceOfPayloadDecoder):1171 protoComponent = univ.SequenceOf()1172 1173 1174class SetOrSetOfPayloadDecoder(ConstructedPayloadDecoderBase):1175 protoRecordComponent = univ.Set()1176 protoSequenceComponent = univ.SetOf()1177 1178 1179class SetPayloadDecoder(SetOrSetOfPayloadDecoder):1180 protoComponent = univ.Set()1181 1182 1183class SetOfPayloadDecoder(SetOrSetOfPayloadDecoder):1184 protoComponent = univ.SetOf()1185 1186 1187class ChoicePayloadDecoder(ConstructedPayloadDecoderBase):1188 protoComponent = univ.Choice()1189 1190 def valueDecoder(self, substrate, asn1Spec,1191 tagSet=None, length=None, state=None,1192 decodeFun=None, substrateFun=None,1193 **options):1194 if asn1Spec is None:1195 asn1Object = self.protoComponent.clone(tagSet=tagSet)1196 1197 else:1198 asn1Object = asn1Spec.clone()1199 1200 if substrateFun: