• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jasonish / suricata / 22873444665

08 Mar 2026 06:10PM UTC coverage: 79.306% (-0.009%) from 79.315%
22873444665

push

github

victorjulien
dpdk: adjust burst size to mempool size

When mempool size was configured really low (<32), Suricata exhausted
the mempool with the rx_burst call, which led to undefined behavior.
The current fix ensures the burst size is at most the size of the mempool,
if the mempool is smaller than BURST_SIZE macro.

3 of 3 new or added lines in 1 file covered. (100.0%)

678 existing lines in 28 files now uncovered.

265817 of 335177 relevant lines covered (79.31%)

4878829.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.12
/src/detect-http-header-names.c
1
/* Copyright (C) 2007-2017 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17

18
/**
19
 * \ingroup httplayer
20
 *
21
 * @{
22
 */
23

24

25
/**
26
 * \file
27
 *
28
 * \author Victor Julien <victor@inliniac.net>
29
 *
30
 * Implements support http_header_names
31
 */
32

33
#include "suricata-common.h"
34
#include "threads.h"
35
#include "decode.h"
36

37
#include "detect.h"
38
#include "detect-parse.h"
39
#include "detect-engine.h"
40
#include "detect-engine-buffer.h"
41
#include "detect-engine-mpm.h"
42
#include "detect-engine-state.h"
43
#include "detect-engine-prefilter.h"
44
#include "detect-engine-content-inspection.h"
45
#include "detect-content.h"
46
#include "detect-pcre.h"
47
#include "detect-http-header-common.h"
48
#include "detect-http-header-names.h"
49

50
#include "flow.h"
51
#include "flow-var.h"
52
#include "flow-util.h"
53

54
#include "util-debug.h"
55
#include "util-unittest.h"
56
#include "util-unittest-helper.h"
57
#include "util-spm.h"
58
#include "util-print.h"
59

60
#include "app-layer.h"
61
#include "app-layer-parser.h"
62

63
#include "app-layer-htp.h"
64
#include "detect-http-header.h"
65
#include "stream-tcp.h"
66

67
#define KEYWORD_NAME "http.header_names"
4,446✔
68
#define KEYWORD_NAME_LEGACY "http_header_names"
2,223✔
69
#define KEYWORD_DOC "http-keywords.html#http-header-names"
2,223✔
70
#define BUFFER_NAME "http_header_names"
24,453✔
71
#define BUFFER_DESC "http header names"
2,223✔
72
static int g_buffer_id = 0;
73
static int g_keyword_thread_id = 0;
74

75
#define BUFFER_SIZE_STEP    256
76
static HttpHeaderThreadDataConfig g_td_config = { BUFFER_SIZE_STEP };
77

78
static uint8_t *GetBufferForTX(
79
        htp_tx_t *tx, DetectEngineThreadCtx *det_ctx, uint8_t flags, uint32_t *buffer_len)
80
{
4,865✔
81
    *buffer_len = 0;
4,865✔
82

83
    HttpHeaderThreadData *hdr_td = NULL;
4,865✔
84
    HttpHeaderBuffer *buf = HttpHeaderGetBufferSpace(det_ctx, flags, g_keyword_thread_id, &hdr_td);
4,865✔
85
    if (unlikely(buf == NULL)) {
4,865✔
UNCOV
86
        return NULL;
×
87
    }
×
88

89
    const htp_headers_t *headers;
4,865✔
90
    if (flags & STREAM_TOSERVER) {
4,865✔
91
        if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP1, tx, flags) <=
2,569✔
92
                HTP_REQUEST_PROGRESS_HEADERS)
2,569✔
93
            return NULL;
279✔
94
        headers = htp_tx_request_headers(tx);
2,290✔
95
    } else {
2,334✔
96
        if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP1, tx, flags) <=
2,296✔
97
                HTP_RESPONSE_PROGRESS_HEADERS)
2,296✔
98
            return NULL;
64✔
99
        headers = htp_tx_response_headers(tx);
2,232✔
100
    }
2,232✔
101
    if (headers == NULL)
4,522✔
UNCOV
102
        return NULL;
×
103

104
    /* fill the buffer. \r\nName1\r\nName2\r\n\r\n */
105
    size_t i = 0;
