Fix getMultipartBoundary() issues and add tests for it.

This commit is contained in:
cheatfate 2021-02-10 12:37:56 +02:00 committed by zah
parent 9b48496513
commit 3495122867
2 changed files with 105 additions and 14 deletions

View File

@ -423,19 +423,36 @@ func getMultipartBoundary*(ch: openarray[string]): HttpResult[string] =
return err("Content-Type is not multipart") return err("Content-Type is not multipart")
if len(mparts) < 2: if len(mparts) < 2:
return err("Content-Type missing boundary value") return err("Content-Type missing boundary value")
let stripped = strip(mparts[1])
if not(stripped.toLowerAscii().startsWith("boundary")): let index =
return err("Incorrect Content-Type boundary format") block:
let bparts = stripped.split("=") var idx = 0
for i in 1 ..< len(mparts):
let stripped = strip(mparts[i])
if stripped.toLowerAscii().startsWith("boundary="):
idx = i
break
idx
if index == 0:
err("Missing Content-Type boundary key")
else:
let stripped = strip(mparts[index])
let bparts = stripped.split("=", 1)
if len(bparts) < 2: if len(bparts) < 2:
err("Missing Content-Type boundary") err("Missing Content-Type boundary")
else:
if bparts[0].toLowerAscii() != "boundary":
err("Missing boundary key")
else: else:
let candidate = strip(bparts[1]) let candidate = strip(bparts[1])
if len(candidate) > 70: if len(candidate) == 0:
err("Content-Type boundary must be at least 1 character size")
elif len(candidate) > 70:
err("Content-Type boundary must be less then 70 characters") err("Content-Type boundary must be less then 70 characters")
else: else:
for ch in candidate: for ch in candidate:
if ch notin {'a'..'z', 'A' .. 'Z', '0' .. '9', if ch notin {'a' .. 'z', 'A' .. 'Z', '0' .. '9',
'\'' .. ')', '+' .. '/', ':', '=', '?', '_'}: '\'' .. ')', '+' .. '/', ':', '=', '?', '_'}:
return err("Content-Type boundary alphabat incorrect") return err("Content-Type boundary alphabet incorrect")
ok(candidate) ok(candidate)

View File

@ -680,6 +680,80 @@ suite "HTTP server testing suite":
check waitFor(testHTTPS2(initTAddress("127.0.0.1:30080"))) == true check waitFor(testHTTPS2(initTAddress("127.0.0.1:30080"))) == true
test "Content-Type multipart boundary test":
const AllowedCharacters = {
'a' .. 'z', 'A' .. 'Z', '0' .. '9',
'\'', '(', ')', '+', '_', ',', '-', '.' ,'/', ':', '=', '?'
}
const FailureVectors = [
"",
"multipart/byteranges; boundary=A",
"multipart/form-data;",
"multipart/form-data; boundary",
"multipart/form-data; boundary=",
"multipart/form-data; boundaryMore=A",
"multipart/form-data; charset=UTF-8; boundary",
"multipart/form-data; charset=UTF-8; boundary=",
"multipart/form-data; charset=UTF-8; boundary =",
"multipart/form-data; charset=UTF-8; boundary= ",
"multipart/form-data; charset=UTF-8; boundaryMore=",
"multipart/form-data; charset=UTF-8; boundaryMore=A",
"multipart/form-data; charset=UTF-8; boundaryMore=AAAAAAAAAAAAAAAAAAAA" &
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
]
const SuccessVectors = [
("multipart/form-data; boundary=A", "A"),
("multipart/form-data; charset=UTF-8; boundary=B", "B"),
("multipart/form-data; charset=UTF-8; boundary=--------------------" &
"--------------------------------------------------", "-----------" &
"-----------------------------------------------------------"),
("multipart/form-data; boundary=--------------------" &
"--------------------------------------------------", "-----------" &
"-----------------------------------------------------------"),
("multipart/form-data; boundary=--------------------" &
"--------------------------------------------------; charset=UTF-8",
"-----------------------------------------------------------------" &
"-----"),
("multipart/form-data; boundary=ABCDEFGHIJKLMNOPQRST" &
"UVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()+_,-.; charset=UTF-8",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()" &
"+_,-."),
("multipart/form-data; boundary=ABCDEFGHIJKLMNOPQRST" &
"UVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()+?=:/; charset=UTF-8",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()" &
"+?=:/"),
("multipart/form-data; charset=UTF-8; boundary=ABCDEFGHIJKLMNOPQRST" &
"UVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()+_,-.",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()" &
"+_,-."),
("multipart/form-data; charset=UTF-8; boundary=ABCDEFGHIJKLMNOPQRST" &
"UVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()+?=:/",
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()" &
"+?=:/")
]
for i in 0 ..< 256:
let boundary = "multipart/form-data; boundary=" & $char(i)
if char(i) in AllowedCharacters:
check getMultipartBoundary([boundary]).isOk()
else:
check getMultipartBoundary([boundary]).isErr()
check:
getMultipartBoundary([]).isErr()
getMultipartBoundary(["multipart/form-data; boundary=A",
"multipart/form-data; boundary=B"]).isErr()
for item in FailureVectors:
check getMultipartBoundary([item]).isErr()
for item in SuccessVectors:
let res = getMultipartBoundary([item[0]])
check:
res.isOk()
item[1] == res.get()
test "Leaks test": test "Leaks test":
check: check:
getTracker("async.stream.reader").isLeaked() == false getTracker("async.stream.reader").isLeaked() == false