Decoded object results in empty infinitely nested SequenceOf
johndoe31415 opened this issue · 1 comments
I'm using 0.4.8 on Linux x86_64 on Python 3.9.5. My x509sak project relies heavily on pyasn1 and I've just today realized that a major component stopped working (not sure exactly when, I've not worked on the project for quite a while). I believe the issue lies within pyasn1 and results in a particular encoding resulting in an empty, infinitely nested ASN.1 SequenceOf object. This object, when re-encoded using pyasn1, leads to stack overflow. Consider this PoC:
#!/usr/bin/python3
#
#
import pyasn1.codec.der.encoder
import pyasn1.codec.der.decoder
der_data = bytes.fromhex("308202d5308202d1308202cd308202c9308202c5308202c1308202bd308202b9308202b5308202b1308202ad308202a9308202a5308202a13082029d3082029930820295308202913082028d3082028930820285308202813082027d3082027930820275308202713082026d3082026930820265308202613082025d3082025930820255308202513082024d3082024930820245308202413082023d3082023930820235308202313082022d3082022930820225308202213082021d3082021930820215308202113082020d308202093082020530820201308201fd308201f9308201f5308201f1308201ed308201e9308201e5308201e1308201dd308201d9308201d5308201d1308201cd308201c9308201c5308201c1308201bd308201b9308201b5308201b1308201ad308201a9308201a5308201a13082019d3082019930820195308201913082018d3082018930820185308201813082017d3082017930820175308201713082016d3082016930820165308201613082015d3082015930820155308201513082014d3082014930820145308201413082013d3082013930820135308201313082012d3082012930820125308201213082011d3082011930820115308201113082010d3082010930820105308201013081fe3081fb3081f83081f53081f23081ef3081ec3081e93081e63081e33081e03081dd3081da3081d73081d43081d13081ce3081cb3081c83081c53081c23081bf3081bc3081b93081b63081b33081b03081ad3081aa3081a73081a43081a130819e30819b30819830819530819230818f30818c308189308186308183308180307e307c307a30783076307430723070306e306c306a30683066306430623060305e305c305a30583056305430523050304e304c304a30483046304430423040303e303c303a30383036303430323030302e302c302a30283026302430223020301e301c301a30183016301430123010300e300c300a30083006300430023000041405824602e9306e6a83857c4307a7692f24b4b317")
(asn1, tail) = pyasn1.codec.der.decoder.decode(der_data)
print("Result:", asn1)
print("Result type:", type(asn1))
print("Result ID:", id(asn1))
print("Result contains ID:", id(asn1[0]))
print("Result contains ID level 2:", id(asn1[0][0]))
print("Result contains ID level 3:", id(asn1[0][0][0]))
reencoded = pyasn1.codec.der.encoder.encode(asn1)
When running this, this is what happens:
Result: SequenceOf:
Result type: <class 'pyasn1.type.univ.SequenceOf'>
Result ID: 140578022085968
Result contains ID: 140578022085872
Result contains ID level 2: 140578022085776
Result contains ID level 3: 140578022085680
Traceback (most recent call last):
File "/home/joe/tmp/./bug_example", line 15, in <module>
reencoded = pyasn1.codec.der.encoder.encode(asn1)
File "/usr/lib/python3/dist-packages/pyasn1/codec/ber/encoder.py", line 832, in __call__
substrate = concreteEncoder.encode(value, asn1Spec, self, **options)
File "/usr/lib/python3/dist-packages/pyasn1/codec/ber/encoder.py", line 101, in encode
substrate, isConstructed, isOctets = self.encodeValue(
File "/usr/lib/python3/dist-packages/pyasn1/codec/cer/encoder.py", line 137, in encodeValue
chunks = self._encodeComponents(
File "/usr/lib/python3/dist-packages/pyasn1/codec/ber/encoder.py", line 660, in _encodeComponents
chunk = encodeFun(component, asn1Spec, **options)
File "/usr/lib/python3/dist-packages/pyasn1/codec/ber/encoder.py", line 832, in __call__
substrate = concreteEncoder.encode(value, asn1Spec, self, **options)
File "/usr/lib/python3/dist-packages/pyasn1/codec/ber/encoder.py", line 101, in encode
substrate, isConstructed, isOctets = self.encodeValue(
File "/usr/lib/python3/dist-packages/pyasn1/codec/cer/encoder.py", line 137, in encodeValue
[...]
File "/usr/lib/python3/dist-packages/pyasn1/codec/ber/encoder.py", line 832, in __call__
substrate = concreteEncoder.encode(value, asn1Spec, self, **options)
File "/usr/lib/python3/dist-packages/pyasn1/codec/ber/encoder.py", line 101, in encode
substrate, isConstructed, isOctets = self.encodeValue(
File "/usr/lib/python3/dist-packages/pyasn1/codec/cer/encoder.py", line 137, in encodeValue
chunks = self._encodeComponents(
File "/usr/lib/python3/dist-packages/pyasn1/codec/ber/encoder.py", line 660, in _encodeComponents
chunk = encodeFun(component, asn1Spec, **options)
File "/usr/lib/python3/dist-packages/pyasn1/codec/ber/encoder.py", line 832, in __call__
substrate = concreteEncoder.encode(value, asn1Spec, self, **options)
File "/usr/lib/python3/dist-packages/pyasn1/codec/ber/encoder.py", line 101, in encode
substrate, isConstructed, isOctets = self.encodeValue(
File "/usr/lib/python3/dist-packages/pyasn1/codec/cer/encoder.py", line 137, in encodeValue
chunks = self._encodeComponents(
File "/usr/lib/python3/dist-packages/pyasn1/codec/ber/encoder.py", line 660, in _encodeComponents
chunk = encodeFun(component, asn1Spec, **options)
File "/usr/lib/python3/dist-packages/pyasn1/codec/ber/encoder.py", line 832, in __call__
substrate = concreteEncoder.encode(value, asn1Spec, self, **options)
File "/usr/lib/python3/dist-packages/pyasn1/codec/ber/encoder.py", line 101, in encode
substrate, isConstructed, isOctets = self.encodeValue(
File "/usr/lib/python3/dist-packages/pyasn1/codec/cer/encoder.py", line 134, in encodeValue
if options.get('ifNotEmpty', False) and not len(value):
RecursionError: maximum recursion depth exceeded while calling a Python object
Please advise on how I can debug this issue further to identify what is going on. Thank you so much for your help.
Disregard this please. This is deliberately malformed. My issue stems from a separate cause.