mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-25 12:14:41 +00:00
Resolve #2347
This commit is contained in:
1 parent
8b4146324f
commit
5d717e6d91
3 files changed
+75
-3
No files matched your search
@@ -9943,8 +9943,10 @@ inline bool Server::check_if_not_modified(const Request &req, Response &res,
|
|||||||
// simplified implementation requires exact matches.
|
// simplified implementation requires exact matches.
|
||||||
auto ret = detail::split_find(val.data(), val.data() + val.size(), ',',
|
auto ret = detail::split_find(val.data(), val.data() + val.size(), ',',
|
||||||
[&](const char *b, const char *e) {
|
[&](const char *b, const char *e) {
|
||||||
return std::equal(b, e, "*") ||
|
auto seg_len = static_cast<size_t>(e - b);
|
||||||
std::equal(b, e, etag.begin());
|
return (seg_len == 1 && *b == '*') ||
|
||||||
|
(seg_len == etag.size() &&
|
||||||
|
std::equal(b, e, etag.begin()));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
CXX = clang++
|
CXX = clang++
|
||||||
CXXFLAGS = -g -std=c++11 -I. -Wall -Wextra -Wtype-limits -Wconversion -Wshadow $(EXTRA_CXXFLAGS) -DCPPHTTPLIB_USE_NON_BLOCKING_GETADDRINFO # -fno-exceptions -DCPPHTTPLIB_NO_EXCEPTIONS -fsanitize=address
|
CXXFLAGS = -g -std=c++11 -I. -Wall -Wextra -Wtype-limits -Wconversion -Wshadow $(EXTRA_CXXFLAGS) -DCPPHTTPLIB_USE_NON_BLOCKING_GETADDRINFO -fsanitize=address # -fno-exceptions -DCPPHTTPLIB_NO_EXCEPTIONS
|
||||||
|
|
||||||
ifneq ($(OS), Windows_NT)
|
ifneq ($(OS), Windows_NT)
|
||||||
UNAME_S := $(shell uname -s)
|
UNAME_S := $(shell uname -s)
|
||||||
|
|||||||
@@ -13730,6 +13730,76 @@ TEST(ETagTest, StaticFileETagIfNoneMatchStarNotFound) {
|
|||||||
t.join();
|
t.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ETagTest, IfNoneMatchBoundaryCheck) {
|
||||||
|
using namespace httplib;
|
||||||
|
|
||||||
|
// Create a test file
|
||||||
|
const char *fname = "etag_boundary_testfile.txt";
|
||||||
|
const char *content = "boundary-test";
|
||||||
|
{
|
||||||
|
std::ofstream ofs(fname);
|
||||||
|
ofs << content;
|
||||||
|
ASSERT_TRUE(ofs.good());
|
||||||
|
}
|
||||||
|
|
||||||
|
Server svr;
|
||||||
|
svr.set_mount_point("/static", ".");
|
||||||
|
auto t = std::thread([&]() { svr.listen("localhost", PORT); });
|
||||||
|
svr.wait_until_ready();
|
||||||
|
|
||||||
|
Client cli(HOST, PORT);
|
||||||
|
|
||||||
|
// Get the actual ETag
|
||||||
|
auto res1 = cli.Get("/static/etag_boundary_testfile.txt");
|
||||||
|
ASSERT_TRUE(res1);
|
||||||
|
ASSERT_EQ(200, res1->status);
|
||||||
|
ASSERT_TRUE(res1->has_header("ETag"));
|
||||||
|
std::string etag = res1->get_header_value("ETag");
|
||||||
|
|
||||||
|
// Test 1: Very long ETag value (longer than actual ETag)
|
||||||
|
// Should NOT match and return 200 (not trigger out-of-bounds read)
|
||||||
|
Headers h1 = {{"If-None-Match", "W/"
|
||||||
|
"\"very-long-etag-value-that-is-much-longer-"
|
||||||
|
"than-the-actual-etag-value\""}};
|
||||||
|
auto res2 = cli.Get("/static/etag_boundary_testfile.txt", h1);
|
||||||
|
ASSERT_TRUE(res2);
|
||||||
|
EXPECT_EQ(200, res2->status); // Should not match
|
||||||
|
|
||||||
|
// Test 2: Long string followed by wildcard
|
||||||
|
// Should match on "*" and return 304 (without out-of-bounds read on the long
|
||||||
|
// string)
|
||||||
|
Headers h2 = {{"If-None-Match", "W/\"another-very-long-value\", *"}};
|
||||||
|
auto res3 = cli.Get("/static/etag_boundary_testfile.txt", h2);
|
||||||
|
ASSERT_TRUE(res3);
|
||||||
|
EXPECT_EQ(304, res3->status); // Should match on "*"
|
||||||
|
|
||||||
|
// Test 3: Wildcard followed by long string
|
||||||
|
// Should match on "*" immediately and return 304
|
||||||
|
Headers h3 = {{"If-None-Match", "*, W/\"long-value-after-wildcard\""}};
|
||||||
|
auto res4 = cli.Get("/static/etag_boundary_testfile.txt", h3);
|
||||||
|
ASSERT_TRUE(res4);
|
||||||
|
EXPECT_EQ(304, res4->status); // Should match on "*"
|
||||||
|
|
||||||
|
// Test 4: Multiple long non-matching values
|
||||||
|
// Should NOT match and return 200 (test that all comparisons are safe)
|
||||||
|
Headers h4 = {{"If-None-Match", "W/\"first-long-non-matching-value\", "
|
||||||
|
"W/\"second-long-non-matching-value\", "
|
||||||
|
"W/\"third-long-non-matching-value\""}};
|
||||||
|
auto res5 = cli.Get("/static/etag_boundary_testfile.txt", h4);
|
||||||
|
ASSERT_TRUE(res5);
|
||||||
|
EXPECT_EQ(200, res5->status); // Should not match
|
||||||
|
|
||||||
|
// Test 5: Single character that is not "*" (edge case)
|
||||||
|
Headers h5 = {{"If-None-Match", "X"}};
|
||||||
|
auto res6 = cli.Get("/static/etag_boundary_testfile.txt", h5);
|
||||||
|
ASSERT_TRUE(res6);
|
||||||
|
EXPECT_EQ(200, res6->status); // Should not match
|
||||||
|
|
||||||
|
svr.stop();
|
||||||
|
t.join();
|
||||||
|
std::remove(fname);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ETagTest, LastModifiedAndIfModifiedSince) {
|
TEST(ETagTest, LastModifiedAndIfModifiedSince) {
|
||||||
using namespace httplib;
|
using namespace httplib;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user