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

View File

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

View File

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

View File

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

View File

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

View File

@ -199,3 +199,8 @@ class CodecTests(unittest.TestCase):
self._roundtrip((False,) * 15, _buf(0xCF, 0x0F, b'\x00' * 15)) self._roundtrip((False,) * 15, _buf(0xCF, 0x0F, b'\x00' * 15))
self._roundtrip((False,) * 100, _buf(0xCF, 0x64, b'\x00' * 100)) self._roundtrip((False,) * 100, _buf(0xCF, 0x64, b'\x00' * 100))
self._roundtrip((False,) * 200, _buf(0xCF, 0xC8, 0x01, b'\x00' * 200)) 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'))