Streamline hardening helpers and expand coverage

This commit is contained in:
udo
2026-05-21 10:12:11 +00:00
parent 0d8b74930c
commit 41e9ca219f
14 changed files with 158 additions and 70 deletions
+4
View File
@@ -30,6 +30,8 @@ RENDER(Request& context)
String uri_input = "alpha beta/?x=1&y=2";
String encoded = uri_encode(uri_input);
String decoded = uri_decode(encoded);
String malformed_percent = uri_decode("% %A %GG ok%20done");
URI empty_uri = parse_uri("");
String generated_session = session_id_create();
String query_dump = var_dump(query);
String set_cookie_dump = var_dump(context.set_cookies);
@@ -39,6 +41,8 @@ RENDER(Request& context)
site_tests_page_start("HTTP And Session", "Request helpers, cookies, headers, URI parsing, and session lifecycle checks.");
check("uri_encode() / uri_decode()", decoded == uri_input, encoded + " => " + decoded);
check("uri_decode() malformed percent literals", malformed_percent == "% %A %GG ok done", malformed_percent);
check("parse_uri() empty input", empty_uri.parts["raw"] == "", var_dump(empty_uri));
check("parse_query()", query["alpha"] == "1" && query["beta"] == "two words", query_dump);
check("set_cookie()", set_cookie_dump.find("site-tests-cookie") != String::npos && set_cookie_dump.find("cookie-value") != String::npos && set_cookie_dump.find("HttpOnly") != String::npos && set_cookie_dump.find("SameSite=Lax") != String::npos, set_cookie_dump);
check("response header mutation", context.header["X-Site-Tests"] == "http-suite", header_dump);
+3
View File
@@ -1,6 +1,9 @@
RENDER(Request& context)
{
context.header["X-UCE-Security-Test"] = "safe\r\nX-UCE-Injected: nope";
context.header["Bad\r\nX-UCE-Injected-Name"] = "nope";
context.set_cookies.push_back("Set-Cookie: raw=1\r\nX-UCE-Cookie-Injected: nope");
redirect("/tests/index.uce\r\nX-UCE-Redirect-Injected: nope", 299);
context.set_status(299, "OK\r\nX-UCE-Status-Injected: nope");
print("security header sanitizer test");
}
+14 -8
View File
@@ -31,10 +31,11 @@ RENDER(Request& context)
bool write_ok = socket_write(sockfd, "GET /tests/index.uce HTTP/1.0\r\nHost: uce.openfu.com\r\n\r\n");
String response = socket_read(sockfd, 4096, 2);
socket_close(sockfd);
bool has_nul = response.find(String("\0", 1)) != String::npos;
mark(
"socket_connect() / socket_write() / socket_read()",
(write_ok && response.find("200 OK") != String::npos) ? "pass" : "fail",
response.substr(0, response.length() > 220 ? 220 : response.length())
(write_ok && response.find("200 OK") != String::npos && !has_nul) ? "pass" : "fail",
response.substr(0, response.length() > 220 ? 220 : response.length()) + (has_nul ? " [unexpected NUL]" : "")
);
}
else
@@ -50,17 +51,22 @@ RENDER(Request& context)
bool write_ok = socket_write(custom_http_sockfd, "GET /custom-test?alpha=1 HTTP/1.0\r\nHost: localhost\r\n\r\n");
String response = socket_read(custom_http_sockfd, 4096, 2);
socket_close(custom_http_sockfd);
server_stop("site-tests-http");
bool stopped = server_stop("site-tests-http");
usleep(200000);
u64 stopped_sockfd = socket_connect("127.0.0.1", 19091);
bool listener_closed = stopped_sockfd == 0;
if(stopped_sockfd != 0)
socket_close(stopped_sockfd);
mark(
"server_start_http() / SERVE_HTTP:named",
(custom_http_pid != 0 && write_ok && response.find("custom-http-named") != String::npos && response.find("query=alpha=1") != String::npos) ? "pass" : "fail",
response.substr(0, response.length() > 260 ? 260 : response.length())
"server_start_http() / SERVE_HTTP:named / server_stop()",
(custom_http_pid != 0 && write_ok && response.find("custom-http-named") != String::npos && response.find("query=alpha=1") != String::npos && stopped && listener_closed) ? "pass" : "fail",
response.substr(0, response.length() > 260 ? 260 : response.length()) + " stopped=" + (stopped ? "true" : "false") + " listener_closed=" + (listener_closed ? "true" : "false")
);
}
else
{
server_stop("site-tests-http");
mark("server_start_http() / SERVE_HTTP:named", "fail", "socket_connect(127.0.0.1, 19091) returned 0; pid=" + std::to_string(custom_http_pid));
bool stopped = server_stop("site-tests-http");
mark("server_start_http() / SERVE_HTTP:named / server_stop()", "fail", "socket_connect(127.0.0.1, 19091) returned 0; pid=" + std::to_string(custom_http_pid) + " stopped=" + (stopped ? "true" : "false"));
}
u64 memfd = memcache_connect();
+31 -1
View File
@@ -62,11 +62,41 @@ RENDER(Request& context)
}
check("zip_create() rejects unsafe names", unsafe_rejected, "absolute member name rejected");
bool nul_name_rejected = false;
try
{
DTree unsafe_entries;
String nul_name = "prefix";
nul_name.push_back((char)0x00);
nul_name += "suffix.txt";
unsafe_entries[nul_name] = "bad";
zip_create(path_join(base, "nul-name.zip"), unsafe_entries);
}
catch(std::exception& e)
{
nul_name_rejected = contains(e.what(), "unsafe");
}
check("zip_create() rejects NUL entry names", nul_name_rejected, "embedded NUL member name rejected");
String binary_source("UCE", 3);
binary_source.push_back((char)0x00);
binary_source += "binary";
binary_source.push_back((char)0xff);
binary_source += "payload";
DTree binary_entries;
binary_entries["binary.dat"] = binary_source;
String binary_archive = path_join(base, "binary.zip");
bool binary_created = zip_create(binary_archive, binary_entries);
String binary_zip_roundtrip = zip_read(binary_archive, "binary.dat");
check("zip binary-safe String payload", binary_created && binary_zip_roundtrip == binary_source && binary_zip_roundtrip.size() == binary_source.size(), "bytes=" + std::to_string((u64)binary_zip_roundtrip.size()));
String gz_source = "UCE gzip payload\nline two\n";
String gz_body = gz_compress(gz_source);
String gz_roundtrip = gz_uncompress(gz_body);
String gz_binary_body = gz_compress(binary_source);
String gz_binary_roundtrip = gz_uncompress(gz_binary_body);
check("gz_compress()", gz_body.size() > gz_source.size() && (u8)gz_body[0] == 0x1f && (u8)gz_body[1] == 0x8b, "bytes=" + std::to_string((u64)gz_body.size()));
check("gz_uncompress()", gz_roundtrip == gz_source, gz_roundtrip);
check("gz_uncompress()", gz_roundtrip == gz_source && gz_binary_roundtrip == binary_source && gz_binary_roundtrip.size() == binary_source.size(), "text=" + gz_roundtrip + ", binary bytes=" + std::to_string((u64)gz_binary_roundtrip.size()));
bool bad_gz_rejected = false;
try