[fuzz] add fuzz tests for hpack encoding and decoding#13315
[fuzz] add fuzz tests for hpack encoding and decoding#13315mattklein123 merged 13 commits intoenvoyproxy:masterfrom
Conversation
Signed-off-by: Asra Ali <asraa@google.com>
htuch
left a comment
There was a problem hiding this comment.
Looks good. What does the performance looks like? Maybe file a bug in nghttp2 repo for them to create a similar fuzzer?
| ENVOY_LOG_MISC(trace, "Encoding headers {}", headers); | ||
| const absl::optional<Buffer::OwnedImpl> payload = encodeHeaders(input_nv); | ||
| if (!payload.has_value() || payload.value().getRawSlices().size() == 0) { | ||
| // An empty header map produces no payload, skip decoding. |
There was a problem hiding this comment.
What if the empty payload is due to some nghttp2 failure?
There was a problem hiding this comment.
If nghttp2 throws a negative error code, payload will be a nullopt, which will return. I think this boils down to whether the team wants scope of fuzzer to be to simply check if encode/decode always work by sending headers through both and checking for equality, or if the team wants to explore header values that could cause nghttp2 to throw errors.
There was a problem hiding this comment.
I think catching unexpected errors from nghttp2 would be a nice bonus, since we have a lot of ASSERTs in places around the returns from nghttp2 calls.
There was a problem hiding this comment.
Done. Empty payload is now handled earlier, since in our codebase and here we pass .data(), which, if nullptr because of empty header map, will crash nghttp2 at runtime. That's kinda bad, but I went through the codebase and there's nowhere we supply headers via data() without at least one header. We should add a statement enforcing this though, maybe.
Since empty payload is not worrisome in encode, I catch errors with an ASSERT(result >= 0) now.
| DEFINE_PROTO_FUZZER(const test::common::http::http2::HpackTestCase& input) { | ||
| // Validate headers. | ||
| try { | ||
| TestUtility::validate(input); |
There was a problem hiding this comment.
Maybe leave a TODO to make this even faster by skipping LPM and working with direct byte array representing lists of headers (let's say separated by any characters that aren't valid HTTP header vals).
There was a problem hiding this comment.
done. using vectors rather than HeaderMap sped it up to about 800, adding verification via qsort and compare brought it back down to 700.
There was a problem hiding this comment.
I was actually suggesting to skip using proto entirely, rather than skipping the HeaderMap, but up to you, I think it's fine to merge as is.
There was a problem hiding this comment.
Yep, acked. The TODO about that is at the top of the file "// TODO(asraa): Speed up by using raw byte input and seperators rather than protobuf input."
|
Good question, performance started at around 650-700, and tapered down to 450. The obvious way to optimize would be to remove the header map construction and just stick to comparisons between protos or the nv arrays. originally i just had the comparison go test::fuzz::Headers input to test::fuzz::Headers decoded headers. But it has the overhead of protos or array sorting I will do this, it's worth getting it to 1000. |
|
@asraa up to you, happy to review in either state, just want to throw it out there. |
Signed-off-by: Asra Ali <asraa@google.com>
| DEFINE_PROTO_FUZZER(const test::common::http::http2::HpackTestCase& input) { | ||
| // Validate headers. | ||
| try { | ||
| TestUtility::validate(input); |
There was a problem hiding this comment.
I was actually suggesting to skip using proto entirely, rather than skipping the HeaderMap, but up to you, I think it's fine to merge as is.
Signed-off-by: Asra Ali <asraa@google.com>
Signed-off-by: Asra Ali <asraa@google.com>
Signed-off-by: Asra Ali <asraa@google.com>
Signed-off-by: Asra Ali <asraa@google.com>
Signed-off-by: Asra Ali <asraa@google.com>
|
This pull request has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
|
@asraa looks like this one was approved but there were some final CI check issues blocking merge. |
|
ping when ready for review /wait |
Signed-off-by: Asra Ali <asraa@google.com>
Signed-off-by: Asra Ali <asraa@google.com>
jmarantz
left a comment
There was a problem hiding this comment.
looks fine modulo some nits.
Signed-off-by: Asra Ali <asraa@google.com>
| // TODO(asraa): Consider adding flags in fuzzed input. | ||
| nva[i++] = {const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(header.key().data())), | ||
| const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(header.value().data())), | ||
| header.key().size(), header.value().size(), /*flags = */ 0}; |
There was a problem hiding this comment.
I think we've not been using this pattern of arg-documentation in Envoy. However I like the previous state of having flags as a variable that's passed in, as it's self-documenting. The flags var could be const though.
There was a problem hiding this comment.
Should be all set (only diff)
Signed-off-by: Asra Ali <asraa@google.com>
* master: (30 commits) Deflaked: Guarddog_impl_test (envoyproxy#14475) [fuzz] add fuzz tests for hpack encoding and decoding (envoyproxy#13315) [filters] Prevent a filter from sending local reply and continue (envoyproxy#14416) oauth2: improving coverage (envoyproxy#14479) owners: Change dio email address (envoyproxy#14498) macos build: Fix ninja install (envoyproxy#14495) http: use OptRef helper to reduce some boilerplate (envoyproxy#14361) doc: update test/integration/README.md (envoyproxy#14485) server: wait workers to start before draining parent. (envoyproxy#14319) api: relax inline_string length limitation in DataSource (envoyproxy#14461) oauth: properly stop filter chain when a response was sent (envoyproxy#14476) listener: deprecate use_proxy_proto (envoyproxy#14406) deps: update cel and remove a patch (envoyproxy#14473) preconnect: rename: (envoyproxy#14474) coverage: ratcheting limits (envoyproxy#14472) grpc mux: fix sending node again after stream is reset (envoyproxy#14080) [test] Replace printers_include with printers_lib. (envoyproxy#14442) tcp: nodelay in the new pool (envoyproxy#14453) test: replace mock_methodn macros with mock_method (envoyproxy#14450) tcp: extending tcp integration test (envoyproxy#14451) ... Signed-off-by: Michael Puncel <mpuncel@squareup.com>
Signed-off-by: Asra Ali asraa@google.com
Commit Message: Adds tests for HPACK encoding and decoding with nghttp2. The fuzz test takes a set of headers, encodes them, decodes, and checks the results is equal to the input.
Performance: 700-800 exec/sec
Risk Level: Low
Testing: Ran with libfuzzer