#include "http_field.h"
+#include "flow/flow_data.h"
#include "http_common.h"
#include "http_enum.h"
#include "http_test_manager.h"
// Both Fields cannot be responsible for deleting the buffer so do not copy own_the_buffer
}
+void Field::update_allocations(snort::FlowData* flow_data)
+{
+ if (own_the_buffer && (len > 0))
+ flow_data->update_allocations(len);
+}
+
+void Field::update_deallocations(snort::FlowData* flow_data)
+{
+ if (own_the_buffer && (len > 0))
+ flow_data->update_deallocations(len);
+}
+
#ifdef REG_TEST
void Field::print(FILE* output, const char* name) const
{
#include "http_common.h"
#include "http_enum.h"
+namespace snort
+{
+class FlowData;
+}
+
// Individual pieces of the message found during parsing.
// Length values <= 0 are StatusCode values and imply that the start pointer is meaningless.
// Never use the start pointer without verifying that length > 0.
void set(const Field& f);
void set(HttpCommon::StatusCode stat_code);
void set(int32_t length) { set(static_cast<HttpCommon::StatusCode>(length)); }
+ void update_allocations(snort::FlowData* flow_data);
+ void update_deallocations(snort::FlowData* flow_data);
#ifdef REG_TEST
void print(FILE* output, const char* name) const;
{
pipeline = new HttpTransaction*[MAX_PIPELINE];
HttpModule::increment_peg_counts(PEG_PIPELINED_FLOWS);
+ update_allocations(sizeof(HttpTransaction*) * MAX_PIPELINE);
}
assert(!pipeline_overflow && !pipeline_underflow);
int new_back = (pipeline_back+1) % MAX_PIPELINE;
{
delete pipeline[k];
}
+ if (pipeline != nullptr)
+ update_deallocations(sizeof(HttpTransaction*) * MAX_PIPELINE);
delete[] pipeline;
}
using namespace HttpEnums;
using namespace snort;
+// Memory calculation:
+// Approximations based on assumptions:
+// - there will be a cookie
+// - http_header and http_cookie rule options will be required
+// - classic normalization on the headers will not be trivial
+// - individual normalized headers won't be a lot and 500 bytes will cover them
+//
+// Header infrastructure (header_line, header_name, header_name_id, header_value):
+// session_data_->num_head_lines[source_id_] * (3 * sizeof(Field) + sizeof(HeaderId))
+//
+// The entire headers consist of http_raw_header and http_raw_cookie. Because there is
+// a cookie it will be necessary to write out the full msg_text into these two buffers,
+// resulting in allocations totaling approximately msg_text.length(). These raw buffers
+// in turn will need to be normalized, requiring another msg_text.length().
+// Total cost: 2 * msg_text.length().
+//
+// Plus 500 bytes for normalized headers.
HttpMsgHeadShared::HttpMsgHeadShared(const uint8_t* buffer, const uint16_t buf_size, HttpFlowData* session_data_,
HttpCommon::SourceId source_id_, bool buf_owner, snort::Flow* flow_,
const HttpParaList* params_): HttpMsgSection(buffer, buf_size, session_data_, source_id_,
- buf_owner, flow_, params_), own_msg_buffer(buf_owner)
+ buf_owner, flow_, params_), own_msg_buffer(buf_owner),
+ extra_memory_allocations(session_data_->num_head_lines[source_id_] *
+ (3 * sizeof(Field) + sizeof(HeaderId)) + 2 * msg_text.length() + 500)
{
if (own_msg_buffer)
session_data->update_allocations(msg_text.length());
+
+ session_data->update_allocations(extra_memory_allocations);
}
HttpMsgHeadShared::~HttpMsgHeadShared()
if (own_msg_buffer)
session_data->update_deallocations(msg_text.length());
+
+ session_data->update_deallocations(extra_memory_allocations);
}
// All the header processing that is done for every message (i.e. not just-in-time) is done here.
bool file_cache_index_computed = false;
bool own_msg_buffer;
+ const uint32_t extra_memory_allocations;
};
#endif
{
uri = new HttpUri(start_line.start() + first_end + 1, last_begin - first_end - 1,
method_id, params->uri_param, transaction->get_infractions(source_id),
- session_data->events[source_id]);
+ session_data->events[source_id], session_data);
}
else
{
uri_end--);
uri = new HttpUri(start_line.start() + uri_begin, uri_end - uri_begin + 1, method_id,
params->uri_param, transaction->get_infractions(source_id),
- session_data->events[source_id]);
+ session_data->events[source_id], session_data);
}
else
{
#include "http_common.h"
#include "http_enum.h"
+#include "http_flow_data.h"
#include "hash/hash_key_operations.h"
using namespace HttpCommon;
using namespace HttpEnums;
using namespace snort;
+HttpUri::HttpUri(const uint8_t* start, int32_t length, HttpEnums::MethodId method_id_,
+ const HttpParaList::UriParam& uri_param_, HttpInfractions* infractions_,
+ HttpEventGen* events_, HttpFlowData* session_data_) :
+ uri(length, start), infractions(infractions_), events(events_), method_id(method_id_),
+ uri_param(uri_param_), session_data(session_data_)
+{
+ normalize();
+ classic_norm.update_allocations(session_data);
+}
+
+HttpUri::~HttpUri()
+{
+ classic_norm.update_deallocations(session_data);
+}
+
void HttpUri::parse_uri()
{
// Four basic types of HTTP URI
return host_norm;
}
+
#ifndef HTTP_URI_H
#define HTTP_URI_H
-#include "http_str_to_code.h"
+#include "http_event.h"
+#include "http_field.h"
#include "http_module.h"
+#include "http_str_to_code.h"
#include "http_uri_norm.h"
-#include "http_field.h"
-#include "http_event.h"
+
+class HttpFlowData;
static const int MAX_SCHEME_LENGTH = 36; // schemes longer than 36 characters are malformed
static const int LONG_SCHEME_LENGTH = 10; // schemes longer than 10 characters will alert
public:
HttpUri(const uint8_t* start, int32_t length, HttpEnums::MethodId method_id_,
const HttpParaList::UriParam& uri_param_, HttpInfractions* infractions_,
- HttpEventGen* events_) :
- uri(length, start), infractions(infractions_), events(events_), method_id(method_id_),
- uri_param(uri_param_)
- { normalize(); }
+ HttpEventGen* events_, HttpFlowData* session_data_);
+ ~HttpUri();
const Field& get_uri() const { return uri; }
HttpEnums::UriType get_uri_type() { return uri_type; }
const Field& get_scheme() { return scheme; }
HttpEnums::UriType uri_type = HttpEnums::URI__NOT_COMPUTE;
const HttpEnums::MethodId method_id;
const HttpParaList::UriParam& uri_param;
+ HttpFlowData* const session_data;
void normalize();
void parse_uri();
HttpJsNorm::~HttpJsNorm() = default;
void HttpJsNorm::configure(){}
int64_t Parameter::get_int(char const*) { return 0; }
+void FlowData::update_allocations(unsigned long) {}
+void FlowData::update_deallocations(unsigned long) {}
TEST_GROUP(http_peg_count_test)
{
// Stubs whose sole purpose is to make the test code link
long HttpTestManager::print_amount {};
bool HttpTestManager::print_hex {};
+void FlowData::update_allocations(unsigned long) {}
+void FlowData::update_deallocations(unsigned long) {}
// Tests for get_next_code()
TEST_GROUP(get_next_code)
const bool HttpEnums::is_sp_tab_quote_dquote[256] {};
long HttpTestManager::print_amount {};
bool HttpTestManager::print_hex {};
+void FlowData::update_allocations(unsigned long) {}
+void FlowData::update_deallocations(unsigned long) {}
TEST_GROUP(norm_decimal_integer_test) {};
HttpJsNorm::~HttpJsNorm() = default;
void HttpJsNorm::configure() {}
int64_t Parameter::get_int(char const*) { return 0; }
+void FlowData::update_allocations(unsigned long) {}
+void FlowData::update_deallocations(unsigned long) {}
TEST_GROUP(http_inspect_uri_norm)
{