4,522✔
106
    size_t no_of_headers = htp_headers_size(headers);
4,522✔
107
    for (; i < no_of_headers; i++) {
34,606✔
108
        const htp_header_t *h = htp_headers_get_index(headers, i);
30,084✔
109
        size_t size = htp_header_name_len(h) + 2; // for \r\n
30,084✔
110
        if (i == 0)
30,084✔
111
            size += 2;
4,288✔
112
        if (i + 1 == no_of_headers)
30,084✔
113
            size += 2;
4,288✔
114

115
        SCLogDebug("size %"PRIuMAX" + buf->len %u vs buf->size %u",
30,084✔
116
                (uintmax_t)size, buf->len, buf->size);
30,084✔
117
        if (size + buf->len > buf->size) {
30,084✔
118
            if (HttpHeaderExpandBuffer(hdr_td, buf, size) != 0) {
4✔
UNCOV
119
                return NULL;
×
120
            }
×
121
        }
4✔
122

123
        /* start with a \r\n */
124
        if (i == 0) {
30,084✔
125
            buf->buffer[buf->len++] = '\r';
4,288✔
126
            buf->buffer[buf->len++] = '\n';
4,288✔
127
        }
4,288✔
128

129
        memcpy(buf->buffer + buf->len, htp_header_name_ptr(h), htp_header_name_len(h));
30,084✔
130
        buf->len += htp_header_name_len(h);
30,084✔
131
        buf->buffer[buf->len++] = '\r';
30,084✔
132
        buf->buffer[buf->len++] = '\n';
30,084✔
133

134
        /* end with an extra \r\n */
135
        if (i + 1 == no_of_headers) {
30,084✔
136
            buf->buffer[buf->len++] = '\r';
4,289✔
137
            buf->buffer[buf->len++] = '\n';
4,289✔
138
        }
4,289✔
139
    }
30,084✔
140

141
    *buffer_len = buf->len;
4,522✔
142
    return buf->buffer;
4,522✔
143
}
4,522✔
144

145
static InspectionBuffer *GetBuffer1ForTX(DetectEngineThreadCtx *det_ctx,
146
        const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
147
        const int list_id)
148
{
7,735✔
149
    InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
7,735✔
150
    if (buffer->inspect == NULL) {
7,735✔
151
        uint32_t rawdata_len = 0;
4,865✔
152
        uint8_t *rawdata = GetBufferForTX(txv, det_ctx, flow_flags, &rawdata_len);
4,865✔
153
        if (rawdata_len == 0)
4,865✔
154
            return NULL;
577✔
155

156
        InspectionBufferSetupAndApplyTransforms(
4,288✔
157
                det_ctx, list_id, buffer, rawdata, rawdata_len, transforms);
4,288✔
158
    }
4,288✔
159

160
    return buffer;
7,158✔
161
}
7,735✔
162

163
static InspectionBuffer *GetBuffer2ForTX(DetectEngineThreadCtx *det_ctx,
164
        const DetectEngineTransforms *transforms, Flow *_f, const uint8_t flow_flags, void *txv,
165
        const int list_id)
166
{
1,088✔
167
    InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
1,088✔
168
    if (buffer->inspect == NULL) {
1,088✔
169
        uint32_t b_len = 0;
989✔
170
        const uint8_t *b = NULL;
989✔
171

172
        if (SCHttp2TxGetHeaderNames(txv, flow_flags, &b, &b_len) != 1)
989✔
173
            return NULL;
561✔
174
        if (b == NULL || b_len == 0)
428✔
175
            return NULL;
×
176

177
        InspectionBufferSetupAndApplyTransforms(det_ctx, list_id, buffer, b, b_len, transforms);
428✔
178
    }
428✔
179

180
    return buffer;
527✔
181
}
1,088✔
182

183
/**
184
 * \brief The setup function for the http.header_names keyword for a signature.
185
 *
186
 * \param de_ctx Pointer to the detection engine context.
187
 * \param s      Pointer to signature for the current Signature being parsed
188
 *               from the rules.
189
 * \param m      Pointer to the head of the SigMatchs for the current rule
190
 *               being parsed.
191
 * \param arg    Pointer to the string holding the keyword value.
192
 *
193
 * \retval  0 On success.
194
 * \retval -1 On failure.
195
 */
