mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 01:14:41 +00:00
Fixes #3847.
This commit is contained in:
@@ -1646,7 +1646,7 @@ proc send*(socket: AsyncFD, data: string,
|
||||
# -- Await Macro
|
||||
include asyncmacro
|
||||
|
||||
proc recvLine*(socket: AsyncFD): Future[string] {.async.} =
|
||||
proc recvLine*(socket: AsyncFD): Future[string] {.async, deprecated.} =
|
||||
## Reads a line of data from ``socket``. Returned future will complete once
|
||||
## a full line is read or an error occurs.
|
||||
##
|
||||
@@ -1664,6 +1664,8 @@ proc recvLine*(socket: AsyncFD): Future[string] {.async.} =
|
||||
##
|
||||
## **Note**: This procedure is mostly used for testing. You likely want to
|
||||
## use ``asyncnet.recvLine`` instead.
|
||||
##
|
||||
## **Deprecated since version 0.15.0**: Use ``asyncnet.recvLine()`` instead.
|
||||
|
||||
template addNLIfEmpty(): stmt =
|
||||
if result.len == 0:
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
|
||||
## This module implements a high performance asynchronous HTTP server.
|
||||
##
|
||||
## This HTTP server has not been designed to be used in production, but
|
||||
## for testing applications locally. Because of this, when deploying your
|
||||
## application you should use a reverse proxy (for example nginx) instead of
|
||||
## allowing users to connect directly to this server.
|
||||
##
|
||||
##
|
||||
## Examples
|
||||
## --------
|
||||
##
|
||||
|
||||
@@ -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].} =
|
||||
|
||||
@@ -112,6 +112,7 @@ else:
|
||||
|
||||
const
|
||||
BufferSize*: int = 4000 ## size of a buffered socket's buffer
|
||||
MaxLineLength* = 1_000_000
|
||||
|
||||
type
|
||||
SocketImpl* = object ## socket type
|
||||
@@ -1006,7 +1007,7 @@ proc peekChar(socket: Socket, c: var char): int {.tags: [ReadIOEffect].} =
|
||||
result = recv(socket.fd, addr(c), 1, MSG_PEEK)
|
||||
|
||||
proc readLine*(socket: Socket, line: var TaintedString, timeout = -1,
|
||||
flags = {SocketFlag.SafeDisconn}) {.
|
||||
flags = {SocketFlag.SafeDisconn}, maxLength = MaxLineLength) {.
|
||||
tags: [ReadIOEffect, TimeEffect].} =
|
||||
## Reads a line of data from ``socket``.
|
||||
##
|
||||
@@ -1021,6 +1022,10 @@ proc readLine*(socket: Socket, line: var TaintedString, timeout = -1,
|
||||
## A timeout can be specified in milliseconds, if data is not received within
|
||||
## the specified time an ETimeout exception will be raised.
|
||||
##
|
||||
## 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**: Only the ``SafeDisconn`` flag is currently supported.
|
||||
|
||||
template addNLIfEmpty() =
|
||||
@@ -1054,8 +1059,15 @@ proc readLine*(socket: Socket, line: var TaintedString, timeout = -1,
|
||||
return
|
||||
add(line.string, c)
|
||||
|
||||
# Verify that this isn't a DOS attack: #3847.
|
||||
if line.string.len > maxLength:
|
||||
let msg = "recvLine received more than the specified `maxLength` " &
|
||||
"allowed."
|
||||
raise newException(ValueError, msg)
|
||||
|
||||
proc recvLine*(socket: Socket, timeout = -1,
|
||||
flags = {SocketFlag.SafeDisconn}): TaintedString =
|
||||
flags = {SocketFlag.SafeDisconn},
|
||||
maxLength = MaxLineLength): TaintedString =
|
||||
## Reads a line of data from ``socket``.
|
||||
##
|
||||
## If a full line is read ``\r\L`` is not
|
||||
@@ -1069,9 +1081,13 @@ proc recvLine*(socket: Socket, timeout = -1,
|
||||
## A timeout can be specified in milliseconds, if data is not received within
|
||||
## the specified time an ETimeout exception will be raised.
|
||||
##
|
||||
## 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**: Only the ``SafeDisconn`` flag is currently supported.
|
||||
result = ""
|
||||
readLine(socket, result, timeout, flags)
|
||||
readLine(socket, result, timeout, flags, maxLength)
|
||||
|
||||
proc recvFrom*(socket: Socket, data: var string, length: int,
|
||||
address: var string, port: var Port, flags = 0'i32): int {.
|
||||
|
||||
Reference in New Issue
Block a user