check for size bounds when reading varints
This commit is contained in:
parent
94fc4e6fd2
commit
53e163abf2
|
@ -15,7 +15,7 @@ import peerinfo,
|
||||||
varint,
|
varint,
|
||||||
vbuffer
|
vbuffer
|
||||||
|
|
||||||
const DefaultReadSize*: uint = 1 shl 20 # 1mb, in order to fit mplex spec
|
const DefaultReadSize* = 1 shl 20
|
||||||
|
|
||||||
type
|
type
|
||||||
Connection* = ref object of LPStream
|
Connection* = ref object of LPStream
|
||||||
|
@ -24,10 +24,14 @@ type
|
||||||
observedAddrs*: Multiaddress
|
observedAddrs*: Multiaddress
|
||||||
|
|
||||||
InvalidVarintException = object of LPStreamError
|
InvalidVarintException = object of LPStreamError
|
||||||
|
InvalidVarintSizeException = object of LPStreamError
|
||||||
|
|
||||||
proc newInvalidVarintException*(): ref InvalidVarintException =
|
proc newInvalidVarintException*(): ref InvalidVarintException =
|
||||||
newException(InvalidVarintException, "unable to parse varint")
|
newException(InvalidVarintException, "unable to parse varint")
|
||||||
|
|
||||||
|
proc newInvalidVarintSizeException*(): ref InvalidVarintSizeException =
|
||||||
|
newException(InvalidVarintSizeException, "wrong varint size")
|
||||||
|
|
||||||
proc init*[T: Connection](self: var T, stream: LPStream) =
|
proc init*[T: Connection](self: var T, stream: LPStream) =
|
||||||
## create a new Connection for the specified async reader/writer
|
## create a new Connection for the specified async reader/writer
|
||||||
new self
|
new self
|
||||||
|
@ -124,8 +128,8 @@ proc readLp*(s: Connection): Future[seq[byte]] {.async, gcsafe.} =
|
||||||
break
|
break
|
||||||
if res != VarintStatus.Success:
|
if res != VarintStatus.Success:
|
||||||
raise newInvalidVarintException()
|
raise newInvalidVarintException()
|
||||||
if size > DefaultReadSize:
|
if size.int > DefaultReadSize:
|
||||||
raise newLPStreamLimitError()
|
raise newInvalidVarintSizeException()
|
||||||
buff.setLen(size)
|
buff.setLen(size)
|
||||||
if size > 0.uint:
|
if size > 0.uint:
|
||||||
trace "reading exact bytes from stream", size = size
|
trace "reading exact bytes from stream", size = size
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
## This file may not be copied, modified, or distributed except according to
|
## This file may not be copied, modified, or distributed except according to
|
||||||
## those terms.
|
## those terms.
|
||||||
|
|
||||||
import chronos, options
|
import chronos
|
||||||
import nimcrypto/utils, chronicles
|
import nimcrypto/utils, chronicles
|
||||||
import types,
|
import types,
|
||||||
../../connection,
|
../../connection,
|
||||||
|
@ -18,30 +18,35 @@ import types,
|
||||||
logScope:
|
logScope:
|
||||||
topic = "MplexCoder"
|
topic = "MplexCoder"
|
||||||
|
|
||||||
|
const DefaultChannelSize* = 1 shr 20
|
||||||
|
|
||||||
type
|
type
|
||||||
Msg* = tuple
|
Msg* = tuple
|
||||||
id: uint
|
id: uint
|
||||||
msgType: MessageType
|
msgType: MessageType
|
||||||
data: seq[byte]
|
data: seq[byte]
|
||||||
|
|
||||||
proc readMplexVarint(conn: Connection): Future[Option[uint]] {.async, gcsafe.} =
|
proc readMplexVarint(conn: Connection): Future[uint] {.async, gcsafe.} =
|
||||||
var
|
var
|
||||||
varint: uint
|
varint: uint
|
||||||
length: int
|
length: int
|
||||||
res: VarintStatus
|
res: VarintStatus
|
||||||
buffer = newSeq[byte](10)
|
buffer = newSeq[byte](10)
|
||||||
|
|
||||||
result = none(uint)
|
|
||||||
try:
|
try:
|
||||||
for i in 0..<len(buffer):
|
for i in 0..<len(buffer):
|
||||||
await conn.readExactly(addr buffer[i], 1)
|
await conn.readExactly(addr buffer[i], 1)
|
||||||
res = PB.getUVarint(buffer.toOpenArray(0, i), length, varint)
|
res = PB.getUVarint(buffer.toOpenArray(0, i), length, varint)
|
||||||
if res == VarintStatus.Success:
|
if res == VarintStatus.Success:
|
||||||
return some(varint)
|
break
|
||||||
if res != VarintStatus.Success:
|
if res != VarintStatus.Success:
|
||||||
raise newInvalidVarintException()
|
raise newInvalidVarintException()
|
||||||
|
if varint.int > DefaultReadSize:
|
||||||
|
raise newInvalidVarintSizeException()
|
||||||
|
return varint
|
||||||
except LPStreamIncompleteError as exc:
|
except LPStreamIncompleteError as exc:
|
||||||
trace "unable to read varint", exc = exc.msg
|
trace "unable to read varint", exc = exc.msg
|
||||||
|
raise exc
|
||||||
|
|
||||||
proc readMsg*(conn: Connection): Future[Msg] {.async, gcsafe.} =
|
proc readMsg*(conn: Connection): Future[Msg] {.async, gcsafe.} =
|
||||||
let headerVarint = await conn.readMplexVarint()
|
let headerVarint = await conn.readMplexVarint()
|
||||||
|
|
Loading…
Reference in New Issue