196
static int DetectHttpHeaderNamesSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
197
{
9,666✔
198
    if (SCDetectBufferSetActiveList(de_ctx, s, g_buffer_id) < 0)
9,666✔
199
        return -1;
2✔
200

201
    if (SCDetectSignatureSetAppProto(s, ALPROTO_HTTP) < 0)
9,664✔
202
        return -1;
1✔
203

204
    return 0;
9,663✔
205
}
9,664✔
206

207
/**
208
 * \brief Registers the keyword handlers for the "http.header_names" keyword.
209
 */
210
void DetectHttpHeaderNamesRegister(void)
211
{
2,223✔
212
    sigmatch_table[DETECT_HTTP_HEADER_NAMES].name = KEYWORD_NAME;
2,223✔
213
    sigmatch_table[DETECT_HTTP_HEADER_NAMES].alias = KEYWORD_NAME_LEGACY;
2,223✔
214
    sigmatch_table[DETECT_HTTP_HEADER_NAMES].desc = BUFFER_NAME " sticky buffer";
2,223✔
215
    sigmatch_table[DETECT_HTTP_HEADER_NAMES].url = "/rules/" KEYWORD_DOC;
2,223✔
216
    sigmatch_table[DETECT_HTTP_HEADER_NAMES].Setup = DetectHttpHeaderNamesSetup;
2,223✔
217

218
    sigmatch_table[DETECT_HTTP_HEADER_NAMES].flags |= SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER;
2,223✔
219

220
    /* http1 */
221
    DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
2,223✔
222
            GetBuffer1ForTX, ALPROTO_HTTP1, HTP_REQUEST_PROGRESS_HEADERS);
2,223✔
223
    DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister,
2,223✔
224
            GetBuffer1ForTX, ALPROTO_HTTP1, HTP_RESPONSE_PROGRESS_HEADERS);
2,223✔
225

226
    DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_HTTP1, SIG_FLAG_TOSERVER,
2,223✔
227
            HTP_REQUEST_PROGRESS_HEADERS, DetectEngineInspectBufferGeneric, GetBuffer1ForTX);
2,223✔
228
    DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_HTTP1, SIG_FLAG_TOCLIENT,
2,223✔
229
            HTP_RESPONSE_PROGRESS_HEADERS, DetectEngineInspectBufferGeneric, GetBuffer1ForTX);
2,223✔
230

231
    /* http2 */
232
    DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
2,223✔
233
            GetBuffer2ForTX, ALPROTO_HTTP2, HTTP2StateDataClient);
2,223✔
234
    DetectAppLayerMpmRegister(BUFFER_NAME, SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister,
2,223✔
235
            GetBuffer2ForTX, ALPROTO_HTTP2, HTTP2StateDataServer);
2,223✔
236

237
    DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_HTTP2, SIG_FLAG_TOSERVER,
2,223✔
238
            HTTP2StateDataClient, DetectEngineInspectBufferGeneric, GetBuffer2ForTX);
2,223✔
239
    DetectAppLayerInspectEngineRegister(BUFFER_NAME, ALPROTO_HTTP2, SIG_FLAG_TOCLIENT,
2,223✔
240
            HTTP2StateDataServer, DetectEngineInspectBufferGeneric, GetBuffer2ForTX);
2,223✔
241

242
    DetectBufferTypeSetDescriptionByName(BUFFER_NAME,
2,223✔
243
            BUFFER_DESC);
2,223✔
244

245
    g_buffer_id = DetectBufferTypeGetByName(BUFFER_NAME);
2,223✔
246

247
    g_keyword_thread_id = DetectRegisterThreadCtxGlobalFuncs(KEYWORD_NAME,
2,223✔
248
            HttpHeaderThreadDataInit, &g_td_config, HttpHeaderThreadDataFree);
2,223✔
249

250
    SCLogDebug("keyword %s registered. Thread id %d. "
2,223✔
251
            "Buffer %s registered. Buffer id %d",
2,223✔
252
            KEYWORD_NAME, g_keyword_thread_id,
2,223✔
253
            BUFFER_NAME, g_buffer_id);
2,223✔
254
}
2,223✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc