mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-22 21:32:31 +00:00
Add /statusz page to redbean plus other enhancements
redbean improvements: - Explicitly disable corking - Simulate Python regex API for Lua - Send warmup requests in main process on startup - Add Class-A granular IPv4 network classification - Add /statusz page so you can monitor your redbean's health - Fix regressions on OpenBSD/NetBSD caused by recent changes - Plug Authorization header into Lua GetUser and GetPass APIs - Recognize X-Forwarded-{For,Host} from local reverse proxies - Add many additional functions to redbean Lua server page API - Report resource usage of child processes on `/` listing page - Introduce `-a` flag for logging child process resource usage - Introduce `-t MILLIS` flag and `ProgramTimeout(ms)` init API - Introduce `-H "Header: value"` flag and `ProgramHeader(k,v)` API Cosmopolitan Libc improvements: - Make strerror() simpler - Make inet_pton() not depend on sscanf() - Fix OpenExecutable() which broke .data section earlier - Fix stdio in cases where it overflows kernel tty buffer - Fix bugs in crash reporting w/o .com.dbg binary present - Add polyfills for SO_LINGER, SO_RCVTIMEO, and SO_SNDTIMEO - Polyfill TCP_CORK on BSD and XNU using TCP_NOPUSH magnums New netcat clone in examples/nc.c: While testing some of the failure conditions for redbean, I noticed that BusyBox's `nc` command is pretty busted, if you use it as an interactive tool, rather than having it be part of a pipeline. Unfortunately this'll only work on UNIX since Windows doesn't let us poll on stdio and sockets at the same time because I don't think they want tools like this running on their platform. So if you want forbidden fruit, it's here so enjoy it
This commit is contained in:
parent
4effa23528
commit
b107d2709f
163 changed files with 4425 additions and 2104 deletions
|
@ -16,10 +16,11 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/hyperion.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/http.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
size_t n;
|
||||
|
||||
|
@ -27,6 +28,30 @@ TEST(DecodeLatin1, test) {
|
|||
EXPECT_STREQ("", DecodeLatin1(NULL, 0, 0));
|
||||
EXPECT_STREQ("¥atta", DecodeLatin1("\245atta", -1, &n));
|
||||
EXPECT_EQ(6, n);
|
||||
EXPECT_STREQ("\245atta", EncodeLatin1("¥atta", -1, &n, 0));
|
||||
EXPECT_EQ(5, n);
|
||||
}
|
||||
|
||||
TEST(DecodeLatin1, testAbleToImposeCharacterRestrictions) {
|
||||
errno = 0;
|
||||
EXPECT_EQ(0, EncodeLatin1("\200atta", -1, &n, kControlC1));
|
||||
EXPECT_EQ(0, n);
|
||||
EXPECT_EQ(EILSEQ, errno);
|
||||
errno = 0;
|
||||
EXPECT_EQ(0, EncodeLatin1("\002atta", -1, &n, kControlC0));
|
||||
EXPECT_EQ(0, n);
|
||||
EXPECT_EQ(EILSEQ, errno);
|
||||
}
|
||||
|
||||
TEST(EncodeLatin1, roundTrip) {
|
||||
int i;
|
||||
char b[256];
|
||||
for (i = 0; i < 256; ++i) b[i] = i;
|
||||
char *utf8 = DecodeLatin1(b, 256, &n);
|
||||
EXPECT_EQ(384, n);
|
||||
char *lat1 = EncodeLatin1(utf8, n, &n, 0);
|
||||
ASSERT_EQ(256, n);
|
||||
EXPECT_EQ(0, memcmp(b, lat1, 256));
|
||||
}
|
||||
|
||||
TEST(DecodeLatin1, testOom_returnsNullAndSetsSizeToZero) {
|
||||
|
@ -38,4 +63,6 @@ TEST(DecodeLatin1, testOom_returnsNullAndSetsSizeToZero) {
|
|||
BENCH(DecodeLatin1, bench) {
|
||||
EZBENCH2("DecodeLatin1", donothing,
|
||||
DecodeLatin1(kHyperion, kHyperionSize, 0));
|
||||
EZBENCH2("EncodeLatin1", donothing,
|
||||
EncodeLatin1(kHyperion, kHyperionSize, 0, 0));
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/hyperion.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/base64.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
size_t i, n, m;
|
||||
char *p, *q, b[32];
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/http.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
char *p;
|
||||
size_t n;
|
||||
|
|
|
@ -24,10 +24,11 @@
|
|||
#include "net/http/escape.h"
|
||||
|
||||
char *escapehtml(const char *s) {
|
||||
struct EscapeResult r;
|
||||
r = EscapeHtml(s, strlen(s));
|
||||
ASSERT_EQ(strlen(r.data), r.size);
|
||||
return r.data;
|
||||
char *p;
|
||||
size_t n;
|
||||
p = EscapeHtml(s, strlen(s), &n);
|
||||
ASSERT_EQ(strlen(p), n);
|
||||
return p;
|
||||
}
|
||||
|
||||
TEST(escapehtml, test) {
|
||||
|
@ -49,5 +50,5 @@ TEST(escapehtml, testAstralPlanes_doesNothing) {
|
|||
|
||||
BENCH(escapehtml, bench) {
|
||||
EZBENCH2("escapehtml", donothing,
|
||||
free(EscapeHtml(kHyperion, kHyperionSize).data));
|
||||
free(EscapeHtml(kHyperion, kHyperionSize, 0)));
|
||||
}
|
||||
|
|
|
@ -24,10 +24,11 @@
|
|||
#include "net/http/escape.h"
|
||||
|
||||
char *escapejs(const char *s) {
|
||||
struct EscapeResult r;
|
||||
r = EscapeJsStringLiteral(s, strlen(s));
|
||||
ASSERT_EQ(strlen(r.data), r.size);
|
||||
return r.data;
|
||||
char *p;
|
||||
size_t n;
|
||||
p = EscapeJsStringLiteral(s, strlen(s), &n);
|
||||
ASSERT_EQ(strlen(p), n);
|
||||
return p;
|
||||
}
|
||||
|
||||
TEST(EscapeJsStringLiteral, test) {
|
||||
|
@ -53,27 +54,29 @@ TEST(EscapeJsStringLiteral, testBrokenUnicode_sparesInnocentCharacters) {
|
|||
|
||||
void makefile1(void) {
|
||||
FILE *f;
|
||||
struct EscapeResult r;
|
||||
r = EscapeJsStringLiteral(kHyperion, kHyperionSize);
|
||||
char *p;
|
||||
size_t n;
|
||||
p = EscapeJsStringLiteral(kHyperion, kHyperionSize, &n);
|
||||
f = fopen("/tmp/a", "wb");
|
||||
fwrite(r.data, r.size, 1, f);
|
||||
fwrite(p, n, 1, f);
|
||||
fclose(f);
|
||||
free(r.data);
|
||||
free(p);
|
||||
}
|
||||
|
||||
void makefile2(void) {
|
||||
int fd;
|
||||
struct EscapeResult r;
|
||||
r = EscapeJsStringLiteral(kHyperion, kHyperionSize);
|
||||
char *p;
|
||||
size_t n;
|
||||
p = EscapeJsStringLiteral(kHyperion, kHyperionSize, &n);
|
||||
fd = creat("/tmp/a", 0644);
|
||||
write(fd, r.data, r.size);
|
||||
write(fd, p, n);
|
||||
close(fd);
|
||||
free(r.data);
|
||||
free(p);
|
||||
}
|
||||
|
||||
BENCH(EscapeJsStringLiteral, bench) {
|
||||
EZBENCH2("escapejs", donothing,
|
||||
free(EscapeJsStringLiteral(kHyperion, kHyperionSize).data));
|
||||
free(EscapeJsStringLiteral(kHyperion, kHyperionSize, 0)));
|
||||
EZBENCH2("makefile1", donothing, makefile1());
|
||||
EZBENCH2("makefile2", donothing, makefile2());
|
||||
}
|
||||
|
|
|
@ -24,10 +24,11 @@
|
|||
#include "net/http/escape.h"
|
||||
|
||||
char *escapeparam(const char *s) {
|
||||
struct EscapeResult r;
|
||||
r = EscapeParam(s, -1);
|
||||
ASSERT_EQ(strlen(r.data), r.size);
|
||||
return r.data;
|
||||
char *p;
|
||||
size_t n;
|
||||
p = EscapeParam(s, -1, &n);
|
||||
ASSERT_EQ(strlen(p), n);
|
||||
return p;
|
||||
}
|
||||
|
||||
TEST(EscapeParam, test) {
|
||||
|
@ -49,5 +50,5 @@ TEST(EscapeParam, testAstralPlanes_usesUtf8HexEncoding) {
|
|||
|
||||
BENCH(EscapeParam, bench) {
|
||||
EZBENCH2("EscapeParam", donothing,
|
||||
free(EscapeParam(kHyperion, kHyperionSize).data));
|
||||
free(EscapeParam(kHyperion, kHyperionSize, 0)));
|
||||
}
|
||||
|
|
51
test/net/http/hascontrolcodes_test.c
Normal file
51
test/net/http/hascontrolcodes_test.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/hyperion.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
TEST(HasControlCodes, test) {
|
||||
EXPECT_FALSE(
|
||||
HasControlCodes(kHyperion, kHyperionSize, kControlC0 | kControlC1));
|
||||
EXPECT_TRUE(HasControlCodes("hi\1", -1, kControlC0));
|
||||
EXPECT_FALSE(HasControlCodes("hi\1", -1, kControlC1));
|
||||
EXPECT_FALSE(HasControlCodes("hi there", -1, 0));
|
||||
EXPECT_TRUE(HasControlCodes("hi\tthere", -1, kControlWs));
|
||||
}
|
||||
|
||||
TEST(HasControlCodes, testDoesUtf8) {
|
||||
EXPECT_FALSE(HasControlCodes(u8"→", -1, kControlC0 | kControlC1));
|
||||
EXPECT_FALSE(HasControlCodes("\304\200", -1, kControlC0 | kControlC1));
|
||||
EXPECT_TRUE(HasControlCodes("\300\200", -1, kControlC0 | kControlC1));
|
||||
EXPECT_FALSE(HasControlCodes("\300\200", -1, kControlC1));
|
||||
EXPECT_TRUE(HasControlCodes("\302\202", -1, kControlC0 | kControlC1));
|
||||
EXPECT_TRUE(HasControlCodes("\302\202", -1, kControlC1));
|
||||
EXPECT_FALSE(HasControlCodes("\302\202", -1, kControlC0));
|
||||
}
|
||||
|
||||
TEST(HasControlCodes, testHasLatin1FallbackBehavior) {
|
||||
EXPECT_TRUE(HasControlCodes("\202", -1, kControlWs | kControlC1));
|
||||
EXPECT_FALSE(HasControlCodes("\202", -1, kControlC0));
|
||||
}
|
||||
|
||||
BENCH(HasControlCodes, bench) {
|
||||
EZBENCH2("HasControlCodes", donothing,
|
||||
HasControlCodes(kHyperion, kHyperionSize, kControlWs));
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/hyperion.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/http.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
TEST(IndentLines, testEmpty) {
|
||||
char *p;
|
||||
|
|
|
@ -89,8 +89,41 @@ TEST(ParseIp, test) {
|
|||
EXPECT_EQ(-1, ParseIp("hello..example", -1));
|
||||
}
|
||||
|
||||
TEST(ParseForwarded, test) {
|
||||
uint32_t ip = 7;
|
||||
uint16_t port = 7;
|
||||
EXPECT_EQ(-1, ParseForwarded("", -1, &ip, &port));
|
||||
EXPECT_EQ(-1, ParseForwarded("0.0.0.0", -1, &ip, &port));
|
||||
EXPECT_EQ(-1, ParseForwarded("8.8.8.8", -1, &ip, &port));
|
||||
EXPECT_EQ(-1, ParseForwarded("[::1]:123", -1, &ip, &port));
|
||||
EXPECT_EQ(7, ip);
|
||||
EXPECT_EQ(7, port);
|
||||
EXPECT_EQ(0, ParseForwarded("0.0.0.1:123", -1, &ip, &port));
|
||||
EXPECT_EQ(0x00000001, ip);
|
||||
EXPECT_EQ(123, port);
|
||||
EXPECT_EQ(0, ParseForwarded("1.2.3.4:123", -1, &ip, &port));
|
||||
EXPECT_EQ(0x01020304, ip);
|
||||
EXPECT_EQ(123, port);
|
||||
EXPECT_EQ(0, ParseForwarded("128.2.3.4:123", -1, &ip, &port));
|
||||
EXPECT_EQ(0x80020304, ip);
|
||||
EXPECT_EQ(123, port);
|
||||
EXPECT_EQ(0, ParseForwarded("255.255.255.255:123", -1, &ip, &port));
|
||||
EXPECT_EQ(0xFFFFFFFF, ip);
|
||||
EXPECT_EQ(123, port);
|
||||
EXPECT_EQ(0, ParseForwarded("203.0.113.0:123", -1, &ip, &port));
|
||||
EXPECT_EQ(0xcb007100, ip);
|
||||
EXPECT_EQ(123, port);
|
||||
EXPECT_EQ(0, ParseForwarded("203.0.113.42:31337", -1, &ip, &port));
|
||||
EXPECT_EQ(-1, ParseForwarded("...:123", -1, &ip, &port));
|
||||
EXPECT_EQ(-1, ParseForwarded("203.0.113.0:123123123", -1, &ip, &port));
|
||||
}
|
||||
|
||||
BENCH(IsAcceptableHost, bench) {
|
||||
uint32_t ip;
|
||||
uint16_t port;
|
||||
EZBENCH2("IsAcceptableHost 127.0.0.1", donothing,
|
||||
IsAcceptableHost("127.0.0.1", 9));
|
||||
EZBENCH2("IsAcceptablePort 80", donothing, IsAcceptablePort("80", 2));
|
||||
EZBENCH2("ParseForwarded 80", donothing,
|
||||
ParseForwarded("203.0.113.42:31337", 20, &ip, &port));
|
||||
}
|
||||
|
|
|
@ -23,10 +23,12 @@
|
|||
#include "net/http/http.h"
|
||||
|
||||
TEST(IsAcceptablePath, test) {
|
||||
EXPECT_TRUE(IsAcceptablePath("*", 1));
|
||||
EXPECT_TRUE(IsAcceptablePath("/", 1));
|
||||
EXPECT_TRUE(IsAcceptablePath("index.html", 10));
|
||||
EXPECT_TRUE(IsAcceptablePath("/index.html", 11));
|
||||
EXPECT_TRUE(IsAcceptablePath("/index.html", -1));
|
||||
EXPECT_TRUE(IsAcceptablePath("/redbean.png", -1));
|
||||
}
|
||||
|
||||
TEST(IsAcceptablePath, testEmptyString_allowedIfYouLikeImplicitLeadingSlash) {
|
||||
|
@ -88,5 +90,6 @@ TEST(IsAcceptablePath, testOverlongSlashDot_isDetected) {
|
|||
}
|
||||
|
||||
BENCH(IsAcceptablePath, bench) {
|
||||
EZBENCH2("IsAcceptablePath", donothing, IsAcceptablePath("*", 1));
|
||||
EZBENCH2("IsAcceptablePath", donothing, IsAcceptablePath("/index.html", 11));
|
||||
}
|
||||
|
|
91
test/net/http/isreasonablepath_test.c
Normal file
91
test/net/http/isreasonablepath_test.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/http.h"
|
||||
|
||||
TEST(IsReasonablePath, test) {
|
||||
EXPECT_TRUE(IsReasonablePath("/", 1));
|
||||
EXPECT_TRUE(IsReasonablePath("index.html", 10));
|
||||
EXPECT_TRUE(IsReasonablePath("/index.html", 11));
|
||||
EXPECT_TRUE(IsReasonablePath("/index.html", -1));
|
||||
EXPECT_TRUE(IsReasonablePath("/redbean.png", -1));
|
||||
}
|
||||
|
||||
TEST(IsReasonablePath, testEmptyString_allowedIfYouLikeImplicitLeadingSlash) {
|
||||
EXPECT_TRUE(IsReasonablePath(0, 0));
|
||||
EXPECT_TRUE(IsReasonablePath(0, -1));
|
||||
EXPECT_TRUE(IsReasonablePath("", 0));
|
||||
}
|
||||
|
||||
TEST(IsReasonablePath, testHiddenFiles_areAllowed) {
|
||||
EXPECT_TRUE(IsReasonablePath("/.index.html", 12));
|
||||
EXPECT_TRUE(IsReasonablePath("/x/.index.html", 14));
|
||||
}
|
||||
|
||||
TEST(IsReasonablePath, testDoubleSlash_isAllowed) {
|
||||
EXPECT_TRUE(IsReasonablePath("//", 2));
|
||||
EXPECT_TRUE(IsReasonablePath("foo//", 5));
|
||||
EXPECT_TRUE(IsReasonablePath("/foo//", 6));
|
||||
EXPECT_TRUE(IsReasonablePath("/foo//bar", 9));
|
||||
}
|
||||
|
||||
TEST(IsReasonablePath, testNoncanonicalDirectories_areForbidden) {
|
||||
EXPECT_FALSE(IsReasonablePath(".", 1));
|
||||
EXPECT_FALSE(IsReasonablePath("..", 2));
|
||||
EXPECT_FALSE(IsReasonablePath("/.", 2));
|
||||
EXPECT_FALSE(IsReasonablePath("/..", 3));
|
||||
EXPECT_FALSE(IsReasonablePath("./", 2));
|
||||
EXPECT_FALSE(IsReasonablePath("../", 3));
|
||||
EXPECT_FALSE(IsReasonablePath("/./", 3));
|
||||
EXPECT_FALSE(IsReasonablePath("/../", 4));
|
||||
EXPECT_FALSE(IsReasonablePath("x/.", 3));
|
||||
EXPECT_FALSE(IsReasonablePath("x/..", 4));
|
||||
EXPECT_FALSE(IsReasonablePath("x/./", 4));
|
||||
EXPECT_FALSE(IsReasonablePath("x/../", 5));
|
||||
EXPECT_FALSE(IsReasonablePath("/x/./", 5));
|
||||
EXPECT_FALSE(IsReasonablePath("/x/../", 6));
|
||||
}
|
||||
|
||||
TEST(IsReasonablePath, testNoncanonicalWindowsDirs_areForbidden) {
|
||||
EXPECT_FALSE(IsReasonablePath(".", 1));
|
||||
EXPECT_FALSE(IsReasonablePath("..", 2));
|
||||
EXPECT_FALSE(IsReasonablePath("\\.", 2));
|
||||
EXPECT_FALSE(IsReasonablePath("\\..", 3));
|
||||
EXPECT_FALSE(IsReasonablePath(".\\", 2));
|
||||
EXPECT_FALSE(IsReasonablePath("..\\", 3));
|
||||
EXPECT_FALSE(IsReasonablePath("\\.\\", 3));
|
||||
EXPECT_FALSE(IsReasonablePath("\\..\\", 4));
|
||||
EXPECT_FALSE(IsReasonablePath("x\\.", 3));
|
||||
EXPECT_FALSE(IsReasonablePath("x\\..", 4));
|
||||
EXPECT_FALSE(IsReasonablePath("x\\.\\", 4));
|
||||
EXPECT_FALSE(IsReasonablePath("x\\..\\", 5));
|
||||
EXPECT_FALSE(IsReasonablePath("\\x\\.\\", 5));
|
||||
EXPECT_FALSE(IsReasonablePath("\\x\\..\\", 6));
|
||||
}
|
||||
|
||||
TEST(IsReasonablePath, testOverlongSlashDot_isDetected) {
|
||||
EXPECT_FALSE(IsReasonablePath("/\300\256", 3)); /* /. */
|
||||
EXPECT_TRUE(IsReasonablePath("/\300\257", 3)); /* // */
|
||||
EXPECT_FALSE(IsReasonablePath("\300\256\300\256", 4)); /* .. */
|
||||
}
|
||||
|
||||
BENCH(IsReasonablePath, bench) {
|
||||
EZBENCH2("IsReasonablePath", donothing, IsReasonablePath("/index.html", 11));
|
||||
}
|
|
@ -242,7 +242,7 @@ Accept: text/plain\r\n\
|
|||
EXPECT_STREQ("text/plain", gc(slice(m, req->xheaders.p[0].v)));
|
||||
}
|
||||
|
||||
TEST(HeaderHasSubstring, testHeaderSpansMultipleLines) {
|
||||
TEST(HeaderHas, testHeaderSpansMultipleLines) {
|
||||
static const char m[] = "\
|
||||
GET / HTTP/1.1\r\n\
|
||||
Accept-Encoding: deflate\r\n\
|
||||
|
@ -250,20 +250,20 @@ ACCEPT-ENCODING: gzip\r\n\
|
|||
ACCEPT-encoding: bzip2\r\n\
|
||||
\r\n";
|
||||
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
||||
EXPECT_TRUE(HeaderHasSubstring(req, m, kHttpAcceptEncoding, "gzip", -1));
|
||||
EXPECT_TRUE(HeaderHasSubstring(req, m, kHttpAcceptEncoding, "deflate", -1));
|
||||
EXPECT_FALSE(HeaderHasSubstring(req, m, kHttpAcceptEncoding, "funzip", -1));
|
||||
EXPECT_TRUE(HeaderHas(req, m, kHttpAcceptEncoding, "gzip", -1));
|
||||
EXPECT_TRUE(HeaderHas(req, m, kHttpAcceptEncoding, "deflate", -1));
|
||||
EXPECT_FALSE(HeaderHas(req, m, kHttpAcceptEncoding, "funzip", -1));
|
||||
}
|
||||
|
||||
TEST(HeaderHasSubstring, testHeaderOnSameLIne) {
|
||||
TEST(HeaderHas, testHeaderOnSameLIne) {
|
||||
static const char m[] = "\
|
||||
GET / HTTP/1.1\r\n\
|
||||
Accept-Encoding: deflate, gzip, bzip2\r\n\
|
||||
\r\n";
|
||||
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
||||
EXPECT_TRUE(HeaderHasSubstring(req, m, kHttpAcceptEncoding, "gzip", -1));
|
||||
EXPECT_TRUE(HeaderHasSubstring(req, m, kHttpAcceptEncoding, "deflate", -1));
|
||||
EXPECT_FALSE(HeaderHasSubstring(req, m, kHttpAcceptEncoding, "funzip", -1));
|
||||
EXPECT_TRUE(HeaderHas(req, m, kHttpAcceptEncoding, "gzip", -1));
|
||||
EXPECT_TRUE(HeaderHas(req, m, kHttpAcceptEncoding, "deflate", -1));
|
||||
EXPECT_FALSE(HeaderHas(req, m, kHttpAcceptEncoding, "funzip", -1));
|
||||
}
|
||||
|
||||
TEST(ParseHttpRequest, testHeaderValuesWithWhitespace_getsTrimmed) {
|
||||
|
@ -273,6 +273,7 @@ User-Agent: \t hi there \t \r\n\
|
|||
\r\n";
|
||||
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
||||
EXPECT_STREQ("hi there", gc(slice(m, req->headers[kHttpUserAgent])));
|
||||
EXPECT_STREQ("*", gc(slice(m, req->uri)));
|
||||
}
|
||||
|
||||
TEST(ParseHttpRequest, testAbsentHost_setsSliceToZero) {
|
||||
|
@ -373,7 +374,7 @@ BENCH(ParseHttpRequest, bench) {
|
|||
EZBENCH2("DoUnstandardChromeRequest", donothing, DoUnstandardChromeRequest());
|
||||
}
|
||||
|
||||
BENCH(HeaderHasSubstring, bench) {
|
||||
BENCH(HeaderHas, bench) {
|
||||
static const char m[] = "\
|
||||
GET / HTTP/1.1\r\n\
|
||||
X-In-Your-Way-A: a\r\n\
|
||||
|
@ -384,12 +385,12 @@ ACCEPT-ENCODING: gzip\r\n\
|
|||
ACCEPT-encoding: bzip2\r\n\
|
||||
\r\n";
|
||||
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
||||
EZBENCH2("HeaderHasSubstring text/plain", donothing,
|
||||
HeaderHasSubstring(req, m, kHttpAccept, "text/plain", 7));
|
||||
EZBENCH2("HeaderHasSubstring deflate", donothing,
|
||||
HeaderHasSubstring(req, m, kHttpAcceptEncoding, "deflate", 7));
|
||||
EZBENCH2("HeaderHasSubstring gzip", donothing,
|
||||
HeaderHasSubstring(req, m, kHttpAcceptEncoding, "gzip", 4));
|
||||
EZBENCH2("HeaderHas text/plain", donothing,
|
||||
HeaderHas(req, m, kHttpAccept, "text/plain", 7));
|
||||
EZBENCH2("HeaderHas deflate", donothing,
|
||||
HeaderHas(req, m, kHttpAcceptEncoding, "deflate", 7));
|
||||
EZBENCH2("HeaderHas gzip", donothing,
|
||||
HeaderHas(req, m, kHttpAcceptEncoding, "gzip", 4));
|
||||
EZBENCH2("IsMimeType", donothing,
|
||||
IsMimeType("text/plain; charset=utf-8", -1, "text/plain"));
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/hyperion.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/http.h"
|
||||
#include "net/http/url.h"
|
||||
|
||||
TEST(ParseUrl, testEmpty) {
|
||||
|
@ -160,8 +161,7 @@ TEST(ParseUrl, testUrl) {
|
|||
ASSERT_EQ('b', h.user.p[0]);
|
||||
ASSERT_EQ(1, h.pass.n);
|
||||
ASSERT_EQ('B', h.pass.p[0]);
|
||||
ASSERT_EQ(1, h.host.n);
|
||||
ASSERT_EQ('c', h.host.p[0]);
|
||||
ASSERT_STREQ("c", gc(strndup(h.host.p, h.host.n)));
|
||||
ASSERT_EQ(1, h.port.n);
|
||||
ASSERT_EQ('C', h.port.p[0]);
|
||||
ASSERT_EQ(2, h.path.n);
|
||||
|
@ -380,6 +380,16 @@ TEST(ParseHost, testObviouslyIllegalIpLiteral_getsTreatedAsRegName) {
|
|||
ASSERT_STREQ("//vf.%3A%3A1%00", gc(EncodeUrl(&h, 0)));
|
||||
}
|
||||
|
||||
TEST(ParseHost, testUnclosedIpv6_doesntSetPort) {
|
||||
struct Url h = {0};
|
||||
gc(ParseHost("2001:db8:cafe::17", -1, &h));
|
||||
gc(h.params.p);
|
||||
ASSERT_STREQ("2001:db8:cafe::17", gc(strndup(h.host.p, h.host.n)));
|
||||
ASSERT_EQ(0, h.port.n);
|
||||
ASSERT_EQ(0, h.port.p);
|
||||
ASSERT_STREQ("//2001%3Adb8%3Acafe%3A%3A17", gc(EncodeUrl(&h, 0)));
|
||||
}
|
||||
|
||||
TEST(EncodeUrl, testHostPortPlacedInHostField_ungoodIdea) {
|
||||
struct Url h = {0};
|
||||
h.host.n = strlen("foo.example:80");
|
||||
|
@ -696,6 +706,8 @@ BENCH(ParseUrl, bench) {
|
|||
free(ParseUrl("a://b@c/?zd#f", -1, &h));
|
||||
free(h.params.p);
|
||||
}));
|
||||
EZBENCH2("ParseHost", donothing, free(ParseHost("127.0.0.1:34832", 15, &h)));
|
||||
EZBENCH2("ParseIp", donothing, ParseIp("127.0.0.1", 9));
|
||||
}
|
||||
|
||||
BENCH(EncodeUrl, bench) {
|
||||
|
|
40
test/net/http/underlong_test.c
Normal file
40
test/net/http/underlong_test.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/hyperion.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
TEST(Underlong, test) {
|
||||
size_t n;
|
||||
EXPECT_BINEQ(u"e e", gc(Underlong("e\300\200e", -1, &n)));
|
||||
EXPECT_EQ(3, n);
|
||||
}
|
||||
|
||||
TEST(Underlong, testNormalText) {
|
||||
size_t n;
|
||||
EXPECT_STREQ(kHyperion, gc(Underlong(kHyperion, kHyperionSize, &n)));
|
||||
EXPECT_EQ(kHyperionSize, n);
|
||||
}
|
||||
|
||||
BENCH(Underlong, bench) {
|
||||
EZBENCH2("Underlong", donothing,
|
||||
free(Underlong(kHyperion, kHyperionSize, 0)));
|
||||
}
|
|
@ -16,24 +16,34 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/hyperion.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/http.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
TEST(VisualizeControlCodes, test) {
|
||||
EXPECT_STREQ("hello", VisualizeControlCodes("hello", -1, 0));
|
||||
EXPECT_STREQ("hello\r\n", VisualizeControlCodes("hello\r\n", -1, 0));
|
||||
EXPECT_STREQ("hello␁␂␡", VisualizeControlCodes("hello\1\2\177", -1, 0));
|
||||
EXPECT_STREQ("hello\\u0085", VisualizeControlCodes("hello\302\205", -1, 0));
|
||||
EXPECT_STREQ("hello", gc(VisualizeControlCodes("hello", -1, 0)));
|
||||
EXPECT_STREQ("hello\r\n", gc(VisualizeControlCodes("hello\r\n", -1, 0)));
|
||||
EXPECT_STREQ("hello␁␂␡", gc(VisualizeControlCodes("hello\1\2\177", -1, 0)));
|
||||
EXPECT_STREQ("hello\\u0085",
|
||||
gc(VisualizeControlCodes("hello\302\205", -1, 0)));
|
||||
}
|
||||
|
||||
TEST(VisualizeControlCodes, testOom_returnsNullAndSetsSizeToZero) {
|
||||
size_t n = 31337;
|
||||
EXPECT_EQ(NULL, VisualizeControlCodes("hello", 0x1000000000000, &n));
|
||||
EXPECT_EQ(NULL, gc(VisualizeControlCodes("hello", 0x1000000000000, &n)));
|
||||
EXPECT_EQ(0, n);
|
||||
}
|
||||
|
||||
TEST(VisualizeControlCodes, testWeirdHttp) {
|
||||
size_t n = 31337;
|
||||
char *p, B[] = "\0GET /redbean.lua\n\n";
|
||||
ASSERT_NE(0, (p = gc(VisualizeControlCodes(B, sizeof(B), &n))));
|
||||
EXPECT_STREQ("\"␀GET /redbean.lua\\n\\n␀\"", gc(xasprintf("%`'.*s", n, p)));
|
||||
}
|
||||
|
||||
BENCH(VisualizeControlCodes, bench) {
|
||||
EZBENCH2("VisualizeControlCodes", donothing,
|
||||
free(VisualizeControlCodes(kHyperion, kHyperionSize, 0)));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue