asio: client: Limit incoming response header field buffer size
This commit is contained in:
parent
00e722f02c
commit
0a1beea13a
|
@ -32,7 +32,7 @@ namespace nghttp2 {
|
||||||
namespace asio_http2 {
|
namespace asio_http2 {
|
||||||
namespace client {
|
namespace client {
|
||||||
|
|
||||||
request_impl::request_impl() : strm_(nullptr) {}
|
request_impl::request_impl() : strm_(nullptr), header_buffer_size_(0) {}
|
||||||
|
|
||||||
void request_impl::write_trailer(header_map h) {
|
void request_impl::write_trailer(header_map h) {
|
||||||
auto sess = strm_->session();
|
auto sess = strm_->session();
|
||||||
|
@ -105,6 +105,12 @@ void request_impl::method(std::string s) { method_ = std::move(s); }
|
||||||
|
|
||||||
const std::string &request_impl::method() const { return method_; }
|
const std::string &request_impl::method() const { return method_; }
|
||||||
|
|
||||||
|
size_t request_impl::header_buffer_size() const { return header_buffer_size_; }
|
||||||
|
|
||||||
|
void request_impl::update_header_buffer_size(size_t len) {
|
||||||
|
header_buffer_size_ += len;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
} // namespace asio_http2
|
} // namespace asio_http2
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
|
@ -75,6 +75,9 @@ public:
|
||||||
void method(std::string s);
|
void method(std::string s);
|
||||||
const std::string &method() const;
|
const std::string &method() const;
|
||||||
|
|
||||||
|
size_t header_buffer_size() const;
|
||||||
|
void update_header_buffer_size(size_t len);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
header_map header_;
|
header_map header_;
|
||||||
response_cb response_cb_;
|
response_cb response_cb_;
|
||||||
|
@ -84,6 +87,7 @@ private:
|
||||||
class stream *strm_;
|
class stream *strm_;
|
||||||
uri_ref uri_;
|
uri_ref uri_;
|
||||||
std::string method_;
|
std::string method_;
|
||||||
|
size_t header_buffer_size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
|
|
@ -30,7 +30,8 @@ namespace nghttp2 {
|
||||||
namespace asio_http2 {
|
namespace asio_http2 {
|
||||||
namespace client {
|
namespace client {
|
||||||
|
|
||||||
response_impl::response_impl() : content_length_(-1), status_code_(0) {}
|
response_impl::response_impl()
|
||||||
|
: content_length_(-1), header_buffer_size_(0), status_code_(0) {}
|
||||||
|
|
||||||
void response_impl::on_data(data_cb cb) { data_cb_ = std::move(cb); }
|
void response_impl::on_data(data_cb cb) { data_cb_ = std::move(cb); }
|
||||||
|
|
||||||
|
@ -52,6 +53,12 @@ header_map &response_impl::header() { return header_; }
|
||||||
|
|
||||||
const header_map &response_impl::header() const { return header_; }
|
const header_map &response_impl::header() const { return header_; }
|
||||||
|
|
||||||
|
size_t response_impl::header_buffer_size() const { return header_buffer_size_; }
|
||||||
|
|
||||||
|
void response_impl::update_header_buffer_size(size_t len) {
|
||||||
|
header_buffer_size_ += len;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
} // namespace asio_http2
|
} // namespace asio_http2
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
|
@ -53,12 +53,16 @@ public:
|
||||||
header_map &header();
|
header_map &header();
|
||||||
const header_map &header() const;
|
const header_map &header() const;
|
||||||
|
|
||||||
|
size_t header_buffer_size() const;
|
||||||
|
void update_header_buffer_size(size_t len);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
data_cb data_cb_;
|
data_cb data_cb_;
|
||||||
|
|
||||||
header_map header_;
|
header_map header_;
|
||||||
|
|
||||||
int64_t content_length_;
|
int64_t content_length_;
|
||||||
|
size_t header_buffer_size_;
|
||||||
int status_code_;
|
int status_code_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,12 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
if (token == http2::HD__STATUS) {
|
if (token == http2::HD__STATUS) {
|
||||||
res.status_code(util::parse_uint(value, valuelen));
|
res.status_code(util::parse_uint(value, valuelen));
|
||||||
} else {
|
} else {
|
||||||
|
if (res.header_buffer_size() + namelen + valuelen > 64_k) {
|
||||||
|
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||||
|
frame->hd.stream_id, NGHTTP2_INTERNAL_ERROR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
res.update_header_buffer_size(namelen + valuelen);
|
||||||
|
|
||||||
if (token == http2::HD_CONTENT_LENGTH) {
|
if (token == http2::HD_CONTENT_LENGTH) {
|
||||||
res.content_length(util::parse_uint(value, valuelen));
|
res.content_length(util::parse_uint(value, valuelen));
|
||||||
|
@ -223,6 +229,13 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
default:
|
default:
|
||||||
|
if (req.header_buffer_size() + namelen + valuelen > 64_k) {
|
||||||
|
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||||
|
frame->hd.stream_id, NGHTTP2_INTERNAL_ERROR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
req.update_header_buffer_size(namelen + valuelen);
|
||||||
|
|
||||||
req.header().emplace(
|
req.header().emplace(
|
||||||
std::string(name, name + namelen),
|
std::string(name, name + namelen),
|
||||||
header_value{std::string(value, value + valuelen),
|
header_value{std::string(value, value + valuelen),
|
||||||
|
|
Loading…
Reference in New Issue