]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1768 in SNORT/snort3 from ~KATHARVE/snort3:h2i_decode_string_lite...
authorMike Stepanek (mstepane) <mstepane@cisco.com>
Tue, 8 Oct 2019 17:54:07 +0000 (13:54 -0400)
committerMike Stepanek (mstepane) <mstepane@cisco.com>
Tue, 8 Oct 2019 17:54:07 +0000 (13:54 -0400)
Squashed commit of the following:

commit c2a9ef959b7ecda8405591d9f53b041b6b06cec1
Author: Katura Harvey <katharve@cisco.com>
Date:   Thu Sep 5 08:49:22 2019 -0400

    http2_inspect: parse hpack header representations and decode string literals

17 files changed:
src/service_inspectors/http2_inspect/dev_notes.txt
src/service_inspectors/http2_inspect/http2_enum.h
src/service_inspectors/http2_inspect/http2_flow_data.cc
src/service_inspectors/http2_inspect/http2_flow_data.h
src/service_inspectors/http2_inspect/http2_hpack_int_decode.cc
src/service_inspectors/http2_inspect/http2_hpack_int_decode.h
src/service_inspectors/http2_inspect/http2_hpack_string_decode.cc
src/service_inspectors/http2_inspect/http2_hpack_string_decode.h
src/service_inspectors/http2_inspect/http2_inspect.cc
src/service_inspectors/http2_inspect/http2_stream_splitter.h
src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc
src/service_inspectors/http2_inspect/http2_tables.cc
src/service_inspectors/http2_inspect/test/CMakeLists.txt
src/service_inspectors/http2_inspect/test/http2_hpack_int_decode_test.cc
src/service_inspectors/http2_inspect/test/http2_hpack_string_decode_test.cc
src/service_inspectors/http2_inspect/test/http2_inspect_impl_test.cc
src/service_inspectors/http2_inspect/test/http2_stream_splitter_impl_test.cc

index 26c649e90e4977f453356ecaf96737a343ca420b..c636cc013551b913cef904cd6538c4578a565526 100644 (file)
@@ -1,6 +1,14 @@
 The HTTP/2 inspector (H2I) will convert HTTP/2 frames into HTTP/1.1 message sections and feed them
 to the new HTTP inspector (NHI) for further processing.
 
-The current implementation is the very first step. It splits an HTTP/2 stream into frames and
-forwards them for inspection. It does not interface with NHI, does not provide error detection and
-handling, and does not address the multiplexed nature of HTTP/2.
+The current implementation is the very first step. It splits an HTTP/2 stream into frame sections and
+forwards them for inspection. It does not interface with NHI and does not address the multiplexed
+nature of HTTP/2.
+
+The Http2StreamSplitter strips the frame headers from the frame data and stores them in separate
+buffers. As in NHI, long data frames are split into 16kb chunks for inspection. If a header frame is
+followed by continuation frames, all the header frames are flushed together for inspection. The
+frame headers from each frame are stored contiguously in the frame_header buffer. After cutting out
+the frame headers, the frame data is stored as a single block, consisting of the HPACK encoded
+HTTP/2 headers. HPACK decoding is under ongoing development. Decoded headers will be stored in the
+http2_decoded_header buffer.
index bb1133374e456fbf8b31c5991ef999c5c385c320..02e2e89ac7836bdd4b3bac67a53bd2da3054b226 100644 (file)
@@ -52,6 +52,7 @@ enum EventSid
     EVENT_STRING_DECODE_FAILURE = 3,
     EVENT_MISSING_CONTINUATION = 4,
     EVENT_UNEXPECTED_CONTINUATION = 5,
+    EVENT_MISFORMATTED_HTTP2 = 6,
     EVENT_PREFACE_MATCH_FAILURE = 7,
     EVENT__MAX_VALUE
 };
@@ -66,7 +67,7 @@ enum Infraction
     INF_INT_LEADING_ZEROS = 3,
     INF_STRING_EMPTY_BUFF = 4,
     INF_STRING_MISSING_BYTES = 5,
-    INF_OUT_BUFF_OUT_OF_SPACE = 6,
+    INF_DECODED_HEADER_BUFF_OUT_OF_SPACE = 6,
     INF_HUFFMAN_BAD_PADDING = 7,
     INF_HUFFMAN_DECODED_EOS = 8,
     INF_HUFFMAN_INCOMPLETE_CODE_PADDING = 9,
index 741d6ed9d57189922d55fa6e6d71c3f0fbe55e09..0b4060e284fd1649caea65ebc0488db076e16917 100644 (file)
@@ -71,7 +71,6 @@ Http2FlowData::~Http2FlowData()
     for (int k=0; k <= 1; k++)
     {
         delete[] frame_header[k];
-        delete[] currently_processing_frame_header[k];
         delete[] frame_data[k];
         delete[] http2_decoded_header[k];
         delete infractions[k];
index b52bbdd95dfd24f42afcab96430f01c6b48b36e7..9191b3c4f1bb6df7e24b83099286854852469a2a 100644 (file)
@@ -31,6 +31,8 @@
 #include "stream/stream_splitter.h"
 
 #include "http2_enum.h"
+#include "http2_hpack_int_decode.h"
+#include "http2_hpack_string_decode.h"
 
 using Http2Infractions = Infractions<Http2Enums::INF__MAX_VALUE, Http2Enums::INF__NONE>;
 
@@ -53,6 +55,36 @@ public:
         uint32_t*, HttpCommon::SourceId);
     friend bool implement_get_buf(unsigned id, Http2FlowData*, HttpCommon::SourceId,
         snort::InspectionBuffer&);
+    friend bool decode_headers(Http2FlowData* session_data, HttpCommon::SourceId source_id,
+        const uint8_t* raw_header_buffer, const uint32_t header_length);
+    friend bool decode_header_line(Http2FlowData* session_data, HttpCommon::SourceId source_id,
+        const uint8_t* encoded_header_buffer, const uint32_t encoded_header_buffer_length,
+        uint32_t& bytes_consumed, uint8_t* decoded_header_buffer,
+        const uint32_t decoded_header_buffer_length, uint32_t& bytes_written);
+    friend bool handle_dynamic_size_update(Http2FlowData* session_data,
+        HttpCommon::SourceId source_id, const uint8_t* encoded_header_buffer,
+        const uint32_t encoded_header_length, const Http2HpackIntDecode &decode_int,
+        uint32_t &bytes_consumed, uint32_t &bytes_written);
+    friend bool decode_literal_header_line(Http2FlowData* session_data,
+         HttpCommon::SourceId source_id, const uint8_t* encoded_header_buffer,
+         const uint32_t encoded_header_buffer_length,
+        const uint8_t name_index_mask, const Http2HpackIntDecode &decode_int,
+        uint32_t &bytes_consumed, uint8_t* decoded_header_buffer,
+        const uint32_t decoded_header_buffer_length, uint32_t &bytes_written);
+    friend bool decode_index(Http2FlowData* session_data, HttpCommon::SourceId source_id,
+        const uint8_t* encoded_header_buffer, const uint32_t encoded_header_length,
+        const Http2HpackIntDecode &decode_int, uint32_t &bytes_consumed,
+        uint8_t* decoded_header_buffer, const uint32_t decoded_header_length,
+        uint32_t &bytes_written);
+    friend bool decode_string_literal(Http2FlowData* session_data, HttpCommon::SourceId source_id,
+        const uint8_t* encoded_header_buffer, const uint32_t encoded_header_length,
+        const Http2HpackStringDecode &decode_string, bool is_field_name, uint32_t &bytes_consumed,
+        uint8_t* decoded_header_buffer, const uint32_t decoded_header_buffer_length,
+        uint32_t &bytes_written);
+    friend bool write_decoded_headers(Http2FlowData* session_data, HttpCommon::SourceId source_id,
+        const uint8_t* in_buffer, const uint32_t in_length,
+        uint8_t* decoded_header_buffer, uint32_t decoded_header_buffer_length,
+        uint32_t &bytes_written);
 
     size_t size_of() override
     { return sizeof(*this); }
@@ -70,7 +102,7 @@ protected:
 
     // Internal to scan
     bool continuation_expected[2] = { false, false };
-    uint8_t* currently_processing_frame_header[2] = { nullptr, nullptr };
+    uint8_t currently_processing_frame_header[2][Http2Enums::FRAME_HEADER_LENGTH];
     uint32_t inspection_section_length[2] = { 0, 0 };
     uint32_t leftover_data[2] = { 0, 0 };
 
@@ -92,7 +124,6 @@ protected:
     // transaction in NHI. Also as in NHI accessor methods will need to be added.
     Http2Infractions* infractions[2] = { new Http2Infractions, new Http2Infractions };
     Http2EventGen* events[2] = { new Http2EventGen, new Http2EventGen };
-    
 
 #ifdef REG_TEST
     static uint64_t instance_count;
index e2ab8c434e78fb5d3c8543d459717ecb9aec8ee0..835c40f3cc9b4e5fb7c8ae4b48f5a0211c4258ce 100644 (file)
@@ -30,15 +30,14 @@ using namespace Http2Enums;
 static const uint8_t VAL_MASK = 0x7F;
 static const uint8_t FLAG_BIT = 0x80;
 
-Http2HpackIntDecode::Http2HpackIntDecode(uint8_t prefix, Http2EventGen* events,
-    Http2Infractions* infractions) : prefix_mask(((uint16_t)1 << prefix) - 1), events(events),
-    infractions(infractions)
+Http2HpackIntDecode::Http2HpackIntDecode(uint8_t prefix) : prefix_mask(((uint16_t)1 << prefix) - 1)
 {
     assert ((0 < prefix) && (prefix < 9));
 }
 
 bool Http2HpackIntDecode::translate(const uint8_t* in_buff, const uint32_t in_len,
-    uint32_t& bytes_consumed, uint64_t& result)
+    uint32_t& bytes_consumed, uint64_t& result, Http2EventGen* events,
+    Http2Infractions* infractions) const
 {
     bytes_consumed = 0;
     result = 0;
index ce0e17f59017306701edf0a0f93c1504cb5e361b..f62e6cec5aa6c7afbcafa20f456f91ebb3e8f1ee 100644 (file)
@@ -33,16 +33,12 @@ using Http2EventGen = EventGen<Http2Enums::EVENT__MAX_VALUE, Http2Enums::EVENT__
 class Http2HpackIntDecode
 {
 public:
-    Http2HpackIntDecode(uint8_t prefix, Http2EventGen* events, Http2Infractions* infractions);
+    Http2HpackIntDecode(uint8_t prefix);
     bool translate(const uint8_t* in_buff, const uint32_t in_len, uint32_t& bytes_consumed,
-        uint64_t& result);
+        uint64_t& result, Http2EventGen* events, Http2Infractions* infractions) const;
 
 private:
     const uint8_t prefix_mask;
-    // FIXIT-M These will get merged into the corresponding frame/stream object infractions and
-    // events
-    Http2EventGen* const events;
-    Http2Infractions* const infractions;
 };
 
 #endif
index 5d9ea2ded1cc5c3fd9ed85e73a7609a37bcb1cdb..ffc4313362e44e1dc262645a06c784d2fe8e75fd 100644 (file)
@@ -36,13 +36,9 @@ static const uint8_t HUFFMAN_FLAG = 0x80;
 static const uint8_t min_decode_len[HUFFMAN_LOOKUP_MAX + 1] =
     {5, 2, 2, 3, 5, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4};
 
-Http2HpackStringDecode::Http2HpackStringDecode(Http2EventGen* events,
-    Http2Infractions* infractions) : decode7(new Http2HpackIntDecode(7, events, infractions)),
-    events(events), infractions(infractions)
-{ }
-
 bool Http2HpackStringDecode::translate(const uint8_t* in_buff, const uint32_t in_len,
-    uint32_t& bytes_consumed, uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written)
+    uint32_t& bytes_consumed, uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written,
+    Http2EventGen* events, Http2Infractions* infractions) const
 {
     bytes_consumed = 0;
     bytes_written = 0;
@@ -58,7 +54,7 @@ bool Http2HpackStringDecode::translate(const uint8_t* in_buff, const uint32_t in
 
     // Get length
     uint64_t encoded_len;
-    if (!decode7->translate(in_buff, in_len, bytes_consumed, encoded_len))
+    if (!decode7.translate(in_buff, in_len, bytes_consumed, encoded_len, events, infractions))
         return false;
 
     if (encoded_len > (uint64_t)(in_len - bytes_consumed))
@@ -72,25 +68,21 @@ bool Http2HpackStringDecode::translate(const uint8_t* in_buff, const uint32_t in
         return true;
 
     if (!isHuffman)
-        return get_string(in_buff, encoded_len, bytes_consumed, out_buff, out_len, bytes_written);
+        return get_string(in_buff, encoded_len, bytes_consumed, out_buff, out_len, bytes_written, 
+                events, infractions);
 
     return get_huffman_string(in_buff, encoded_len, bytes_consumed, out_buff, out_len,
-        bytes_written);
-}
-
-Http2HpackStringDecode::~Http2HpackStringDecode()
-{
-    assert(decode7 != nullptr);
-    delete decode7;
+        bytes_written, events, infractions);
 }
 
 bool Http2HpackStringDecode::get_string(const uint8_t* in_buff, const uint32_t encoded_len,
-    uint32_t& bytes_consumed, uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written)
+    uint32_t& bytes_consumed, uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written,
+    Http2EventGen* events, Http2Infractions* infractions) const
 {
     if (encoded_len > out_len)
     {
-        *infractions += INF_OUT_BUFF_OUT_OF_SPACE;
-        events->create_event(EVENT_STRING_DECODE_FAILURE);
+        *infractions += INF_DECODED_HEADER_BUFF_OUT_OF_SPACE;
+        events->create_event(EVENT_MISFORMATTED_HTTP2);
         return false;
     }
 
@@ -103,7 +95,7 @@ bool Http2HpackStringDecode::get_string(const uint8_t* in_buff, const uint32_t e
 // return is tail/padding
 bool Http2HpackStringDecode::get_next_byte(const uint8_t* in_buff, const uint32_t last_byte,
     uint32_t& bytes_consumed, uint8_t& cur_bit, uint8_t match_len, uint8_t& byte,
-    bool& another_search)
+    bool& another_search) const
 {
     another_search = true;
     cur_bit += match_len;
@@ -148,7 +140,8 @@ bool Http2HpackStringDecode::get_next_byte(const uint8_t* in_buff, const uint32_
 }
 
 bool Http2HpackStringDecode::get_huffman_string(const uint8_t* in_buff, const uint32_t encoded_len,
-    uint32_t& bytes_consumed, uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written)
+    uint32_t& bytes_consumed, uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written,
+    Http2EventGen* events, Http2Infractions* infractions) const
 {
     const uint32_t last_encoded_byte = bytes_consumed + encoded_len;
     uint8_t byte;
@@ -161,7 +154,7 @@ bool Http2HpackStringDecode::get_huffman_string(const uint8_t* in_buff, const ui
     const uint32_t max_length = floor(encoded_len * 8.0/5.0);
     if (max_length > out_len)
     {
-        *infractions += INF_OUT_BUFF_OUT_OF_SPACE;
+        *infractions += INF_DECODED_HEADER_BUFF_OUT_OF_SPACE;
         events->create_event(EVENT_STRING_DECODE_FAILURE);
         return false;
     }
index 464bf6ba6b5171c60afc1664864aa5d95672d1e4..0a772420ca6745ed81f82d4be897e317ba66150e 100644 (file)
 class Http2HpackStringDecode
 {
 public:
-    Http2HpackStringDecode(Http2EventGen* events, Http2Infractions* infractions);
+    Http2HpackStringDecode() : decode7(7) { }
     bool translate(const uint8_t* in_buff, const uint32_t in_len, uint32_t& bytes_consumed,
-        uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written);
-    ~Http2HpackStringDecode();
+        uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written,
+        Http2EventGen* events, Http2Infractions* infractions) const;
 
 private:
     bool get_string(const uint8_t* in_buff, const uint32_t encoded_len, uint32_t& bytes_consumed,
-        uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written);
+        uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written, Http2EventGen* events,
+        Http2Infractions* infractions) const;
     bool get_huffman_string(const uint8_t* in_buff, const uint32_t encoded_len,
-        uint32_t& bytes_consumed, uint8_t* out_buff, const uint32_t out_len, uint32_t& bytes_written);
+        uint32_t& bytes_consumed, uint8_t* out_buff, const uint32_t out_len, uint32_t& 
+        bytes_written, Http2EventGen* events, Http2Infractions* infractions) const;
     bool get_next_byte(const uint8_t* in_buff, const uint32_t last_byte,
-                      uint32_t& bytes_consumed, uint8_t& cur_bit, uint8_t match_len, uint8_t& byte, bool& another_search);
+               uint32_t& bytes_consumed, uint8_t& cur_bit, uint8_t match_len, uint8_t& byte,
+        bool& another_search) const;
   
-    Http2HpackIntDecode* const decode7;
-    Http2EventGen* const events;
-    Http2Infractions* const infractions;
+    const Http2HpackIntDecode decode7;
 };
 
 #endif
index a43b109c9f56920b8923895b37dd4350d4c91f64..bbe8d3c2c80195f3819bddcbf1a6b04e84fa7598 100644 (file)
@@ -140,8 +140,7 @@ void Http2Inspect::clear(Packet* p)
     delete[] session_data->http2_decoded_header[source_id];
     session_data->http2_decoded_header[source_id] = nullptr;
     session_data->continuation_expected[source_id] = false;
-    delete[] session_data->currently_processing_frame_header[source_id];
-    session_data->currently_processing_frame_header[source_id] = nullptr;
     session_data->frames_aggregated[source_id] = 0;
+    session_data->header_octets_seen[source_id] = 0;
 }
 
index 167353e615261721aa9e3076ac826ac5039b276c..2a351e7ae998f5e09b1d95efe35f9ee0ff987ae6 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "http2_enum.h"
 #include "http2_flow_data.h"
+#include "http2_hpack_int_decode.h"
+#include "http2_hpack_string_decode.h"
 
 class Http2Inspect;
 
@@ -44,8 +46,24 @@ public:
     // FIXIT-M should return actual packet buffer size
     unsigned max(snort::Flow*) override { return Http2Enums::MAX_OCTETS; }
 
