diff options
| author | Oskari Timperi <oskari.timperi@iki.fi> | 2018-04-02 11:37:07 +0300 |
|---|---|---|
| committer | Oskari Timperi <oskari.timperi@iki.fi> | 2018-04-02 11:39:36 +0300 |
| commit | 2427dd3c04c37dd78a54a73da41141b74182590a (patch) | |
| tree | e2024e67ba094566282c05160048ae1f4786f12d | |
| parent | c4c34c5974ea373288bd29df25ee5fd50325daa2 (diff) | |
| download | nimpb-2427dd3c04c37dd78a54a73da41141b74182590a.tar.gz nimpb-2427dd3c04c37dd78a54a73da41141b74182590a.zip | |
Multiple fixes to reading data from a stream
- littleEndia32/64 arguments were in wrong order in a few places
- add safeReadStr that throws and exception if couldn't read enough data
- throw exceptions when not reading enough data
| -rw-r--r-- | generator/protoc_gen_nim.nim | 8 | ||||
| -rw-r--r-- | src/protobuf/stream.nim | 30 |
2 files changed, 23 insertions, 15 deletions
diff --git a/generator/protoc_gen_nim.nim b/generator/protoc_gen_nim.nim index 22e3cd7..d371859 100644 --- a/generator/protoc_gen_nim.nim +++ b/generator/protoc_gen_nim.nim @@ -638,7 +638,7 @@ iterator genReadMapKVProc(msg: Message): string = if isMessage(value): yield indent("let", 12) yield indent("size = readVarint(stream)", 16) - yield indent("data = readStr(stream, int(size))", 16) + yield indent("data = safeReadStr(stream, int(size))", 16) yield indent("pbs = newProtobufStream(newStringStream(data))", 16) yield indent(&"value = read{value.typeName}(pbs)", 12) else: @@ -677,7 +677,7 @@ iterator genReadMessageProc(msg: Message): string = yield indent(&"expectWireType(wireType, {field.wiretypeStr})", 12) yield indent("let", 12) yield indent("size = readVarint(stream)", 16) - yield indent("data = readStr(stream, int(size))", 16) + yield indent("data = safeReadStr(stream, int(size))", 16) yield indent("pbs = newProtobufStream(newStringStream(data))", 16) yield indent(&"read{field.typeName}KV(pbs, result.{field.name})", 12) elif isNumeric(field): @@ -698,7 +698,7 @@ iterator genReadMessageProc(msg: Message): string = yield indent(&"expectWireType(wireType, {field.wiretypeStr})", 12) yield indent("let", 12) yield indent("size = readVarint(stream)", 16) - yield indent("data = readStr(stream, int(size))", 16) + yield indent("data = safeReadStr(stream, int(size))", 16) yield indent("pbs = newProtobufStream(newStringStream(data))", 16) yield indent(&"{setter}(result, {reader}(pbs))", 12) else: @@ -709,7 +709,7 @@ iterator genReadMessageProc(msg: Message): string = if isMessage(field): yield indent("let", 12) yield indent("size = readVarint(stream)", 16) - yield indent("data = readStr(stream, int(size))", 16) + yield indent("data = safeReadStr(stream, int(size))", 16) yield indent("pbs = newProtobufStream(newStringStream(data))", 16) yield indent(&"{setter}(result, {reader}(pbs))", 12) else: diff --git a/src/protobuf/stream.nim b/src/protobuf/stream.nim index d7eeadd..9d843e6 100644 --- a/src/protobuf/stream.nim +++ b/src/protobuf/stream.nim @@ -181,7 +181,8 @@ proc writeFixed64*(stream: ProtobufStream, value: uint64) = proc readFixed64*(stream: ProtobufStream): uint64 = var tmp: uint64 - discard readData(stream, addr(tmp), sizeof(tmp)) + if readData(stream, addr(tmp), sizeof(tmp)) != sizeof(tmp): + raise newException(IOError, "cannot read from stream") littleEndian64(addr(result), addr(tmp)) proc writeSFixed64*(stream: ProtobufStream, value: int64) = @@ -201,8 +202,9 @@ proc writeDouble*(stream: ProtobufStream, value: float64) = proc readDouble*(stream: ProtobufStream): float64 = var tmp: uint64 - discard readData(stream, addr(tmp), sizeof(tmp)) - littleEndian64(addr(tmp), addr(result)) + if readData(stream, addr(tmp), sizeof(tmp)) != sizeof(tmp): + raise newException(IOError, "cannot read from stream") + littleEndian64(addr(result), addr(tmp)) proc writeFixed32*(stream: ProtobufStream, value: uint32) = var @@ -215,8 +217,9 @@ proc writeFixed32*(stream: ProtobufStream, value: uint32) = proc readFixed32*(stream: ProtobufStream): uint32 = var tmp: uint32 - discard readData(stream, addr(tmp), sizeof(tmp)) - littleEndian32(addr(tmp), addr(result)) + if readData(stream, addr(tmp), sizeof(tmp)) != sizeof(tmp): + raise newException(IOError, "cannot read from stream") + littleEndian32(addr(result), addr(tmp)) proc writeSFixed32*(stream: ProtobufStream, value: int32) = writeFixed32(stream, cast[uint32](value)) @@ -235,8 +238,9 @@ proc writeFloat*(stream: ProtobufStream, value: float32) = proc readFloat*(stream: ProtobufStream): float32 = var tmp: float32 - discard readData(stream, addr(tmp), sizeof(tmp)) - littleEndian32(addr(tmp), addr(result)) + if readData(stream, addr(tmp), sizeof(tmp)) != sizeof(tmp): + raise newException(IOError, "cannot read from stream") + littleEndian32(addr(result), addr(tmp)) proc writeString*(stream: ProtobufStream, s: string) = writeUInt64(stream, len(s).uint64) @@ -245,10 +249,14 @@ proc writeString*(stream: ProtobufStream, s: string) = proc writeBytes*(stream: ProtobufStream, s: bytes) = writeString(stream, string(s)) +proc safeReadStr*(stream: Stream, size: int): string = + result = newString(size) + if readData(stream, addr(result[0]), size) != size: + raise newException(IOError, "cannot read from stream") + proc readString*(stream: ProtobufStream): string = - # TODO: use something else than readStr to get rid of int cast? - let size = readUInt64(stream).int - result = readStr(stream, size) + let size = int(readUInt64(stream)) + result = safeReadStr(stream, size) proc readBytes*(stream: ProtobufStream): bytes = bytes(readString(stream)) @@ -336,7 +344,7 @@ proc skipField*(stream: ProtobufStream, wiretype: WireType) = discard readFixed32(stream) of WireType.LengthDelimited: let size = readVarint(stream) - discard readStr(stream, int(size)) + discard safeReadStr(stream, int(size)) else: raise newException(Exception, "unsupported wiretype: " & $wiretype) |
