Compare commits
10 Commits
f00b01cbae
...
1c40a3875b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c40a3875b | ||
|
|
e82531d7c2 | ||
|
|
a66edc294d | ||
|
|
92b0b3b4b4 | ||
|
|
921b8247b5 | ||
|
|
a6e3ce5e59 | ||
|
|
0d64ed947d | ||
|
|
a47a2bf875 | ||
|
|
5614c42f1c | ||
|
|
b84078d02e |
104
CVE-2025-0825.patch
Normal file
104
CVE-2025-0825.patch
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
From 9c36aae4b73e2b6e493f4133e4173103c9266289 Mon Sep 17 00:00:00 2001
|
||||||
|
From: yhirose <yuji.hirose.bug@gmail.com>
|
||||||
|
Date: Thu, 16 Jan 2025 00:04:17 -0500
|
||||||
|
Subject: [PATCH] Fix HTTP Response Splitting Vulnerability
|
||||||
|
|
||||||
|
---
|
||||||
|
httplib.h | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||||
|
1 file changed, 59 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/httplib.h b/httplib.h
|
||||||
|
index 5a4b64a..86a7452 100644
|
||||||
|
--- a/httplib.h
|
||||||
|
+++ b/httplib.h
|
||||||
|
@@ -2159,6 +2159,60 @@ private:
|
||||||
|
void *addr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
+// NOTE: https://www.rfc-editor.org/rfc/rfc9110#section-5
|
||||||
|
+namespace fields {
|
||||||
|
+
|
||||||
|
+inline bool is_token_char(char c) {
|
||||||
|
+ return std::isalnum(c) || c == '!' || c == '#' || c == '$' || c == '%' ||
|
||||||
|
+ c == '&' || c == '\'' || c == '*' || c == '+' || c == '-' ||
|
||||||
|
+ c == '.' || c == '^' || c == '_' || c == '`' || c == '|' || c == '~';
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+inline bool is_token(const std::string &s) {
|
||||||
|
+ if (s.empty()) { return false; }
|
||||||
|
+ for (auto c : s) {
|
||||||
|
+ if (!is_token_char(c)) { return false; }
|
||||||
|
+ }
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+inline bool is_field_name(const std::string &s) { return is_token(s); }
|
||||||
|
+
|
||||||
|
+inline bool is_vchar(char c) { return c >= 33 && c <= 126; }
|
||||||
|
+
|
||||||
|
+inline bool is_obs_text(char c) { return 128 <= static_cast<unsigned char>(c); }
|
||||||
|
+
|
||||||
|
+inline bool is_field_vchar(char c) { return is_vchar(c) || is_obs_text(c); }
|
||||||
|
+
|
||||||
|
+inline bool is_field_content(const std::string &s) {
|
||||||
|
+ if (s.empty()) { return false; }
|
||||||
|
+
|
||||||
|
+ if (s.size() == 1) {
|
||||||
|
+ return is_field_vchar(s[0]);
|
||||||
|
+ } else if (s.size() == 2) {
|
||||||
|
+ return is_field_vchar(s[0]) && is_field_vchar(s[1]);
|
||||||
|
+ } else {
|
||||||
|
+ size_t i = 0;
|
||||||
|
+
|
||||||
|
+ if (!is_field_vchar(s[i])) { return false; }
|
||||||
|
+ i++;
|
||||||
|
+
|
||||||
|
+ while (i < s.size() - 1) {
|
||||||
|
+ auto c = s[i++];
|
||||||
|
+ if (c == ' ' || c == '\t' || is_field_vchar(c)) {
|
||||||
|
+ } else {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return is_field_vchar(s[i]);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+inline bool is_field_value(const std::string &s) { return is_field_content(s); }
|
||||||
|
+
|
||||||
|
+}; // namespace fields
|
||||||
|
+
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
@@ -5118,7 +5172,8 @@ inline size_t Request::get_header_value_count(const std::string &key) const {
|
||||||
|
|
||||||
|
inline void Request::set_header(const std::string &key,
|
||||||
|
const std::string &val) {
|
||||||
|
- if (!detail::has_crlf(key) && !detail::has_crlf(val)) {
|
||||||
|
+ if (detail::fields::is_field_name(key) &&
|
||||||
|
+ detail::fields::is_field_value(val)) {
|
||||||
|
headers.emplace(key, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -5183,13 +5238,14 @@ inline size_t Response::get_header_value_count(const std::string &key) const {
|
||||||
|
|
||||||
|
inline void Response::set_header(const std::string &key,
|
||||||
|
const std::string &val) {
|
||||||
|
- if (!detail::has_crlf(key) && !detail::has_crlf(val)) {
|
||||||
|
+ if (detail::fields::is_field_name(key) &&
|
||||||
|
+ detail::fields::is_field_value(val)) {
|
||||||
|
headers.emplace(key, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Response::set_redirect(const std::string &url, int stat) {
|
||||||
|
- if (!detail::has_crlf(url)) {
|
||||||
|
+ if (detail::fields::is_field_value(url)) {
|
||||||
|
set_header("Location", url);
|
||||||
|
if (300 <= stat && stat < 400) {
|
||||||
|
this->status = stat;
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
||||||
107
CVE-2025-46728.patch
Normal file
107
CVE-2025-46728.patch
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
From 7b752106ac42bd5b907793950d9125a0972c8e8e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ville Vesilehto <ville@vesilehto.fi>
|
||||||
|
Date: Sat, 3 May 2025 11:39:01 +0300
|
||||||
|
Subject: [PATCH] Merge commit from fork
|
||||||
|
|
||||||
|
* fix(parser): Limit line length in getline
|
||||||
|
|
||||||
|
Prevents potential infinite loop and memory exhaustion in
|
||||||
|
stream_line_reader::getline by enforcing max line length.
|
||||||
|
|
||||||
|
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
|
||||||
|
|
||||||
|
* fix: increase default max line length to 32k
|
||||||
|
|
||||||
|
LONG_QUERY_VALUE test is set at 25k.
|
||||||
|
|
||||||
|
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
|
||||||
|
|
||||||
|
* test(client): expect read error with too long query
|
||||||
|
|
||||||
|
Adds a test case (`TooLongQueryValue`) to verify client behavior
|
||||||
|
when the request URI is excessively long, exceeding
|
||||||
|
`CPPHTTPLIB_MAX_LINE_LENGTH`. In this scenario, the server is
|
||||||
|
expected to reset the connection.
|
||||||
|
|
||||||
|
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
|
||||||
|
|
||||||
|
---------
|
||||||
|
|
||||||
|
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
|
||||||
|
|
||||||
|
Origin: https://github.com/yhirose/cpp-httplib/commit/7b752106ac42bd5b907793950d9125a0972c8e8e
|
||||||
|
---
|
||||||
|
httplib.h | 9 +++++++++
|
||||||
|
test/test.cc | 15 +++++++++++++++
|
||||||
|
2 files changed, 24 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/httplib.h b/httplib.h
|
||||||
|
index 86a7452..b13f7b6 100644
|
||||||
|
--- a/httplib.h
|
||||||
|
+++ b/httplib.h
|
||||||
|
@@ -113,6 +113,10 @@
|
||||||
|
#define CPPHTTPLIB_LISTEN_BACKLOG 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#ifndef CPPHTTPLIB_MAX_LINE_LENGTH
|
||||||
|
+#define CPPHTTPLIB_MAX_LINE_LENGTH 32768
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Headers
|
||||||
|
*/
|
||||||
|
@@ -2559,6 +2563,11 @@ inline bool stream_line_reader::getline() {
|
||||||
|
glowable_buffer_.clear();
|
||||||
|
|
||||||
|
for (size_t i = 0;; i++) {
|
||||||
|
+ if (size() >= CPPHTTPLIB_MAX_LINE_LENGTH) {
|
||||||
|
+ // Treat exceptionally long lines as an error to
|
||||||
|
+ // prevent infinite loops/memory exhaustion
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
char byte;
|
||||||
|
auto n = strm_.read(&byte, 1);
|
||||||
|
|
||||||
|
diff --git a/test/test.cc b/test/test.cc
|
||||||
|
index e702e36..eefa33b 100644
|
||||||
|
--- a/test/test.cc
|
||||||
|
+++ b/test/test.cc
|
||||||
|
@@ -33,6 +33,9 @@ const int PORT = 1234;
|
||||||
|
const string LONG_QUERY_VALUE = string(25000, '@');
|
||||||
|
const string LONG_QUERY_URL = "/long-query-value?key=" + LONG_QUERY_VALUE;
|
||||||
|
|
||||||
|
+const string TOO_LONG_QUERY_VALUE = string(35000, '@');
|
||||||
|
+const string TOO_LONG_QUERY_URL = "/too-long-query-value?key=" + TOO_LONG_QUERY_VALUE;
|
||||||
|
+
|
||||||
|
const std::string JSON_DATA = "{\"hello\":\"world\"}";
|
||||||
|
|
||||||
|
const string LARGE_DATA = string(1024 * 1024 * 100, '@'); // 100MB
|
||||||
|
@@ -1991,6 +1994,11 @@ protected:
|
||||||
|
EXPECT_EQ(LONG_QUERY_URL, req.target);
|
||||||
|
EXPECT_EQ(LONG_QUERY_VALUE, req.get_param_value("key"));
|
||||||
|
})
|
||||||
|
+ .Get("/too-long-query-value",
|
||||||
|
+ [&](const Request &req, Response & /*res*/) {
|
||||||
|
+ EXPECT_EQ(TOO_LONG_QUERY_URL, req.target);
|
||||||
|
+ EXPECT_EQ(TOO_LONG_QUERY_VALUE, req.get_param_value("key"));
|
||||||
|
+ })
|
||||||
|
.Get("/array-param",
|
||||||
|
[&](const Request &req, Response & /*res*/) {
|
||||||
|
EXPECT_EQ(3u, req.get_param_value_count("array"));
|
||||||
|
@@ -2697,6 +2705,13 @@ TEST_F(ServerTest, LongQueryValue) {
|
||||||
|
EXPECT_EQ(414, res->status);
|
||||||
|
}
|
||||||
|
|
||||||
|
+TEST_F(ServerTest, TooLongQueryValue) {
|
||||||
|
+ auto res = cli_.Get(TOO_LONG_QUERY_URL.c_str());
|
||||||
|
+
|
||||||
|
+ ASSERT_FALSE(res);
|
||||||
|
+ EXPECT_EQ(Error::Read, res.error());
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
TEST_F(ServerTest, TooLongHeader) {
|
||||||
|
Request req;
|
||||||
|
req.method = "GET";
|
||||||
|
--
|
||||||
|
2.49.0
|
||||||
|
|
||||||
BIN
cpp-httplib-0.14.0.tar.gz
Normal file
BIN
cpp-httplib-0.14.0.tar.gz
Normal file
Binary file not shown.
@ -1,12 +1,14 @@
|
|||||||
Name: cpp-httplib
|
Name: cpp-httplib
|
||||||
Version: 0.11.1
|
Version: 0.14.0
|
||||||
Release: 1
|
Release: 4
|
||||||
Summary: A C++ header-only HTTP/HTTPS server and client library
|
Summary: A C++ header-only HTTP/HTTPS server and client library
|
||||||
License: MIT
|
License: MIT
|
||||||
URL: https://github.com/yhirose/cpp-httplib
|
URL: https://github.com/yhirose/cpp-httplib
|
||||||
Source0: https://github.com/yhirose/%{name}/archive/refs/tags/v%{version}.tar.gz
|
Source0: https://github.com/yhirose/cpp-httplib/archive/v%{version}/cpp-httplib-%{version}.tar.gz
|
||||||
|
Patch0: CVE-2025-0825.patch
|
||||||
|
Patch1: CVE-2025-46728.patch
|
||||||
|
|
||||||
BuildArch: noarch
|
BuildRequires: gcc-c++ meson >= 0.47.0 openssl openssl-devel brotli-devel gtest-devel zlib-devel
|
||||||
Requires: openssl-devel, glibc-devel, zlib-devel
|
Requires: openssl-devel, glibc-devel, zlib-devel
|
||||||
|
|
||||||
%description
|
%description
|
||||||
@ -14,17 +16,15 @@ A C++11 single-file header-only cross platform HTTP/HTTPS library.
|
|||||||
It's extremely easy to setup. Just include httplib.h file in your code!
|
It's extremely easy to setup. Just include httplib.h file in your code!
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q -n %{name}-%{version}/
|
%autosetup -p1 -n %{name}-%{version}
|
||||||
|
|
||||||
%build
|
%build
|
||||||
|
%meson -Dcpp-httplib_compile=true -Dcpp-httplib_test=true \
|
||||||
|
--buildtype=release
|
||||||
|
%meson_build
|
||||||
|
|
||||||
%install
|
%install
|
||||||
install -d %{buildroot}/%{_includedir}
|
%meson_install
|
||||||
install -m0644 httplib.h %{buildroot}/%{_includedir}
|
|
||||||
install -d %{buildroot}/%{_docdir}/%{name}
|
|
||||||
cp -r example %{buildroot}/%{_docdir}/%{name}
|
|
||||||
cp %{buildroot}/%{_includedir}/httplib.h %{buildroot}/%{_docdir}/%{name}
|
|
||||||
|
|
||||||
|
|
||||||
%pre
|
%pre
|
||||||
%preun
|
%preun
|
||||||
@ -32,15 +32,33 @@ cp %{buildroot}/%{_includedir}/httplib.h %{buildroot}/%{_docdir}/%{name}
|
|||||||
%postun
|
%postun
|
||||||
|
|
||||||
%check
|
%check
|
||||||
|
export GTEST_FILTER='_Online$'
|
||||||
|
%meson_test
|
||||||
|
|
||||||
%files
|
%files
|
||||||
%license LICENSE
|
%license LICENSE
|
||||||
%doc README.md split.py
|
%doc README.md example
|
||||||
%{_includedir}/*
|
%{_includedir}/httplib.h
|
||||||
%{_docdir}/%{name}/httplib.h
|
%{_libdir}/lib%{name}.so
|
||||||
%{_docdir}/%{name}/example
|
%{_libdir}/lib%{name}.so.*
|
||||||
|
%{_libdir}/pkgconfig/%{name}.pc
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed May 07 2025 yaoxin <1024769339@qq.com> - 0.14.0-4
|
||||||
|
- Fix CVE-2025-46728
|
||||||
|
|
||||||
|
* Fri Feb 07 2025 yaoxin <1024769339@qq.com> - 0.14.0-3
|
||||||
|
- Fix CVE-2025-0825
|
||||||
|
|
||||||
|
* Wed Sep 27 2023 Chenxi Mao <chenxi.mao@suse.com> - 0.14.0-2
|
||||||
|
- Add openssl to build require list to fix build error
|
||||||
|
|
||||||
|
* Thu Sep 14 2023 liyanan <thistleslyn@163.com> - 0.14.0-1
|
||||||
|
- update to 0.14.0
|
||||||
|
|
||||||
|
* Tue Jun 13 2023 yaoxin <yao_xin001@hoperun.com> - 0.12.4-1
|
||||||
|
- Update to 0.12.4 for fix CVE-2023-26130
|
||||||
|
|
||||||
* Tue Aug 16 2022 jinzhiguang <jinzhiguang@kylinos.cn> - 0.11.1-1
|
* Tue Aug 16 2022 jinzhiguang <jinzhiguang@kylinos.cn> - 0.11.1-1
|
||||||
- update to 0.11.1
|
- update to 0.11.1
|
||||||
|
|
||||||
|
|||||||
BIN
v0.11.1.tar.gz
BIN
v0.11.1.tar.gz
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user