+    friend bool decode_literal_header_line(Http2FlowData* session_data,
+        HttpCommon::SourceId source_id, const uint8_t* encoded_header_buffer,
+        const uint32_t encoded_header_length, const uint8_t name_index_mask,
+        const Http2HpackIntDecode &decode_int, uint32_t &bytes_consumed,
+        uint8_t* decoded_header_buffer, const uint32_t decoded_header_length,
+        uint32_t &bytes_written);
+    friend bool decode_header_line(Http2FlowData* session_data, HttpCommon::SourceId source_id,
+        const uint8_t* encoded_header_buffer, const uint32_t encoded_header_length,
+        uint32_t& bytes_consumed, uint8_t* decoded_header_buffer,
+        const uint32_t decoded_header_length, uint32_t& bytes_written);
+
 private:
     const HttpCommon::SourceId source_id;
+    static Http2HpackIntDecode decode_int7;
+    static Http2HpackIntDecode decode_int6;
+    static Http2HpackIntDecode decode_int5;
+    static Http2HpackIntDecode decode_int4;
+    static Http2HpackStringDecode decode_string;
 };
 
 snort::StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t* data,
@@ -53,6 +71,8 @@ snort::StreamSplitter::Status implement_scan(Http2FlowData* session_data, const
 const snort::StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned total,
     unsigned offset, const uint8_t* data, unsigned len, uint32_t flags,
     HttpCommon::SourceId source_id);
+bool decode_headers(Http2FlowData* session_data, HttpCommon::SourceId source_id, 
+    const uint8_t* raw_header_buffer, const uint32_t header_length, bool field_name);
 
 enum ValidationResult { V_GOOD, V_BAD, V_TBD };
 
@@ -60,4 +80,3 @@ ValidationResult validate_preface(const uint8_t* data, const uint32_t length,
     const uint32_t octets_seen);
 
 #endif
-
index 7566f58ea81ebbc20edc3de5c0a86000f504b2f6..890e2e5ec6423ba5f854495a778b47fecf5f9bd3 100644 (file)
 
 #include <cassert>
 
-#include "http2_stream_splitter.h"
 #include "protocols/packet.h"
 #include "service_inspectors/http_inspect/http_common.h"
+#include "service_inspectors/http_inspect/http_field.h"
+#include "service_inspectors/http_inspect/http_test_input.h"
+#include "service_inspectors/http_inspect/http_test_manager.h"
 
 #include "http2_flow_data.h"
+#include "http2_hpack_int_decode.h"
+#include "http2_hpack_string_decode.h"
+#include "http2_stream_splitter.h"
 
 using namespace snort;
 using namespace HttpCommon;
 using namespace Http2Enums;
 
-static uint32_t get_frame_length(const uint8_t *frame_buffer)
+#define STATIC_TABLE_MAX_INDEX 61
+
+// FIXIT-H remove these declarations once implemented, for some reason this makes the compiler
+// happy for build alt
+bool decode_static_table_index(void);
+bool decode_dynamic_table_index(void);
+
+Http2HpackIntDecode Http2StreamSplitter::decode_int7(7);
+Http2HpackIntDecode Http2StreamSplitter::decode_int6(6);
+Http2HpackIntDecode Http2StreamSplitter::decode_int5(5);
+Http2HpackIntDecode Http2StreamSplitter::decode_int4(4);
+Http2HpackStringDecode Http2StreamSplitter::decode_string;
+
+static uint32_t get_frame_length(const uint8_t* frame_buffer)
 {
     return (frame_buffer[0] << 16) + (frame_buffer[1] << 8) + frame_buffer[2];
 }
 
-static uint8_t get_frame_type(const uint8_t *frame_buffer)
+static uint8_t get_frame_type(const uint8_tframe_buffer)
 {
     const uint8_t frame_type_index = 3;
     if (frame_buffer)
@@ -47,7 +65,7 @@ static uint8_t get_frame_type(const uint8_t *frame_buffer)
        return FT__NONE;
 }
 
