Fix error in format C decoding

This commit is contained in:
Tony Garnock-Jones 2018-11-18 16:28:21 +00:00
parent c9484ac9ac
commit 639241c5a6
6 changed files with 46 additions and 59 deletions

View File

@ -13,6 +13,7 @@ class EncodeError extends Error {
this.irritant = irritant;
}
}
class ShortPacket extends DecodeError {}
class Decoder {
constructor(packet, options) {
@ -22,22 +23,18 @@ class Decoder {
this.shortForms = options.shortForms || {};
}
peekbyte() {
if (this.index >= this.packet.length) throw new DecodeError("Short packet");
// ^ NOTE: greater-than-or-equal-to, not greater-than.
return this.packet[this.index];
}
advance(count) {
const start = this.index;
this.index += (count === void 0 ? 1 : count);
return start;
}
nextbyte() {
const val = this.peekbyte();
this.advance();
return val;
if (this.index >= this.packet.length) throw new ShortPacket("Short packet");
// ^ NOTE: greater-than-or-equal-to, not greater-than.
return this.packet[this.index++];
}
nextbytes(n) {
const start = this.index;
this.index += n;
if (this.index > this.packet.length) throw new ShortPacket("Short packet");
// ^ NOTE: greater-than, not greater-than-or-equal-to.
return new DataView(this.packet.buffer, this.packet.byteOffset + start, n);
}
wirelength(arg) {
@ -52,36 +49,25 @@ class Decoder {
return (this.varint() << 7) + (v - 128);
}
nextbytes(n) {
const start = this.advance(n);
if (this.index > this.packet.length) throw new DecodeError("Short packet");
// ^ NOTE: greater-than, not greater-than-or-equal-to.
return new DataView(this.packet.buffer, this.packet.byteOffset + start, n);
}
nextvalues(n) {
const result = [];
for (let i = 0; i < n; i++) result.push(this.next());
return result;
}
peekop() {
const b = this.peekbyte();
nextop() {
const b = this.nextbyte();
const major = b >> 6;
const minor = (b >> 4) & 3;
const arg = b & 15;
return [major, minor, arg];
}
nextop() {
const op = this.peekop();
this.advance();
return op;
}
peekend(arg) {
const [a,i,r] = this.peekop();
return (a === 0) && (i === 3) && (r === arg);
const [a,i,r] = this.nextop();
const result = (a === 0) && (i === 3) && (r === arg);
if (!result) this.index--;
return result;
}
binarystream(arg, minor) {
@ -335,6 +321,7 @@ class Encoder {
Object.assign(module.exports, {
DecodeError,
EncodeError,
ShortPacket,
Decoder,
Encoder,
});

View File

@ -12,6 +12,7 @@
26626865626c6c6060616f36
27626865626c6c6060616f37
2c111213143c
2c2563616263352563646566353c
2cc2516111c2516212c25163133c
410d
417f

View File

@ -71,6 +71,7 @@ describe('hex samples', () => {
{ expected: Bytes.from("hello"), encodesTo: '6568656c6c6f', },
{ expected: Symbol.for("hello"), encodesTo: '7568656c6c6f', },
{ expected: Immutable.Seq([1, 2, 3, 4]), },
{ expected: Preserves.fromJS(["abc", "def"]), encodesTo: 'c25361626353646566' },
{ expected: Preserves.fromJS([["a", 1], ["b", 2], ["c", 3]]),
encodesTo: 'c3c2516111c2516212c2516313', },
{ expected: 13, },

View File

@ -1,6 +1,6 @@
from .preserves import Float, Symbol, Record, ImmutableDict
from .preserves import DecodeError, EncodeError
from .preserves import DecodeError, EncodeError, ShortPacket
from .preserves import Decoder, Encoder

View File

@ -119,6 +119,7 @@ def dict_kvs(d):
class DecodeError(ValueError): pass
class EncodeError(ValueError): pass
class ShortPacket(DecodeError): pass
class Codec(object):
def __init__(self):
@ -183,21 +184,19 @@ class Decoder(Codec):
self.packet = packet
self.index = 0
def peekbyte(self):
if self.index < len(self.packet):
return _ord(self.packet[self.index])
else:
raise DecodeError('Short packet')
def advance(self, count=1):
start = self.index
self.index = self.index + count
return start
def nextbyte(self):
val = self.peekbyte()
self.advance()
return val
if self.index >= len(self.packet):
raise ShortPacket('Short packet')
self.index = self.index + 1
return _ord(self.packet[self.index - 1])
def nextbytes(self, n):
start = self.index
end = start + n
if end > len(self.packet):
raise ShortPacket('Short packet')
self.index = end
return self.packet[start : end]
def wirelength(self, arg):
if arg < 15:
@ -211,30 +210,24 @@ class Decoder(Codec):
else:
return self.varint() * 128 + (v - 128)
def nextbytes(self, n):
start = self.advance(n)
return self.packet[start : self.index]
def nextvalues(self, n):
result = []
for i in range(n):
result.append(self.next())
return result
def peekop(self):
b = self.peekbyte()
def nextop(self):
b = self.nextbyte()
major = b >> 6
minor = (b >> 4) & 3
arg = b & 15
return (major, minor, arg)
def nextop(self):
op = self.peekop()
self.advance()
return op
def peekend(self, arg):
return self.peekop() == (0, 3, arg)
matched = (self.nextop() == (0, 3, arg))
if not matched:
self.index = self.index - 1
return matched
def binarystream(self, arg, minor):
result = []

View File

@ -199,3 +199,8 @@ class CodecTests(unittest.TestCase):
self._roundtrip((False,) * 15, _buf(0xCF, 0x0F, b'\x00' * 15))
self._roundtrip((False,) * 100, _buf(0xCF, 0x64, b'\x00' * 100))
self._roundtrip((False,) * 200, _buf(0xCF, 0xC8, 0x01, b'\x00' * 200))
def test_format_c_twice(self):
self._roundtrip(SequenceStream([StringStream([b'abc']), StringStream([b'def'])]),
_buf(0x2C, 0x25, 0x63, 'abc', 0x35, 0x25, 0x63, 'def', 0x35, 0x3C),
back=(u'abc', u'def'))