diff --git a/rust/src/http2/detect.rs b/rust/src/http2/detect.rs index d9a28f947b..040c87e7e0 100644 --- a/rust/src/http2/detect.rs +++ b/rust/src/http2/detect.rs @@ -741,11 +741,29 @@ fn http2_escape_header(blocks: &[parser::HTTP2FrameHeaderBlock], i: u32) -> Vec< return vec; } +#[derive(Default)] +struct Http2ThreadBuf { + data: Vec, +} + +#[no_mangle] +pub unsafe extern "C" fn SCHttp2ThreadBufDataInit(_cfg: *mut c_void) -> *mut c_void { + let boxed = Box::new(Http2ThreadBuf::default()); + return Box::into_raw(boxed) as *mut c_void; +} + +#[no_mangle] +pub unsafe extern "C" fn SCHttp2ThreadBufDataFree(ctx: *mut c_void) { + std::mem::drop(Box::from_raw(ctx as *mut Http2ThreadBuf)); +} + #[no_mangle] pub unsafe extern "C" fn SCHttp2TxGetHeaderNames( tx: &mut HTTP2Transaction, direction: u8, buffer: *mut *const u8, buffer_len: *mut u32, + tbuf: *mut c_void, ) -> u8 { - let mut vec = vec![b'\r', b'\n']; + let tbuf = cast_pointer!(tbuf, Http2ThreadBuf); + tbuf.data = vec![b'\r', b'\n']; let frames = if direction & Direction::ToServer as u8 != 0 { &tx.frames_ts } else { @@ -755,18 +773,15 @@ pub unsafe extern "C" fn SCHttp2TxGetHeaderNames( if let Some(blocks) = http2_header_blocks(frame) { for block in blocks.iter() { // we do not escape linefeeds in headers names - vec.extend_from_slice(&block.name); - vec.extend_from_slice(b"\r\n"); + tbuf.data.extend_from_slice(&block.name); + tbuf.data.extend_from_slice(b"\r\n"); } } } - if vec.len() > 2 { - vec.extend_from_slice(b"\r\n"); - tx.escaped.push(vec); - let idx = tx.escaped.len() - 1; - let value = &tx.escaped[idx]; - *buffer = value.as_ptr(); //unsafe - *buffer_len = value.len() as u32; + if tbuf.data.len() > 2 { + tbuf.data.extend_from_slice(b"\r\n"); + *buffer = tbuf.data.as_ptr(); //unsafe + *buffer_len = tbuf.data.len() as u32; return 1; } return 0; diff --git a/src/detect-http-header-names.c b/src/detect-http-header-names.c index 9839d2b079..6bfbb9a4dd 100644 --- a/src/detect-http-header-names.c +++ b/src/detect-http-header-names.c @@ -71,6 +71,7 @@ #define BUFFER_DESC "http header names" static int g_buffer_id = 0; static int g_keyword_thread_id = 0; +static int g_http2_thread_id = 0; #define BUFFER_SIZE_STEP 256 static HttpHeaderThreadDataConfig g_td_config = { BUFFER_SIZE_STEP }; @@ -170,7 +171,11 @@ static InspectionBuffer *GetBuffer2ForTX(DetectEngineThreadCtx *det_ctx, uint32_t b_len = 0; const uint8_t *b = NULL; - if (SCHttp2TxGetHeaderNames(txv, flow_flags, &b, &b_len) != 1) + void *thread_buf = DetectThreadCtxGetGlobalKeywordThreadCtx(det_ctx, g_http2_thread_id); + if (thread_buf == NULL) + return NULL; + + if (SCHttp2TxGetHeaderNames(txv, flow_flags, &b, &b_len, thread_buf) != 1) return NULL; if (b == NULL || b_len == 0) return NULL; @@ -248,6 +253,9 @@ void DetectHttpHeaderNamesRegister(void) g_keyword_thread_id = DetectRegisterThreadCtxGlobalFuncs(KEYWORD_NAME, HttpHeaderThreadDataInit, &g_td_config, HttpHeaderThreadDataFree); + g_http2_thread_id = DetectRegisterThreadCtxGlobalFuncs( + "http2.header_names", SCHttp2ThreadBufDataInit, NULL, SCHttp2ThreadBufDataFree); + SCLogDebug("keyword %s registered. Thread id %d. " "Buffer %s registered. Buffer id %d", KEYWORD_NAME, g_keyword_thread_id,