-static uint8_t get_frame_flags(const uint8_t *frame_buffer)
+static uint8_t get_frame_flags(const uint8_tframe_buffer)
 {
     const uint8_t frame_flags_index = 4;
     if (frame_buffer)
@@ -108,41 +126,57 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t
 
         // Have full inspection section, flush and update leftover
         *flush_offset = session_data->inspection_section_length[source_id];
-        session_data->leftover_data[source_id] -= session_data->inspection_section_length[source_id];
+        session_data->leftover_data[source_id] -=
+            session_data->inspection_section_length[source_id];
         session_data->octets_seen[source_id] = 0;
     }
     else
     {
         // frame with header
-        // If there is a header frame followed by a continuation frame in the same tcp segment, 
-        // need to process multiple frames in a single scan
+        // If there is a header frame followed by a continuation frame in the same tcp segment, need
+        // to process multiple frames in a single scan
         *flush_offset = 0;
+        uint32_t remaining_length = length;    
+        const uint8_t *data_pos = data;
         do
         {
-            if (session_data->currently_processing_frame_header[source_id] == nullptr)
+            if (session_data->header_octets_seen[source_id] == 0)
             {
                 session_data->header_coming[source_id] = true;
-                session_data->currently_processing_frame_header[source_id] = new uint8_t[FRAME_HEADER_LENGTH];
                 session_data->octets_seen[source_id] = 0;
                 session_data->header_octets_seen[source_id] = 0;
-                session_data->frames_aggregated[source_id] = 1;
             }
 
-            // The first nine bytes are the frame header. But all nine might not all be present in the
-            // first TCP segment we receive. 
-            for (uint32_t k = 0; (k < length) && (session_data->header_octets_seen[source_id] <
-                        FRAME_HEADER_LENGTH); k++, session_data->header_octets_seen[source_id]++)
+            // The first nine bytes are the frame header. But all nine might not all be present in
+            // the first TCP segment we receive.
+            if (session_data->header_octets_seen[source_id] < FRAME_HEADER_LENGTH)
             {
-                session_data->currently_processing_frame_header[source_id]
-                    [session_data->header_octets_seen[source_id]] = data[k];
+                uint32_t remaining_header = FRAME_HEADER_LENGTH -
+                    session_data->header_octets_seen[source_id];
+                uint32_t remaining_header_in_data = remaining_header > remaining_length ?
+                    remaining_length : remaining_header;
+                memcpy(session_data->currently_processing_frame_header[source_id] +
+                    session_data->header_octets_seen[source_id],
+                    data_pos, remaining_header_in_data);
+                session_data->header_octets_seen[source_id] += remaining_header_in_data;
+                if (session_data->header_octets_seen[source_id] < FRAME_HEADER_LENGTH)
+                {
+                    session_data->octets_seen[source_id] += remaining_header_in_data;
+                    status = StreamSplitter::SEARCH;
+                    break;
+                }
+                session_data->frames_aggregated[source_id] += 1;
             }
-            if (session_data->header_octets_seen[source_id] < FRAME_HEADER_LENGTH)
+            
+            uint8_t type = get_frame_type(session_data->currently_processing_frame_header[source_id]);
+
+            if (session_data->continuation_expected[source_id] && type != FT_CONTINUATION)
             {
-                session_data->octets_seen[source_id] += length;
-                status = StreamSplitter::SEARCH;
+                *session_data->infractions[source_id] += INF_MISSING_CONTINUATION;
+                session_data->events[source_id]->create_event(EVENT_MISSING_CONTINUATION);
+                status = StreamSplitter::ABORT;
                 break;
             }
-            uint8_t type = get_frame_type(session_data->currently_processing_frame_header[source_id]);
 
             // Frame length does not include the frame header
             uint32_t const frame_length = get_frame_length(session_data->
@@ -154,7 +188,8 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t
             if ((type == FT_DATA) && (frame_length > DATA_SECTION_SIZE))
             {
                 // Break up long data frames into pieces for detection
-                session_data->inspection_section_length[source_id] = DATA_SECTION_SIZE + FRAME_HEADER_LENGTH;
+                session_data->inspection_section_length[source_id] = DATA_SECTION_SIZE +
+                    FRAME_HEADER_LENGTH;
             }
             else if (frame_length + FRAME_HEADER_LENGTH > MAX_OCTETS)
             {
@@ -174,7 +209,8 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t
             else
             {
                 // we have the full frame section to flush to detection
-                *flush_offset += session_data->inspection_section_length[source_id] - session_data->octets_seen[source_id];
+                *flush_offset += session_data->inspection_section_length[source_id] -
+                    session_data->octets_seen[source_id];
                 session_data->leftover_data[source_id] = frame_length + FRAME_HEADER_LENGTH 
                     - session_data->inspection_section_length[source_id];
                 session_data->octets_seen[source_id] = 0;
@@ -189,18 +225,18 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t
                 session_data->continuation_expected[source_id] = true;
                 
                 session_data->header_octets_seen[source_id] = 0;
-                session_data->frames_aggregated[source_id] += 1;
                 status = StreamSplitter::SEARCH;
-                data += frame_length + FRAME_HEADER_LENGTH;
+                data_pos = data + *flush_offset;
+                remaining_length = length - *flush_offset;
             }
             else if ( type == FT_CONTINUATION && session_data->continuation_expected[source_id])
             {
                 if (!(frame_flags & END_HEADERS))
                 {
                     session_data->header_octets_seen[source_id] = 0;
-                    session_data->frames_aggregated[source_id] += 1;
                     status = StreamSplitter::SEARCH;
-                    data += frame_length + FRAME_HEADER_LENGTH;
+                    data_pos = data + *flush_offset;
+                    remaining_length = length - *flush_offset;
                 }
                 else
                 {
@@ -217,17 +253,13 @@ StreamSplitter::Status implement_scan(Http2FlowData* session_data, const uint8_t
                 session_data->events[source_id]->create_event(EVENT_UNEXPECTED_CONTINUATION);
                 status = StreamSplitter::ABORT;
             }
-            else if (session_data->continuation_expected[source_id])
-            {
-                *session_data->infractions[source_id] += INF_MISSING_CONTINUATION;
-                session_data->events[source_id]->create_event(EVENT_MISSING_CONTINUATION);
-                status = StreamSplitter::ABORT;
-            }
-        } while (status != StreamSplitter::FLUSH && *flush_offset < length);
+        } while (status == StreamSplitter::SEARCH && remaining_length > 0);
     }
     return status;
 }
 
+// FIXIT-M If there are any errors in header decoding, this currently tells stream not to send 
+// headers to detection. This behavior may need to be changed.
 const StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned total,
     unsigned offset, const uint8_t* data, unsigned len, uint32_t flags,
     HttpCommon::SourceId source_id)
@@ -377,13 +409,12 @@ const StreamBuffer implement_reassemble(Http2FlowData* session_data, unsigned to
             if (type == FT_HEADERS || type == FT_CONTINUATION)
             {
                 assert(session_data->http2_decoded_header[source_id] == nullptr);
-                session_data->http2_decoded_header[source_id] = new uint8_t[MAX_OCTETS];
 
                 //FIXIT-H This will eventually be the decoded header buffer. For now just copy
                 //directly
-                memcpy(session_data->http2_decoded_header[source_id],
-                    session_data->frame_data[source_id], session_data->frame_data_size[source_id]);
-                session_data->http2_decoded_header_size[source_id] = session_data->frame_data_size[source_id];
+                               if (!decode_headers(session_data, source_id, session_data->frame_data[source_id],
+                        session_data->frame_data_size[source_id]))
+                    return frame_buf;
             }
         }
         // Return 0-length non-null buffer to stream which signals detection required, but don't 
@@ -418,3 +449,297 @@ ValidationResult validate_preface(const uint8_t* data, const uint32_t length,
     
     return V_GOOD;
 }
+
+bool write_decoded_headers(Http2FlowData* session_data, HttpCommon::SourceId source_id,
+    const uint8_t* in_buffer, const uint32_t in_length,
+    uint8_t* decoded_header_buffer, uint32_t decoded_header_length,
+    uint32_t &bytes_written)
+{
+    bool ret = true;
+    uint32_t length = in_length;
+    bytes_written = 0;
+
+    if (in_length > decoded_header_length)
+    {
+        length = MAX_OCTETS - session_data->http2_decoded_header_size[source_id];
+        *session_data->infractions[source_id] += INF_DECODED_HEADER_BUFF_OUT_OF_SPACE;
+        session_data->events[source_id]->create_event(EVENT_MISFORMATTED_HTTP2);
+        ret = false;
+    }
+
+    memcpy((void*)decoded_header_buffer, (void*) in_buffer, length);
+    bytes_written = length;
+    return ret;
+}
+
+bool decode_string_literal(Http2FlowData* session_data, HttpCommon::SourceId source_id,
+    const uint8_t* encoded_header_buffer, const uint32_t encoded_header_length,
+    const Http2HpackStringDecode &decode_string, bool is_field_name, uint32_t &bytes_consumed,
+    uint8_t* decoded_header_buffer, const uint32_t decoded_header_length,
+    uint32_t &bytes_written)
+{
+    uint32_t decoded_bytes_written;
+    uint32_t encoded_bytes_consumed;
+    uint32_t encoded_header_offset = 0;
+    bytes_written = 0;
+    bytes_consumed = 0;
+
+    if (is_field_name)
+    {
+        // skip over parsed pattern and zeroed index
+        encoded_header_offset++;
+        bytes_consumed++;
+    }
+
+    if (!decode_string.translate(encoded_header_buffer + encoded_header_offset,
+        encoded_header_length, encoded_bytes_consumed, decoded_header_buffer,
+        decoded_header_length, decoded_bytes_written, session_data->events[source_id],
+        session_data->infractions[source_id]))
+    {
+        return false;
+    }
+
+    bytes_consumed += encoded_bytes_consumed;
+    bytes_written += decoded_bytes_written;
+
+    if (is_field_name)
+    {
+        if (!write_decoded_headers(session_data, source_id, (const uint8_t*)": ", 2,
+                decoded_header_buffer + bytes_written, decoded_header_length -
+                bytes_written, decoded_bytes_written))
+            return false;
+    }
+    else
+    {
+        if (!write_decoded_headers(session_data, source_id, (const uint8_t*)"\r\n", 2,
+                decoded_header_buffer + bytes_written, decoded_header_length -
+                bytes_written, decoded_bytes_written))
+            return false;
+    }
+
+    bytes_written += decoded_bytes_written;
+
+    return true;
+}
+
+// FIXIT-H implement
+bool decode_static_table_index(void)
+{
+    return false;
+}
+
+// FIXIT-H implement
+bool decode_dynamic_table_index(void)
+{
+    return false;
+}
+
+// FIXIT-H Will be incrementally updated to actually decode indexes. For now just copies encoded
+// index directly to decoded_header_buffer
+bool decode_index(Http2FlowData* session_data, HttpCommon::SourceId source_id,
+    const uint8_t* encoded_header_buffer, const uint32_t encoded_header_length,
+    const Http2HpackIntDecode &decode_int, uint32_t &bytes_consumed,
+    uint8_t* decoded_header_buffer, const uint32_t decoded_header_length,
+    uint32_t &bytes_written)
+{
+    uint64_t index;
+    bytes_written = 0;
+    bytes_consumed = 0;
+
+    if (!decode_int.translate(encoded_header_buffer, encoded_header_length,
+        bytes_consumed, index, session_data->events[source_id],
+        session_data->infractions[source_id]))
+    {
+        return false;
+    }
+
+    if (index <= STATIC_TABLE_MAX_INDEX)
+        decode_static_table_index();
+    else
+        decode_dynamic_table_index();
+
+    if (!write_decoded_headers(session_data, source_id, encoded_header_buffer, bytes_consumed,
+            decoded_header_buffer, decoded_header_length, bytes_written))
+        return false;
+
+    return true;
+}
+
+bool decode_literal_header_line(Http2FlowData* session_data, HttpCommon::SourceId source_id,
+    const uint8_t* encoded_header_buffer, const uint32_t encoded_header_length,
+    const uint8_t name_index_mask, const Http2HpackIntDecode &decode_int, uint32_t &bytes_consumed,
+    uint8_t* decoded_header_buffer, const uint32_t decoded_header_length,
+    uint32_t &bytes_written)
+{
+    bytes_written = 0;
+    bytes_consumed = 0;
+    uint32_t partial_bytes_consumed;
+    uint32_t partial_bytes_written;
+    // indexed field name
+    if (encoded_header_buffer[0] & name_index_mask)
+    {
+        if (!decode_index(session_data, source_id, encoded_header_buffer,
+                encoded_header_length, decode_int, partial_bytes_consumed,
+                decoded_header_buffer, decoded_header_length, partial_bytes_written))
+            return false;
+    }
+    // literal field name
+    else
+    {
+        if (!decode_string_literal(session_data, source_id, encoded_header_buffer,
+                encoded_header_length, Http2StreamSplitter::decode_string, true,
+                partial_bytes_consumed, decoded_header_buffer, decoded_header_length,
+                partial_bytes_written))
+            return false;
+    }
+
+    bytes_consumed += partial_bytes_consumed;
+    bytes_written += partial_bytes_written;
+
+    // value is always literal
+    if (!decode_string_literal(session_data, source_id, encoded_header_buffer +
+            partial_bytes_consumed, encoded_header_length - partial_bytes_consumed,
+            Http2StreamSplitter::decode_string, false, partial_bytes_consumed,
+            decoded_header_buffer + partial_bytes_written, decoded_header_length -
+            partial_bytes_written, partial_bytes_written))
+        return false;
+
+    bytes_consumed += partial_bytes_consumed;
+    bytes_written += partial_bytes_written;
+
+    return true;
+}
+
+// FIXIT-M Will be updated to actually update dynamic table size. For now just skips over
+bool handle_dynamic_size_update(Http2FlowData* session_data, HttpCommon::SourceId source_id,
+    const uint8_t* encoded_header_buffer, const uint32_t encoded_header_length,
+    const Http2HpackIntDecode &decode_int, uint32_t &bytes_consumed, uint32_t &bytes_written)
+{
+    uint64_t decoded_int;
+    uint32_t encoded_bytes_consumed;
+    bytes_consumed = 0;
+    bytes_written = 0;
+
+    if (!decode_int.translate(encoded_header_buffer, encoded_header_length,
+        encoded_bytes_consumed, decoded_int, session_data->events[source_id],
+        session_data->infractions[source_id]))
+    {
+        return false;
+    }
+#ifdef REG_TEST
+    //FIXIT-M remove when dynamic size updates are handled
+    if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP2))
+    {
+            fprintf(HttpTestManager::get_output_file(),
+                "Skipping HPACK dynamic size update: %lu\n", decoded_int);
+    }
+#endif
+    bytes_consumed += encoded_bytes_consumed;
+
+    return true;
+}
+
+bool decode_header_line(Http2FlowData* session_data, HttpCommon::SourceId source_id,
+    const uint8_t* encoded_header_buffer, const uint32_t encoded_header_length,
+    uint32_t& bytes_consumed, uint8_t* decoded_header_buffer,
+    const uint32_t decoded_header_length, uint32_t& bytes_written)
+{
+    const uint8_t index_mask = 0x80;
+    const uint8_t literal_index_mask = 0x40;
+    const uint8_t literal_index_name_index_mask = 0x3f;
+    const uint8_t literal_no_index_mask = 0xf0;
+    const uint8_t literal_never_index_pattern = 0x10;
+    const uint8_t literal_no_index_name_index_mask = 0x0f;
+
+    // indexed header representation
+    if (encoded_header_buffer[0] & index_mask)
+        return decode_index(session_data, source_id, encoded_header_buffer, encoded_header_length,
+            Http2StreamSplitter::decode_int7, bytes_consumed, decoded_header_buffer,
+            decoded_header_length, bytes_written);
+
+    // literal header representation to be added to dynamic table
+    else if (encoded_header_buffer[0] & literal_index_mask)
+        return decode_literal_header_line(session_data, source_id, encoded_header_buffer,
+             encoded_header_length, literal_index_name_index_mask,
+             Http2StreamSplitter::decode_int6, bytes_consumed, decoded_header_buffer,
+             decoded_header_length, bytes_written);
+
+    // literal header field representation not to be added to dynamic table
+    // Note that this includes two representation types from the RFC - literal without index and
+    // literal never index. From a decoding standpoint these are identical.
+    else if ((encoded_header_buffer[0] & literal_no_index_mask) == 0 or
+            (encoded_header_buffer[0] & literal_no_index_mask) == literal_never_index_pattern)
+        return decode_literal_header_line(session_data, source_id, encoded_header_buffer,
+             encoded_header_length, literal_no_index_name_index_mask,
+             Http2StreamSplitter::decode_int4, bytes_consumed, decoded_header_buffer,
+             decoded_header_length, bytes_written);
+    else
+        // FIXIT-M dynamic table size update not yet supported, just skip
+        return handle_dynamic_size_update(session_data, source_id, encoded_header_buffer,
+            encoded_header_length, Http2StreamSplitter::decode_int5, bytes_consumed, bytes_written);
+}
+
+//FIXIT-H This will eventually be the decoded header buffer. For now only string literals are
+//decoded
+bool decode_headers(Http2FlowData* session_data, HttpCommon::SourceId source_id,
+    const uint8_t* encoded_header_buffer, const uint32_t header_length)
+{
+
+    uint32_t total_bytes_consumed = 0;
+    uint32_t line_bytes_consumed = 0;
+    uint32_t line_bytes_written = 0;
+    bool success = true;
+    session_data->http2_decoded_header[source_id] = new uint8_t[MAX_OCTETS];
+    session_data->http2_decoded_header_size[source_id] = 0;
+
+    while (total_bytes_consumed < header_length)
+    {
+        if (!decode_header_line(session_data, source_id,
+            encoded_header_buffer + total_bytes_consumed, header_length - total_bytes_consumed,
+            line_bytes_consumed, session_data->http2_decoded_header[source_id] +
+            session_data->http2_decoded_header_size[source_id], MAX_OCTETS -
+            session_data->http2_decoded_header_size[source_id], line_bytes_written))
+        {
+            success = false;
+            break;
+        }
+        total_bytes_consumed  += line_bytes_consumed;
+        session_data->http2_decoded_header_size[source_id] += line_bytes_written;
+    }
+
+    if (!success)
+    {
+#ifdef REG_TEST
+        if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP2))
+        {
+            fprintf(HttpTestManager::get_output_file(),
+                    "Error decoding headers. ");
+            if(session_data->http2_decoded_header_size[source_id] > 0)
+                Field(session_data->http2_decoded_header_size[source_id],
+                    session_data->http2_decoded_header[source_id]).print(
+                    HttpTestManager::get_output_file(), "Partially Decoded Header");
+        }
+#endif
+    return false;
+    }
+
+    // write the last crlf to end the header
+    if (!write_decoded_headers(session_data, source_id, (const uint8_t*)"\r\n", 2,
+            session_data->http2_decoded_header[source_id] +
+            session_data->http2_decoded_header_size[source_id], MAX_OCTETS -
+            session_data->http2_decoded_header_size[source_id], line_bytes_written))
+        return false;
+    session_data->http2_decoded_header_size[source_id] += line_bytes_written;
+
+#ifdef REG_TEST
+       if (HttpTestManager::use_test_output(HttpTestManager::IN_HTTP2))
+       {
+               Field(session_data->http2_decoded_header_size[source_id],
+                       session_data->http2_decoded_header[source_id]).print(HttpTestManager::get_output_file(),
+            "Decoded Header");
+       }
+#endif
+
+    return success;
+}
index 8620f5f6e4f5192d06407a9a77e516bef1b530c5..510df8ccb730421ed9121f08ab54ffb2f3987bd3 100644 (file)
@@ -35,6 +35,7 @@ const snort::RuleMap Http2Module::http2_events[] =
     { EVENT_STRING_DECODE_FAILURE, "error in HPACK string value" },
     { EVENT_MISSING_CONTINUATION, "missing continuation frame"},
     { EVENT_UNEXPECTED_CONTINUATION, "unexpected continuation frame"},
+    { EVENT_MISFORMATTED_HTTP2, "misformatted HTTP/2 traffic"},
     { EVENT_PREFACE_MATCH_FAILURE, "HTTP/2 connection preface does not match"},
     { 0, nullptr }
 };
index 81320eea25004e46a17112eaee84868fe87b5d67..0b312e509c6713bcd145a3f653c029015bd3326b 100644 (file)
@@ -9,6 +9,9 @@ add_cpputest( http2_inspect_impl_test
 add_cpputest( http2_stream_splitter_impl_test
     SOURCES
         ../http2_flow_data.cc
+        ../http2_hpack_int_decode.cc
+        ../http2_hpack_string_decode.cc
+        ../http2_huffman_state_machine.cc
         ../http2_stream_splitter_impl.cc
         ../http2_module.cc
         ../http2_tables.cc
index 706f1f8b23f8b61379473d2902b827b8e90df1e7..411d12c57efdb0564055d2c1a526ccc1d135e8b0 100644 (file)
@@ -44,7 +44,7 @@ TEST_GROUP(http2_hpack_int_decode_success)
 {
     Http2EventGen events;
     Http2Infractions inf;
-    Http2HpackIntDecode* const decode = new Http2HpackIntDecode(5, &events, &inf);
+    Http2HpackIntDecode* const decode = new Http2HpackIntDecode(5);
 
     void teardown() override
     {
@@ -61,7 +61,7 @@ TEST(http2_hpack_int_decode_success, 10_using_5_bits)
     // decode
     uint32_t bytes_processed = 0;
     uint64_t res = 0;
-    bool success = decode->translate(&buf, 1, bytes_processed, res);
+    bool success = decode->translate(&buf, 1, bytes_processed, res, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(res == 10);
@@ -75,7 +75,7 @@ TEST(http2_hpack_int_decode_success, 10_using_5_bits_wtail)
     // decode
     uint32_t bytes_processed = 0;
     uint64_t res = 0;
-    bool success = decode->translate(buf, 2, bytes_processed, res);
+    bool success = decode->translate(buf, 2, bytes_processed, res, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(res == 10);
@@ -89,7 +89,7 @@ TEST(http2_hpack_int_decode_success, 1337_using_5_bits)
     // decode
     uint32_t bytes_processed = 0;
     uint64_t res = 0;
-    bool success = decode->translate(buf, 3, bytes_processed, res);
+    bool success = decode->translate(buf, 3, bytes_processed, res, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(res == 1337);
@@ -99,13 +99,13 @@ TEST(http2_hpack_int_decode_success, 1337_using_5_bits)
 TEST(http2_hpack_int_decode_success, 42_using_8_bits)
 {
     // prepare decode object
-    Http2HpackIntDecode decode_8(8, &events, &inf);
+    Http2HpackIntDecode decode_8(8);
     // prepare buf to decode - example from RFC 7541 c.1.3
     uint8_t buf = 42;
     // decode
     uint32_t bytes_processed = 0;
     uint64_t res = 0;
-    bool success = decode_8.translate(&buf, 1, bytes_processed, res);
+    bool success = decode_8.translate(&buf, 1, bytes_processed, res, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(res == 42);
@@ -119,7 +119,7 @@ TEST(http2_hpack_int_decode_success, max_val_using_5_bit)
     // decode
     uint32_t bytes_processed = 0;
     uint64_t res = 0;
-    bool success = decode->translate(buf, 11, bytes_processed, res);
+    bool success = decode->translate(buf, 11, bytes_processed, res, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(res == 0xFFFFFFFFFFFFFFFF);
@@ -133,7 +133,7 @@ TEST(http2_hpack_int_decode_success, 31_using_5_bits)
     // decode
     uint32_t bytes_processed = 0;
     uint64_t res = 0;
-    bool success = decode->translate(buf, 2, bytes_processed, res);
+    bool success = decode->translate(buf, 2, bytes_processed, res, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(res == 31);
@@ -147,7 +147,7 @@ TEST(http2_hpack_int_decode_success, 0_using_5_bits)
     // decode
     uint32_t bytes_processed = 0;
     uint64_t res = 0;
-    bool success = decode->translate(&buf, 1, bytes_processed, res);
+    bool success = decode->translate(&buf, 1, bytes_processed, res, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(res == 0);
@@ -166,13 +166,13 @@ TEST(http2_hpack_int_decode_failure, 0_len_field)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackIntDecode decode_8(8, &local_events, &local_inf);
+    Http2HpackIntDecode decode_8(8);
     // prepare buf to decode - use buf length 0
     uint8_t buf = 42;
     // decode
     uint32_t bytes_processed = 0;
     uint64_t res = 0;
-    bool success = decode_8.translate(&buf, 0, bytes_processed, res);
+    bool success = decode_8.translate(&buf, 0, bytes_processed, res, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 0);
@@ -185,13 +185,13 @@ TEST(http2_hpack_int_decode_failure, too_short)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackIntDecode local_decode(5, &local_events, &local_inf);
+    Http2HpackIntDecode local_decode(5);
     // prepare buf to decode - buffer ends before decode finished
     uint8_t buf[3] = { 31, 0x9a, 10 };
     // decode
     uint32_t bytes_processed = 0;
     uint64_t res = 0;
-    bool success = local_decode.translate(buf, 2, bytes_processed, res);
+    bool success = local_decode.translate(buf, 2, bytes_processed, res, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 2);
@@ -204,13 +204,13 @@ TEST(http2_hpack_int_decode_failure, multiplier_bigger_than_63)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackIntDecode local_decode(5, &local_events, &local_inf);
+    Http2HpackIntDecode local_decode(5);
     // prepare buf to decode - multiplier > 63
     uint8_t buf[13] = { 31, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 1 };
     // decode
     uint32_t bytes_processed = 0;
     uint64_t res = 0;
-    bool success = local_decode.translate(buf, 13, bytes_processed, res);
+    bool success = local_decode.translate(buf, 13, bytes_processed, res, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 11);
@@ -223,13 +223,13 @@ TEST(http2_hpack_int_decode_failure, add_val_overflow)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackIntDecode local_decode(5, &local_events, &local_inf);
+    Http2HpackIntDecode local_decode(5);
     // prepare buf to decode - value to add itself is already creating overflow
     uint8_t buf[12] = { 31, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF, 1 };
     // decode
     uint32_t bytes_processed = 0;
     uint64_t res = 0;
-    bool success = local_decode.translate(buf, 12, bytes_processed, res);
+    bool success = local_decode.translate(buf, 12, bytes_processed, res, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 11);
@@ -242,13 +242,13 @@ TEST(http2_hpack_int_decode_failure, add_val_overflow2)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackIntDecode local_decode(5, &local_events, &local_inf);
+    Http2HpackIntDecode local_decode(5);
     // prepare buf to decode - adding value to result kept so far creates overflow
     uint8_t buf[11] = { 31, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1 };
     // decode
     uint32_t bytes_processed = 0;
     uint64_t res = 0;
-    bool success = local_decode.translate(buf, 11, bytes_processed, res);
+    bool success = local_decode.translate(buf, 11, bytes_processed, res, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 11);
@@ -261,13 +261,13 @@ TEST(http2_hpack_int_decode_failure, 2_64_using_5_bit)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackIntDecode local_decode(5, &local_events, &local_inf);
+    Http2HpackIntDecode local_decode(5);
     // prepare buf to decode - 2^64
     uint8_t buf[11] = { 31, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1 };
     // decode
     uint32_t bytes_processed = 0;
     uint64_t res = 0;
-    bool success = local_decode.translate(buf, 11, bytes_processed, res);
+    bool success = local_decode.translate(buf, 11, bytes_processed, res, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 11);
@@ -288,13 +288,13 @@ TEST(http2_hpack_int_decode_leading_zeros, leading_zeros)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackIntDecode local_decode(5, &local_events, &local_inf);
+    Http2HpackIntDecode local_decode(5);
     // prepare buf to decode - MSB is zero
     uint8_t buf[3] = { 31, 0x80, 0 };
     // decode
     uint32_t bytes_processed = 0;
     uint64_t res = 0;
-    bool success = local_decode.translate(buf, 3, bytes_processed, res);
+    bool success = local_decode.translate(buf, 3, bytes_processed, res, &local_events, &local_inf);
     // check results
     CHECK(success == true);
     CHECK(res == 31);
@@ -308,14 +308,14 @@ TEST(http2_hpack_int_decode_leading_zeros, leading_0_byte_11)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackIntDecode local_decode(5, &local_events, &local_inf);
+    Http2HpackIntDecode local_decode(5);
     // prepare buf to decode - multiplier 63 doesn't create overflow, should alert on
     // leading 0
     uint8_t buf[11] = { 31, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0 };
     // decode
     uint32_t bytes_processed = 0;
     uint64_t res = 0;
-    bool success = local_decode.translate(buf, 11, bytes_processed, res);
+    bool success = local_decode.translate(buf, 11, bytes_processed, res, &local_events, &local_inf);
     // check results
     CHECK(success == true);
     CHECK(res == 0x7FFFFFFFFFFFFFFF);
index 16e4eff080cc30bb0ea3bca600e9472f841a079c..a6b5867ca15c1721917216ae771468d55d04e660 100644 (file)
@@ -48,7 +48,7 @@ TEST_GROUP(http2_hpack_string_decode_success)
 {
     Http2EventGen events;
     Http2Infractions inf;
-    Http2HpackStringDecode* const decode = new Http2HpackStringDecode(&events, &inf);
+    Http2HpackStringDecode* const decode = new Http2HpackStringDecode();
 
     void teardown() override
     {
@@ -65,7 +65,7 @@ TEST(http2_hpack_string_decode_success, custom_key_len_10)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[10];
-    bool success = decode->translate(buf, 11, bytes_processed, res, 10, bytes_written);
+    bool success = decode->translate(buf, 11, bytes_processed, res, 10, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(memcmp(res, "custom-key", 10) == 0);
@@ -80,7 +80,7 @@ TEST(http2_hpack_string_decode_success, custom_key_len_10_wtail)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[12];
-    bool success = decode->translate(buf, 12, bytes_processed, res, 12, bytes_written);
+    bool success = decode->translate(buf, 12, bytes_processed, res, 12, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(memcmp(res, "custom-key", 10) == 0);
@@ -98,7 +98,7 @@ TEST(http2_hpack_string_decode_success, int_is_more_than_1_byte)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[130];
-    bool success = decode->translate(buf, 130, bytes_processed, res, 130, bytes_written);
+    bool success = decode->translate(buf, 130, bytes_processed, res, 130, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 130);
@@ -113,7 +113,7 @@ TEST(http2_hpack_string_decode_success, empty_string)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res = 10; // random value, just to check it wasn't overwritten
-    bool success = decode->translate(&buf, 1, bytes_processed, &res, 1, bytes_written);
+    bool success = decode->translate(&buf, 1, bytes_processed, &res, 1, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 1);
@@ -128,7 +128,7 @@ TEST(http2_hpack_string_decode_success, string_len_1)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res = 0;
-    bool success = decode->translate(buf, 2, bytes_processed, &res, 1, bytes_written);
+    bool success = decode->translate(buf, 2, bytes_processed, &res, 1, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 2);
@@ -149,7 +149,7 @@ TEST(http2_hpack_string_decode_success, max_field_length)
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[MAX_OCTETS];
     bool success = decode->translate(buf, MAX_OCTETS, bytes_processed, res,
-        MAX_OCTETS, bytes_written);
+        MAX_OCTETS, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == MAX_OCTETS);
@@ -164,7 +164,7 @@ TEST(http2_hpack_string_decode_success, huffman_1_byte)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[1];
-    bool success = decode->translate(buf, 2, bytes_processed, res, 1, bytes_written);
+    bool success = decode->translate(buf, 2, bytes_processed, res, 1, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 2);
@@ -179,7 +179,7 @@ TEST(http2_hpack_string_decode_success, huffman_1_byte_star)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[1];
-    bool success = decode->translate(buf, 2, bytes_processed, res, 1, bytes_written);
+    bool success = decode->translate(buf, 2, bytes_processed, res, 1, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 2);
@@ -194,7 +194,7 @@ TEST(http2_hpack_string_decode_success, huffman_2_bytes_aligned)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[3];
-    bool success = decode->translate(buf, 3, bytes_processed, res, 3, bytes_written);
+    bool success = decode->translate(buf, 3, bytes_processed, res, 3, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 3);
@@ -209,7 +209,7 @@ TEST(http2_hpack_string_decode_success, huffman_2_bytes_unaligned)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[3];
-    bool success = decode->translate(buf, 3, bytes_processed, res, 3, bytes_written);
+    bool success = decode->translate(buf, 3, bytes_processed, res, 3, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 3);
@@ -224,7 +224,7 @@ TEST(http2_hpack_string_decode_success, huffman_rfc_example1)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[19];
-    bool success = decode->translate(buf, 13, bytes_processed, res, 19, bytes_written);
+    bool success = decode->translate(buf, 13, bytes_processed, res, 19, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 13);
@@ -239,7 +239,7 @@ TEST(http2_hpack_string_decode_success, huffman_rfc_example2)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[9];
-    bool success = decode->translate(buf, 7, bytes_processed, res, 9, bytes_written);
+    bool success = decode->translate(buf, 7, bytes_processed, res, 9, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 7);
@@ -254,7 +254,7 @@ TEST(http2_hpack_string_decode_success, huffman_rfc_example3)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[12];
-    bool success = decode->translate(buf, 9, bytes_processed, res, 12, bytes_written);
+    bool success = decode->translate(buf, 9, bytes_processed, res, 12, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 9);
@@ -269,7 +269,7 @@ TEST(http2_hpack_string_decode_success, huffman_rfc_example4)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[14];
-    bool success = decode->translate(buf, 10, bytes_processed, res, 14, bytes_written);
+    bool success = decode->translate(buf, 10, bytes_processed, res, 14, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 10);
@@ -285,7 +285,7 @@ TEST(http2_hpack_string_decode_success, huffman_rfc_example5)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[35];
-    bool success = decode->translate(buf, 23, bytes_processed, res, 35, bytes_written);
+    bool success = decode->translate(buf, 23, bytes_processed, res, 35, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 23);
@@ -303,7 +303,7 @@ TEST(http2_hpack_string_decode_success, huffman_rfc_example6)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[73];
-    bool success = decode->translate(buf, 46, bytes_processed, res, 73, bytes_written);
+    bool success = decode->translate(buf, 46, bytes_processed, res, 73, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 46);
@@ -318,7 +318,7 @@ TEST(http2_hpack_string_decode_success, huffman_unaligned_then_aligned)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[6];
-    bool success = decode->translate(buf, 5, bytes_processed, res, 6, bytes_written);
+    bool success = decode->translate(buf, 5, bytes_processed, res, 6, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 5);
@@ -334,7 +334,7 @@ TEST(http2_hpack_string_decode_success, huffman_decoding_all_possible_symbols_1)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[32];
-    bool success = decode->translate(buf, 21, bytes_processed, res, 32, bytes_written);
+    bool success = decode->translate(buf, 21, bytes_processed, res, 32, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 21);
@@ -350,7 +350,7 @@ TEST(http2_hpack_string_decode_success, huffman_decoding_all_possible_symbols_2)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[36];
-    bool success = decode->translate(buf, 24, bytes_processed, res, 36, bytes_written);
+    bool success = decode->translate(buf, 24, bytes_processed, res, 36, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 24);
@@ -365,7 +365,7 @@ TEST(http2_hpack_string_decode_success, huffman_decoding_all_possible_symbols_3)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[12];
-    bool success = decode->translate(buf, 9, bytes_processed, res, 12, bytes_written);
+    bool success = decode->translate(buf, 9, bytes_processed, res, 12, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 9);
@@ -380,7 +380,7 @@ TEST(http2_hpack_string_decode_success, huffman_decoding_all_possible_symbols_4)
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[70];
-    bool success = decode->translate(buf, 45, bytes_processed, res, 70, bytes_written);
+    bool success = decode->translate(buf, 45, bytes_processed, res, 70, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 45);
@@ -396,7 +396,7 @@ TEST(http2_hpack_string_decode_success, huffman_decoding_all_possible_symbols_he
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[88];
     uint8_t expected[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
-    bool success = decode->translate(buf, 55, bytes_processed, res, 88, bytes_written);
+    bool success = decode->translate(buf, 55, bytes_processed, res, 88, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 55);
@@ -412,7 +412,7 @@ TEST(http2_hpack_string_decode_success, huffman_decoding_all_possible_symbols_he
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[93];
     uint8_t expected[16] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};
-    bool success = decode->translate(buf, 58, bytes_processed, res, 93, bytes_written);
+    bool success = decode->translate(buf, 58, bytes_processed, res, 93, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 58);
@@ -428,7 +428,7 @@ TEST(http2_hpack_string_decode_success, huffman_decoding_all_possible_symbols_he
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[79];
     uint8_t expected[17] = {0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F};
-    bool success = decode->translate(buf, 49, bytes_processed, res, 79, bytes_written);
+    bool success = decode->translate(buf, 49, bytes_processed, res, 79, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 49);
@@ -445,7 +445,7 @@ TEST(http2_hpack_string_decode_success, huffman_decoding_all_possible_symbols_he
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[76];
     uint8_t expected[16] = {0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F};
-    bool success = decode->translate(buf, 47, bytes_processed, res, 76, bytes_written);
+    bool success = decode->translate(buf, 47, bytes_processed, res, 76, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 47);
@@ -461,7 +461,7 @@ TEST(http2_hpack_string_decode_success, huffman_decoding_all_possible_symbols_he
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[74];
     uint8_t expected[16] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF};
-    bool success = decode->translate(buf, 46, bytes_processed, res, 74, bytes_written);
+    bool success = decode->translate(buf, 46, bytes_processed, res, 74, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 46);
@@ -478,7 +478,7 @@ TEST(http2_hpack_string_decode_success, huffman_decoding_all_possible_symbols_he
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[73];
     uint8_t expected[16] = {0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF};
-    bool success = decode->translate(buf, 45, bytes_processed, res, 73, bytes_written);
+    bool success = decode->translate(buf, 45, bytes_processed, res, 73, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 45);
@@ -495,7 +495,7 @@ TEST(http2_hpack_string_decode_success, huffman_decoding_all_possible_symbols_he
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[80];
     uint8_t expected[16] = {0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF};
-    bool success = decode->translate(buf, 50, bytes_processed, res, 80, bytes_written);
+    bool success = decode->translate(buf, 50, bytes_processed, res, 80, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 50);
@@ -512,7 +512,7 @@ TEST(http2_hpack_string_decode_success, huffman_decoding_all_possible_symbols_he
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[82];
     uint8_t expected[16] = {0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF};
-    bool success = decode->translate(buf, 51, bytes_processed, res, 82, bytes_written);
+    bool success = decode->translate(buf, 51, bytes_processed, res, 82, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 51);
@@ -529,7 +529,7 @@ TEST(http2_hpack_string_decode_success, huffman_decoding_all_possible_symbols_he
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[76];
     uint8_t expected[16] = {0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF};
-    bool success = decode->translate(buf, 47, bytes_processed, res, 76, bytes_written);
+    bool success = decode->translate(buf, 47, bytes_processed, res, 76, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 47);
@@ -546,7 +546,7 @@ TEST(http2_hpack_string_decode_success, huffman_decoding_all_possible_symbols_he
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[88];
     uint8_t expected[16] = {0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF};
-    bool success = decode->translate(buf, 55, bytes_processed, res, 88, bytes_written);
+    bool success = decode->translate(buf, 55, bytes_processed, res, 88, bytes_written, &events, &inf);
     // check results
     CHECK(success == true);
     CHECK(bytes_processed == 55);
@@ -566,13 +566,13 @@ TEST(http2_hpack_string_decode_infractions, 0_len_field)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackStringDecode local_decode(&local_events, &local_inf);
+    Http2HpackStringDecode local_decode;
     // prepare buf to decode - use field length 0
     uint8_t buf = 0;
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res;
-    bool success = local_decode.translate(&buf, 0, bytes_processed, &res, 1, bytes_written);
+    bool success = local_decode.translate(&buf, 0, bytes_processed, &res, 1, bytes_written, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 0);
@@ -586,13 +586,13 @@ TEST(http2_hpack_string_decode_infractions, missing_bytes)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackStringDecode local_decode(&local_events, &local_inf);
+    Http2HpackStringDecode local_decode;
     // prepare buf to decode - length is 1, no string
     uint8_t buf = 1;
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[2];
-    bool success = local_decode.translate(&buf, 1, bytes_processed, res, 2, bytes_written);
+    bool success = local_decode.translate(&buf, 1, bytes_processed, res, 2, bytes_written, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_written == 0);
@@ -606,13 +606,13 @@ TEST(http2_hpack_string_decode_infractions, bad_int)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackStringDecode local_decode(&local_events, &local_inf);
+    Http2HpackStringDecode local_decode;
     // prepare buf to decode - bad int
     uint8_t buf[2] = { 0x7f, 0x80 };
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[2];
-    bool success = local_decode.translate(buf, 2, bytes_processed, res, 2, bytes_written);
+    bool success = local_decode.translate(buf, 2, bytes_processed, res, 2, bytes_written, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 2);
@@ -626,7 +626,7 @@ TEST(http2_hpack_string_decode_infractions, max_field_length_plus_1)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackStringDecode local_decode(&local_events, &local_inf);
+    Http2HpackStringDecode local_decode;
     // prepare buf to decode -  int + string == MAX_OCTETS+1 (Field limitation + 1)
     uint8_t buf[MAX_OCTETS];
     buf[0] = 0x7F;
@@ -638,7 +638,7 @@ TEST(http2_hpack_string_decode_infractions, max_field_length_plus_1)
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[MAX_OCTETS];
     bool success = local_decode.translate(buf, MAX_OCTETS, bytes_processed, res,
-        MAX_OCTETS, bytes_written);
+        MAX_OCTETS, bytes_written, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 4);
@@ -652,7 +652,7 @@ TEST(http2_hpack_string_decode_infractions, out_buf_out_of_space)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackStringDecode local_decode(&local_events, &local_inf);
+    Http2HpackStringDecode local_decode;
     // prepare buf to decode
     uint8_t buf[MAX_OCTETS];
     buf[0] = 0x7F;
@@ -664,13 +664,13 @@ TEST(http2_hpack_string_decode_infractions, out_buf_out_of_space)
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[MAX_OCTETS-5];
     bool success = local_decode.translate(buf, MAX_OCTETS, bytes_processed, res,
-        MAX_OCTETS-5, bytes_written);
+        MAX_OCTETS-5, bytes_written, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 4);
     CHECK(bytes_written == 0);
-    CHECK(local_inf.get_raw() == (1<<INF_OUT_BUFF_OUT_OF_SPACE));
-    CHECK(local_events.get_raw() == (1<<(EVENT_STRING_DECODE_FAILURE-1)));
+    CHECK(local_inf.get_raw() == (1<<INF_DECODED_HEADER_BUFF_OUT_OF_SPACE));
+    CHECK(local_events.get_raw() == (1<<(EVENT_MISFORMATTED_HTTP2-1)));
 }
 
 TEST(http2_hpack_string_decode_infractions, huffman_1_byte_bad_padding)
@@ -678,13 +678,13 @@ TEST(http2_hpack_string_decode_infractions, huffman_1_byte_bad_padding)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackStringDecode local_decode(&local_events, &local_inf);
+    Http2HpackStringDecode local_decode;
     // prepare buf to decode - bad padding
     uint8_t buf[2] = { 0x81, 0x54 };
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[2];
-    bool success = local_decode.translate(buf, 2, bytes_processed, res, 2, bytes_written);
+    bool success = local_decode.translate(buf, 2, bytes_processed, res, 2, bytes_written, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 2);
@@ -698,13 +698,13 @@ TEST(http2_hpack_string_decode_infractions, huffman_1_byte_incomplete_FF)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackStringDecode local_decode(&local_events, &local_inf);
+    Http2HpackStringDecode local_decode;
     // prepare buf to decode - Incomplete code 0xFF
     uint8_t buf[2] = { 0x81, 0xFF };
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[2];
-    bool success = local_decode.translate(buf, 2, bytes_processed, res, 2, bytes_written);
+    bool success = local_decode.translate(buf, 2, bytes_processed, res, 2, bytes_written, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 2);
@@ -718,13 +718,13 @@ TEST(http2_hpack_string_decode_infractions, huffman_1_byte_incomplete_FE)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackStringDecode local_decode(&local_events, &local_inf);
+    Http2HpackStringDecode local_decode;
     // prepare buf to decode - Incomplete code 0xFE
     uint8_t buf[2] = { 0x81, 0xFE };
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[2];
-    bool success = local_decode.translate(buf, 2, bytes_processed, res, 2, bytes_written);
+    bool success = local_decode.translate(buf, 2, bytes_processed, res, 2, bytes_written, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 2);
@@ -738,13 +738,13 @@ TEST(http2_hpack_string_decode_infractions, huffman_2_bytes_incomplete_FF_FE)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackStringDecode local_decode(&local_events, &local_inf);
+    Http2HpackStringDecode local_decode;
     // prepare buf to decode - Incomplete code 0xFFFE
     uint8_t buf[3] = { 0x82, 0xFF, 0xFE };
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[5];
-    bool success = local_decode.translate(buf, 3, bytes_processed, res, 5, bytes_written);
+    bool success = local_decode.translate(buf, 3, bytes_processed, res, 5, bytes_written, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 3);
@@ -758,13 +758,13 @@ TEST(http2_hpack_string_decode_infractions, huffman_3_bytes_incomplete)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackStringDecode local_decode(&local_events, &local_inf);
+    Http2HpackStringDecode local_decode;
     // prepare buf to decode - Incomplete code 0xFFFFFE
     uint8_t buf[4] = { 0x83, 0xFF, 0xFF, 0xFE };
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[7];
-    bool success = local_decode.translate(buf, 4, bytes_processed, res, 7, bytes_written);
+    bool success = local_decode.translate(buf, 4, bytes_processed, res, 7, bytes_written, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 4);
@@ -778,13 +778,13 @@ TEST(http2_hpack_string_decode_infractions, huffman_FB_incomplete_FF)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackStringDecode local_decode(&local_events, &local_inf);
+    Http2HpackStringDecode local_decode;
     // prepare buf to decode - ';' (8 bits) and incomplete code 0xFF
     uint8_t buf[3] = { 0x82, 0xFB, 0xFF };
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[5];
-    bool success = local_decode.translate(buf, 3, bytes_processed, res, 5, bytes_written);
+    bool success = local_decode.translate(buf, 3, bytes_processed, res, 5, bytes_written, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 3);
@@ -799,13 +799,13 @@ TEST(http2_hpack_string_decode_infractions, huffman_07_incomplete_FF)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackStringDecode local_decode(&local_events, &local_inf);
+    Http2HpackStringDecode local_decode;
     // prepare buf to decode - '0' (5 bits) and incomplete code 0xFF with padding
     uint8_t buf[3] = { 0x82, 0x07, 0xFF };
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[5];
-    bool success = local_decode.translate(buf, 3, bytes_processed, res, 5, bytes_written);
+    bool success = local_decode.translate(buf, 3, bytes_processed, res, 5, bytes_written, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 3);
@@ -820,13 +820,13 @@ TEST(http2_hpack_string_decode_infractions, huffman_decoded_eos)
     // prepare decode object
     Http2EventGen local_events;
     Http2Infractions local_inf;
-    Http2HpackStringDecode local_decode(&local_events, &local_inf);
+    Http2HpackStringDecode local_decode;
     // prepare buf to decode - bad padding
     uint8_t buf[5] = { 0x84, 0xFF, 0xFF, 0xFF, 0xFF };
     // decode
     uint32_t bytes_processed = 0, bytes_written = 0;
     uint8_t res[10];
-    bool success = local_decode.translate(buf, 5, bytes_processed, res, 10, bytes_written);
+    bool success = local_decode.translate(buf, 5, bytes_processed, res, 10, bytes_written, &local_events, &local_inf);
     // check results
     CHECK(success == false);
     CHECK(bytes_processed == 4);
index c9527e276ddcc5f1aba059bfa35d12b78c6269b4..5e8fa7e6820ec751e4974f9446f7c7fdc512f764 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "protocols/packet.h"
 #include "service_inspectors/http_inspect/http_common.h"
+#include "service_inspectors/http_inspect/http_field.h"
 #include "service_inspectors/http_inspect/http_test_manager.h"
 #include "service_inspectors/http2_inspect/http2_enum.h"
 
@@ -36,6 +37,8 @@
 #include <CppUTest/TestHarness.h>
 #include <CppUTestExt/MockSupport.h>
 
+#include <cstdio>
+
 using namespace snort;
 using namespace HttpCommon;
 using namespace Http2Enums;
@@ -44,6 +47,7 @@ using namespace Http2Enums;
 unsigned HttpTestManager::test_input = IN_NONE;
 unsigned HttpTestManager::test_output = IN_NONE;
 int DetectionEngine::queue_event(unsigned int, unsigned int, Actions::Type) { return 0; }
+void Field::print(FILE*, char const*) const {}
 
 TEST_GROUP(http2_get_buf_test)
 {
index 85f7d8460ac8e4debb25ba3337fdae3243500052..50b5d14ecd2cef6933967e7e22f2e21de1394b7f 100644 (file)
 #include "config.h"
 #endif
 
-#include "service_inspectors/http2_inspect/http2_stream_splitter.h"
 
 #include "protocols/packet.h"
 #include "service_inspectors/http_inspect/http_common.h"
 #include "service_inspectors/http_inspect/http_test_manager.h"
 #include "service_inspectors/http2_inspect/http2_enum.h"
 #include "service_inspectors/http2_inspect/http2_flow_data.h"
+#include "service_inspectors/http2_inspect/http2_hpack_int_decode.h"
+#include "service_inspectors/http2_inspect/http2_hpack_string_decode.h"
+#include "service_inspectors/http2_inspect/http2_stream_splitter.h"
 
 #include "http2_flow_data_test.h"
 
@@ -44,7 +46,9 @@ using namespace Http2Enums;
 // Stubs whose sole purpose is to make the test code link
 unsigned HttpTestManager::test_input = IN_NONE;
 unsigned HttpTestManager::test_output = IN_NONE;
+FILE* HttpTestManager::test_out = nullptr ;
 int DetectionEngine::queue_event(unsigned int, unsigned int, Actions::Type) { return 0; }
+void Field::print(_IO_FILE*, char const*) const {}
 
 TEST_GROUP(http2_scan_test)
 {