Fixes #3847.
This commit is contained in:
parent
6e7d50310e
commit
8a6343b5b6
4 changed files with 52 additions and 10 deletions
|
|
@ -388,7 +388,7 @@ proc accept*(socket: AsyncSocket,
|
|||
return retFut
|
||||
|
||||
proc recvLineInto*(socket: AsyncSocket, resString: FutureVar[string],
|
||||
flags = {SocketFlag.SafeDisconn}) {.async.} =
|
||||
flags = {SocketFlag.SafeDisconn}, maxLength = MaxLineLength) {.async.} =
|
||||
## Reads a line of data from ``socket`` into ``resString``.
|
||||
##
|
||||
## If a full line is read ``\r\L`` is not
|
||||
|
|
@ -401,13 +401,14 @@ proc recvLineInto*(socket: AsyncSocket, resString: FutureVar[string],
|
|||
## is read) then line will be set to ``""``.
|
||||
## The partial line **will be lost**.
|
||||
##
|
||||
## The ``maxLength`` parameter determines the maximum amount of characters
|
||||
## that can be read before a ``ValueError`` is raised. This prevents Denial
|
||||
## of Service (DOS) attacks.
|
||||
##
|
||||
## **Warning**: The ``Peek`` flag is not yet implemented.
|
||||
##
|
||||
## **Warning**: ``recvLineInto`` on unbuffered sockets assumes that the
|
||||
## protocol uses ``\r\L`` to delimit a new line.
|
||||
##
|
||||
## **Warning**: ``recvLineInto`` currently uses a raw pointer to a string for
|
||||
## performance reasons. This will likely change soon to use FutureVars.
|
||||
assert SocketFlag.Peek notin flags ## TODO:
|
||||
assert(not resString.mget.isNil(),
|
||||
"String inside resString future needs to be initialised")
|
||||
|
|
@ -454,6 +455,12 @@ proc recvLineInto*(socket: AsyncSocket, resString: FutureVar[string],
|
|||
else:
|
||||
resString.mget.add socket.buffer[socket.currPos]
|
||||
socket.currPos.inc()
|
||||
|
||||
# Verify that this isn't a DOS attack: #3847.
|
||||
if resString.mget.len > maxLength:
|
||||
let msg = "recvLine received more than the specified `maxLength` " &
|
||||
"allowed."
|
||||
raise newException(ValueError, msg)
|
||||
else:
|
||||
var c = ""
|
||||
while true:
|
||||
|
|
@ -475,10 +482,17 @@ proc recvLineInto*(socket: AsyncSocket, resString: FutureVar[string],
|
|||
resString.complete()
|
||||
return
|
||||
resString.mget.add c
|
||||
|
||||
# Verify that this isn't a DOS attack: #3847.
|
||||
if resString.mget.len > maxLength:
|
||||
let msg = "recvLine received more than the specified `maxLength` " &
|
||||
"allowed."
|
||||
raise newException(ValueError, msg)
|
||||
resString.complete()
|
||||
|
||||
proc recvLine*(socket: AsyncSocket,
|
||||
flags = {SocketFlag.SafeDisconn}): Future[string] {.async.} =
|
||||
flags = {SocketFlag.SafeDisconn},
|
||||
maxLength = MaxLineLength): Future[string] {.async.} =
|
||||
## Reads a line of data from ``socket``. Returned future will complete once
|
||||
## a full line is read or an error occurs.
|
||||
##
|
||||
|
|
@ -492,6 +506,10 @@ proc recvLine*(socket: AsyncSocket,
|
|||
## is read) then line will be set to ``""``.
|
||||
## The partial line **will be lost**.
|
||||
##
|
||||
## The ``maxLength`` parameter determines the maximum amount of characters
|
||||
## that can be read before a ``ValueError`` is raised. This prevents Denial
|
||||
## of Service (DOS) attacks.
|
||||
##
|
||||
## **Warning**: The ``Peek`` flag is not yet implemented.
|
||||
##
|
||||
## **Warning**: ``recvLine`` on unbuffered sockets assumes that the protocol
|
||||
|
|
@ -501,7 +519,7 @@ proc recvLine*(socket: AsyncSocket,
|
|||
# TODO: Optimise this
|
||||
var resString = newFutureVar[string]("asyncnet.recvLine")
|
||||
resString.mget() = ""
|
||||
await socket.recvLineInto(resString, flags)
|
||||
await socket.recvLineInto(resString, flags, maxLength)
|
||||
result = resString.mget()
|
||||
|
||||
proc listen*(socket: AsyncSocket, backlog = SOMAXCONN) {.tags: [ReadIOEffect].} =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue