Skip to content
Snippets Groups Projects
Commit 9688c23390ec authored by Ilya Etingof's avatar Ilya Etingof
Browse files

Add more debug logging to *ER codecs

More debug logging added to BER family of codecs to
ease encoding problems troubleshooting.

Also:

* code layout made a bit more sparse
* potential bug in open type decoding in indefinite mode
  fixed
parent 95b832997e5c
No related branches found
No related tags found
No related merge requests found
......@@ -6,6 +6,8 @@
for more functionality when in use. Specifically, the global
LOG object can easily be used from any function/method, not just
from codec main loop as it used to be.
- More debug logging added to BER family of codecs to ease encoding
problems troubleshooting.
Revision 0.4.4, released 26-07-2018
-----------------------------------
......
This diff is collapsed.
......@@ -33,5 +33,6 @@
encodedTag = tagClass | tagFormat
if isConstructed:
encodedTag |= tag.tagFormatConstructed
if tagId < 31:
return encodedTag | tagId,
......@@ -36,4 +37,5 @@
if tagId < 31:
return encodedTag | tagId,
else:
substrate = tagId & 0x7f,
......@@ -38,3 +40,4 @@
else:
substrate = tagId & 0x7f,
tagId >>= 7
......@@ -40,4 +43,5 @@
tagId >>= 7
while tagId:
substrate = (0x80 | (tagId & 0x7f),) + substrate
tagId >>= 7
......@@ -41,8 +45,9 @@
while tagId:
substrate = (0x80 | (tagId & 0x7f),) + substrate
tagId >>= 7
return (encodedTag | 0x1F,) + substrate
def encodeLength(self, length, defMode):
if not defMode and self.supportIndefLenMode:
return (0x80,)
......@@ -44,7 +49,8 @@
return (encodedTag | 0x1F,) + substrate
def encodeLength(self, length, defMode):
if not defMode and self.supportIndefLenMode:
return (0x80,)
if length < 0x80:
return length,
......@@ -49,7 +55,8 @@
if length < 0x80:
return length,
else:
substrate = ()
while length:
substrate = (length & 0xff,) + substrate
length >>= 8
......@@ -51,6 +58,7 @@
else:
substrate = ()
while length:
substrate = (length & 0xff,) + substrate
length >>= 8
substrateLen = len(substrate)
......@@ -56,3 +64,4 @@
substrateLen = len(substrate)
if substrateLen > 126:
raise error.PyAsn1Error('Length octets overflow (%d)' % substrateLen)
......@@ -57,5 +66,6 @@
if substrateLen > 126:
raise error.PyAsn1Error('Length octets overflow (%d)' % substrateLen)
return (0x80 | substrateLen,) + substrate
def encodeValue(self, value, asn1Spec, encodeFun, **options):
......@@ -87,6 +97,11 @@
value, asn1Spec, encodeFun, **options
)
if LOG:
LOG('encoded %svalue %s into %s' % (
isConstructed and 'constructed ' or '', value, substrate
))
if not substrate and isConstructed and options.get('ifNotEmpty', False):
return substrate
......@@ -90,7 +105,6 @@
if not substrate and isConstructed and options.get('ifNotEmpty', False):
return substrate
# primitive form implies definite mode
if not isConstructed:
defModeOverride = True
......@@ -94,4 +108,7 @@
if not isConstructed:
defModeOverride = True
if LOG:
LOG('overridden encoding mode into definitive for primitive type')
header = self.encodeTag(singleTag, isConstructed)
......@@ -97,3 +114,8 @@
header = self.encodeTag(singleTag, isConstructed)
if LOG:
LOG('encoded %stag %s into %s' % (isConstructed and 'constructed ' or '',
singleTag, debug.hexdump(header)))
header += self.encodeLength(len(substrate), defModeOverride)
......@@ -98,5 +120,9 @@
header += self.encodeLength(len(substrate), defModeOverride)
if LOG:
LOG('encoded %s octets (tag + payload) into %s' % (
len(substrate), debug.hexdump(header)))
if isOctets:
substrate = ints2octs(header) + substrate
......@@ -133,6 +159,11 @@
def encodeValue(self, value, asn1Spec, encodeFun, **options):
if value == 0:
if LOG:
LOG('encoding %spayload for zero INTEGER' % (
self.supportCompactZero and 'no ' or ''
))
# de-facto way to encode zero
if self.supportCompactZero:
return (), False, False
......@@ -159,8 +190,11 @@
substrate = alignedValue.asOctets()
return int2oct(len(substrate) * 8 - valueLength) + substrate, False, True
if LOG:
LOG('encoding into up to %s-octet chunks' % maxChunkSize)
baseTag = value.tagSet.baseTag
# strip off explicit tags
if baseTag:
tagSet = tag.TagSet(baseTag, baseTag)
......@@ -162,8 +196,9 @@
baseTag = value.tagSet.baseTag
# strip off explicit tags
if baseTag:
tagSet = tag.TagSet(baseTag, baseTag)
else:
tagSet = tag.TagSet()
......@@ -197,7 +232,8 @@
if not maxChunkSize or len(substrate) <= maxChunkSize:
return substrate, False, True
else:
if LOG:
LOG('encoding into up to %s-octet chunks' % maxChunkSize)
# strip off explicit tags for inner chunks
......@@ -207,6 +243,7 @@
# strip off explicit tags
if baseTag:
tagSet = tag.TagSet(baseTag, baseTag)
else:
tagSet = tag.TagSet()
......@@ -218,6 +255,7 @@
# strip off explicit tags
if baseTag:
tagSet = tag.TagSet(baseTag, baseTag)
else:
tagSet = tag.TagSet()
......@@ -270,5 +308,6 @@
oid = (second + 80,) + oid[2:]
else:
raise error.PyAsn1Error('Impossible first/second arcs at %s' % (value,))
elif first == 2:
oid = (second + 80,) + oid[2:]
......@@ -273,5 +312,6 @@
elif first == 2:
oid = (second + 80,) + oid[2:]
else:
raise error.PyAsn1Error('Impossible first/second arcs at %s' % (value,))
......@@ -282,7 +322,8 @@
if 0 <= subOid <= 127:
# Optimize for the common case
octets += (subOid,)
elif subOid > 127:
# Pack large Sub-Object IDs
res = (subOid & 0x7f,)
subOid >>= 7
......@@ -285,7 +326,8 @@
elif subOid > 127:
# Pack large Sub-Object IDs
res = (subOid & 0x7f,)
subOid >>= 7
while subOid:
res = (0x80 | (subOid & 0x7f),) + res
subOid >>= 7
......@@ -289,5 +331,6 @@
while subOid:
res = (0x80 | (subOid & 0x7f),) + res
subOid >>= 7
# Add packed Sub-Object ID to resulted Object ID
octets += res
......@@ -292,5 +335,6 @@
# Add packed Sub-Object ID to resulted Object ID
octets += res
else:
raise error.PyAsn1Error('Negative OID arc %s at %s' % (subOid, value))
......@@ -306,5 +350,6 @@
ms, es = 1, 1
if m < 0:
ms = -1 # mantissa sign
if e < 0:
es = -1 # exponent sign
......@@ -309,3 +354,4 @@
if e < 0:
es = -1 # exponent sign
m *= ms
......@@ -311,4 +357,5 @@
m *= ms
if encbase == 8:
m *= 2 ** (abs(e) % 3 * es)
e = abs(e) // 3 * es
......@@ -312,6 +359,7 @@
if encbase == 8:
m *= 2 ** (abs(e) % 3 * es)
e = abs(e) // 3 * es
elif encbase == 16:
m *= 2 ** (abs(e) % 4 * es)
e = abs(e) // 4 * es
......@@ -322,6 +370,7 @@
e -= 1
continue
break
return ms, int(m), encbase, e
def _chooseEncBase(self, value):
......@@ -329,5 +378,6 @@
encBase = [2, 8, 16]
if value.binEncBase in encBase:
return self._dropFloatingPoint(m, value.binEncBase, e)
elif self.binEncBase in encBase:
return self._dropFloatingPoint(m, self.binEncBase, e)
......@@ -332,8 +382,9 @@
elif self.binEncBase in encBase:
return self._dropFloatingPoint(m, self.binEncBase, e)
# auto choosing base 2/8/16
mantissa = [m, m, m]
exponent = [e, e, e]
sign = 1
encbase = 2
e = float('inf')
......@@ -334,11 +385,12 @@
# auto choosing base 2/8/16
mantissa = [m, m, m]
exponent = [e, e, e]
sign = 1
encbase = 2
e = float('inf')
for i in range(3):
(sign,
mantissa[i],
encBase[i],
exponent[i]) = self._dropFloatingPoint(mantissa[i], encBase[i], exponent[i])
......@@ -340,9 +392,10 @@
for i in range(3):
(sign,
mantissa[i],
encBase[i],
exponent[i]) = self._dropFloatingPoint(mantissa[i], encBase[i], exponent[i])
if abs(exponent[i]) < abs(e) or (abs(exponent[i]) == abs(e) and mantissa[i] < m):
e = exponent[i]
m = int(mantissa[i])
encbase = encBase[i]
......@@ -345,7 +398,12 @@
if abs(exponent[i]) < abs(e) or (abs(exponent[i]) == abs(e) and mantissa[i] < m):
e = exponent[i]
m = int(mantissa[i])
encbase = encBase[i]
if LOG:
LOG('automatically chosen REAL encoding base %s, sign %s, mantissa %s, '
'exponent %s' % (encbase, sign, m, e))
return sign, m, encbase, e
def encodeValue(self, value, asn1Spec, encodeFun, **options):
......@@ -354,5 +412,6 @@
if value.isPlusInf:
return (0x40,), False, False
if value.isMinusInf:
return (0x41,), False, False
......@@ -357,3 +416,4 @@
if value.isMinusInf:
return (0x41,), False, False
m, b, e = value
......@@ -359,3 +419,4 @@
m, b, e = value
if not m:
return null, False, True
......@@ -360,3 +421,4 @@
if not m:
return null, False, True
if b == 10:
......@@ -362,2 +424,5 @@
if b == 10:
if LOG:
LOG('encoding REAL into character form')
return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), False, True
......@@ -363,4 +428,5 @@
return str2octs('\x03%dE%s%d' % (m, e == 0 and '+' or '', e)), False, True
elif b == 2:
fo = 0x80 # binary encoding
ms, m, encbase, e = self._chooseEncBase(value)
......@@ -364,5 +430,6 @@
elif b == 2:
fo = 0x80 # binary encoding
ms, m, encbase, e = self._chooseEncBase(value)
if ms < 0: # mantissa sign
fo |= 0x40 # sign bit
......@@ -367,7 +434,8 @@
if ms < 0: # mantissa sign
fo |= 0x40 # sign bit
# exponent & mantissa normalization
if encbase == 2:
while m & 0x1 == 0:
m >>= 1
e += 1
......@@ -369,10 +437,11 @@
# exponent & mantissa normalization
if encbase == 2:
while m & 0x1 == 0:
m >>= 1
e += 1
elif encbase == 8:
while m & 0x7 == 0:
m >>= 3
e += 1
fo |= 0x10
......@@ -374,10 +443,11 @@
elif encbase == 8:
while m & 0x7 == 0:
m >>= 3
e += 1
fo |= 0x10
else: # encbase = 16
while m & 0xf == 0:
m >>= 4
e += 1
fo |= 0x20
......@@ -379,6 +449,7 @@
else: # encbase = 16
while m & 0xf == 0:
m >>= 4
e += 1
fo |= 0x20
sf = 0 # scale factor
......@@ -384,4 +455,5 @@
sf = 0 # scale factor
while m & 0x1 == 0:
m >>= 1
sf += 1
......@@ -385,5 +457,6 @@
while m & 0x1 == 0:
m >>= 1
sf += 1
if sf > 3:
raise error.PyAsn1Error('Scale factor overflow') # bug if raised
......@@ -388,6 +461,7 @@
if sf > 3:
raise error.PyAsn1Error('Scale factor overflow') # bug if raised
fo |= sf << 2
eo = null
if e == 0 or e == -1:
eo = int2oct(e & 0xff)
......@@ -390,8 +464,9 @@
fo |= sf << 2
eo = null
if e == 0 or e == -1:
eo = int2oct(e & 0xff)
else:
while e not in (0, -1):
eo = int2oct(e & 0xff) + eo
e >>= 8
......@@ -394,6 +469,7 @@
else:
while e not in (0, -1):
eo = int2oct(e & 0xff) + eo
e >>= 8
if e == 0 and eo and oct2int(eo[0]) & 0x80:
eo = int2oct(0) + eo
......@@ -398,4 +474,5 @@
if e == 0 and eo and oct2int(eo[0]) & 0x80:
eo = int2oct(0) + eo
if e == -1 and eo and not (oct2int(eo[0]) & 0x80):
eo = int2oct(0xff) + eo
......@@ -400,5 +477,6 @@
if e == -1 and eo and not (oct2int(eo[0]) & 0x80):
eo = int2oct(0xff) + eo
n = len(eo)
if n > 0xff:
raise error.PyAsn1Error('Real exponent overflow')
......@@ -402,5 +480,6 @@
n = len(eo)
if n > 0xff:
raise error.PyAsn1Error('Real exponent overflow')
if n == 1:
pass
......@@ -405,4 +484,5 @@
if n == 1:
pass
elif n == 2:
fo |= 1
......@@ -407,4 +487,5 @@
elif n == 2:
fo |= 1
elif n == 3:
fo |= 2
......@@ -409,5 +490,6 @@
elif n == 3:
fo |= 2
else:
fo |= 3
eo = int2oct(n & 0xff) + eo
......@@ -411,4 +493,5 @@
else:
fo |= 3
eo = int2oct(n & 0xff) + eo
po = null
......@@ -414,4 +497,5 @@
po = null
while m:
po = int2oct(m & 0xff) + po
m >>= 8
......@@ -415,4 +499,5 @@
while m:
po = int2oct(m & 0xff) + po
m >>= 8
substrate = int2oct(fo) + eo + po
......@@ -418,2 +503,3 @@
substrate = int2oct(fo) + eo + po
return substrate, False, True
......@@ -419,4 +505,5 @@
return substrate, False, True
else:
raise error.PyAsn1Error('Prohibited Real base %s' % b)
......@@ -441,6 +528,8 @@
namedType = namedTypes[idx]
if namedType.isOptional and not component.isValue:
if LOG:
LOG('not encoding OPTIONAL component %r' % (namedType,))
continue
if namedType.isDefaulted and component == namedType.asn1Object:
......@@ -444,6 +533,8 @@
continue
if namedType.isDefaulted and component == namedType.asn1Object:
if LOG:
LOG('not encoding DEFAULT component %r' % (namedType,))
continue
if self.omitEmptyOptionals:
......@@ -457,6 +548,9 @@
if wrapType.tagSet and not wrapType.isSameTypeWith(component):
chunk = encodeFun(chunk, wrapType, **options)
if LOG:
LOG('wrapped open type with wrap type %r' % (wrapType,))
substrate += chunk
else:
......@@ -467,6 +561,7 @@
component = value[namedType.name]
except KeyError:
raise error.PyAsn1Error('Component name "%s" not found in %r' % (namedType.name, value))
raise error.PyAsn1Error('Component name "%s" not found in %r' % (
namedType.name, value))
if namedType.isOptional and namedType.name not in value:
......@@ -471,5 +566,7 @@
if namedType.isOptional and namedType.name not in value:
if LOG:
LOG('not encoding OPTIONAL component %r' % (namedType,))
continue
if namedType.isDefaulted and component == namedType.asn1Object:
......@@ -473,6 +570,8 @@
continue
if namedType.isDefaulted and component == namedType.asn1Object:
if LOG:
LOG('not encoding DEFAULT component %r' % (namedType,))
continue
if self.omitEmptyOptionals:
......@@ -486,6 +585,9 @@
if wrapType.tagSet and not wrapType.isSameTypeWith(component):
chunk = encodeFun(chunk, wrapType, **options)
if LOG:
LOG('wrapped open type with wrap type %r' % (wrapType,))
substrate += chunk
return substrate, True, True
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment