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

OISF / suricata / 23374838686

21 Mar 2026 07:29AM UTC coverage: 59.341% (-20.0%) from 79.315%
23374838686

Pull #15075

github

web-flow
Merge 90b4e834f into 6587e363a
Pull Request #15075: Stack 8001 v16.4

38 of 70 new or added lines in 10 files covered. (54.29%)

34165 existing lines in 563 files now uncovered.

119621 of 201584 relevant lines covered (59.34%)

650666.92 hits per line

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

89.8
/rust/src/detect/mod.rs
1
/* Copyright (C) 2022 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
//! Module for rule parsing.
19

20
pub mod byte_extract;
21
pub mod byte_math;
22
pub mod datasets;
23
pub mod entropy;
24
pub mod error;
25
pub mod float;
26
pub mod flow;
27
pub mod fragbits;
28
pub mod iprep;
29
pub mod parser;
30
pub mod requires;
31
pub mod stream_size;
32
pub mod tcp;
33
pub mod tojson;
34
pub mod transforms;
35
pub mod uint;
36
pub mod uri;
37
pub mod vlan;
38

39
use std::ffi::CString;
40
use std::os::raw::c_int;
41

42
use suricata_sys::sys::{
43
    DetectEngineCtx, SCDetectHelperKeywordRegister, SCDetectHelperKeywordSetCleanCString,
44
    SCSigTableAppLiteElmt, Signature,
45
};
46

47
/// EnumString trait that will be implemented on enums that
48
/// derive StringEnum.
49
pub trait EnumString<T> {
50
    /// Return the enum variant of the given numeric value.
51
    fn from_u(v: T) -> Option<Self>
52
    where
53
        Self: Sized;
54

55
    /// Convert the enum variant to the numeric value.
56
    fn into_u(self) -> T;
57

58
    /// Return the string for logging the enum value.
59
    fn to_str(&self) -> &'static str;
60

61
    /// Get an enum variant from parsing a string.
62
    fn from_str(s: &str) -> Option<Self>
63
    where
64
        Self: Sized;
65
}
66

67
/// Rust app-layer light version of SigTableElmt for simple sticky buffer
68
pub struct SigTableElmtStickyBuffer {
69
    /// keyword name
70
    pub name: String,
71
    /// keyword description
72
    pub desc: String,
73
    /// keyword documentation url
74
    pub url: String,
75
    /// function callback to parse and setup keyword in rule
76
    pub setup: unsafe extern "C" fn(
77
        de: *mut DetectEngineCtx,
78
        s: *mut Signature,
79
        raw: *const std::os::raw::c_char,
80
    ) -> c_int,
81
}
82

83
fn helper_keyword_register_buffer_flags(kw: &SigTableElmtStickyBuffer, flags: u32) -> u16 {
220✔
84
    let name = CString::new(kw.name.as_bytes()).unwrap().into_raw();
220✔
85
    let desc = CString::new(kw.desc.as_bytes()).unwrap().into_raw();
220✔
86
    let url = CString::new(kw.url.as_bytes()).unwrap().into_raw();
220✔
87
    let st = SCSigTableAppLiteElmt {
220✔
88
        name,
220✔
89
        desc,
220✔
90
        url,
220✔
91
        Setup: Some(kw.setup),
220✔
92
        flags,
220✔
93
        AppLayerTxMatch: None,
220✔
94
        Free: None,
220✔
95
    };
220✔
96
    unsafe {
220✔
97
        let r = SCDetectHelperKeywordRegister(&st);
220✔
98
        SCDetectHelperKeywordSetCleanCString(r);
220✔
99
        return r;
220✔
100
    }
220✔
101
}
220✔
102

103
pub fn helper_keyword_register_multi_buffer(kw: &SigTableElmtStickyBuffer) -> u16 {
78✔
104
    return helper_keyword_register_buffer_flags(
78✔
105
        kw,
78✔
106
        SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER | SIGMATCH_INFO_MULTI_BUFFER,
78✔
107
    );
78✔
108
}
78✔
109

110
pub fn helper_keyword_register_sticky_buffer(kw: &SigTableElmtStickyBuffer) -> u16 {
142✔
111
    return helper_keyword_register_buffer_flags(kw, SIGMATCH_NOOPT | SIGMATCH_INFO_STICKY_BUFFER);
142✔
112
}
142✔
113

114
#[repr(C)]
115
#[allow(non_snake_case)]
116
/// Names of SigTableElmt for release by rust
117
pub struct SCSigTableNamesElmt {
118
    /// keyword name
119
    pub name: *mut libc::c_char,
120
    /// keyword description
121
    pub desc: *mut libc::c_char,
122
    /// keyword documentation url
123
    pub url: *mut libc::c_char,
124
}
125

126
#[no_mangle]
UNCOV
127
pub unsafe extern "C" fn SCDetectSigMatchNamesFree(kw: &mut SCSigTableNamesElmt) {
×
UNCOV
128
    let _ = CString::from_raw(kw.name);
×
UNCOV
129
    let _ = CString::from_raw(kw.desc);
×
UNCOV
130
    let _ = CString::from_raw(kw.url);
×
UNCOV
131
}
×
132

133
// TODO bindgen these
134
pub const SIGMATCH_NOOPT: u32 = 1; // BIT_U16(0) in detect.h
135
pub(crate) const SIGMATCH_OPTIONAL_OPT: u32 = 0x10; // BIT_U16(4) in detect.h
136
pub(crate) const SIGMATCH_QUOTES_MANDATORY: u32 = 0x40; // BIT_U16(6) in detect.h
137
pub const SIGMATCH_INFO_STICKY_BUFFER: u32 = 0x200; // BIT_U16(9)
138
pub const SIGMATCH_INFO_MULTI_BUFFER: u32 = 0x4000; // BIT_U16(14)
139
pub const SIGMATCH_INFO_UINT8: u32 = 0x8000; // BIT_U32(15)
140
pub const SIGMATCH_INFO_UINT16: u32 = 0x10000; // BIT_U32(16)
141
pub const SIGMATCH_INFO_UINT32: u32 = 0x20000; // BIT_U32(17)
142
pub const SIGMATCH_INFO_UINT64: u32 = 0x40000; // BIT_U32(18)
143
pub const SIGMATCH_INFO_MULTI_UINT: u32 = 0x80000; // BIT_U32(19)
144
pub const SIGMATCH_INFO_ENUM_UINT: u32 = 0x100000; // BIT_U32(20)
145
pub const SIGMATCH_INFO_BITFLAGS_UINT: u32 = 0x200000; // BIT_U32(21)
146

147
#[repr(u8)]
148
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
149
// endian <big|little|dce>
150
pub enum ByteEndian {
151
    BigEndian = 1,
152
    LittleEndian = 2,
153
    EndianDCE = 3,
154
}
155

156
#[repr(u8)]
157
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
158
pub enum ByteBase {
159
    BaseOct = 8,
160
    BaseDec = 10,
161
    BaseHex = 16,
162
}
163

164
fn get_string_value(value: &str) -> Option<ByteBase> {
48,781✔
165
    let res = match value {
48,781✔
166
        "hex" => Some(ByteBase::BaseHex),
48,781✔
167
        "oct" => Some(ByteBase::BaseOct),
48,516✔
168
        "dec" => Some(ByteBase::BaseDec),
48,136✔
169
        _ => None,
5✔
170
    };
171

172
    res
48,781✔
173
}
48,781✔
174

175
fn get_endian_value(value: &str) -> Option<ByteEndian> {
3,183✔
176
    let res = match value {
3,183✔
177
        "big" => Some(ByteEndian::BigEndian),
3,183✔
178
        "little" => Some(ByteEndian::LittleEndian),
3,139✔
179
        "dce" => Some(ByteEndian::EndianDCE),
2,554✔
180
        _ => None,
3✔
181
    };
182

183
    res
3,183✔
184
}
3,183✔
185

186
#[cfg(test)]
187
mod test {
188
    use super::*;
189
    use suricata_derive::EnumStringU8;
190

191
    #[derive(Clone, Debug, PartialEq, EnumStringU8)]
192
    #[repr(u8)]
193
    pub enum TestEnum {
194
        Zero = 0,
195
        BestValueEver = 42,
196
    }
197

198
    #[test]
199
    fn test_enum_string_u8() {
200
        assert_eq!(TestEnum::from_u(0), Some(TestEnum::Zero));
201
        assert_eq!(TestEnum::from_u(1), None);
202
        assert_eq!(TestEnum::from_u(42), Some(TestEnum::BestValueEver));
203
        assert_eq!(TestEnum::Zero.into_u(), 0);
204
        assert_eq!(TestEnum::BestValueEver.into_u(), 42);
205
        assert_eq!(TestEnum::Zero.to_str(), "zero");
206
        assert_eq!(TestEnum::BestValueEver.to_str(), "best_value_ever");
207
        assert_eq!(TestEnum::from_str("zero"), Some(TestEnum::Zero));
208
        assert_eq!(TestEnum::from_str("nope"), None);
209
        assert_eq!(
210
            TestEnum::from_str("best_value_ever"),
211
            Some(TestEnum::BestValueEver)
212
        );
213
    }
214

215
    #[derive(Clone, Debug, PartialEq, EnumStringU8)]
216
    #[repr(u8)]
217
    #[suricata(enum_string_style = "LOG_UPPERCASE")]
218
    pub enum TestEnumLogUppercase {
219
        Zero = 0,
220
        BestValueEver = 42,
221
    }
222

223
    #[test]
224
    fn test_enum_string_log_uppercase() {
225
        assert_eq!(TestEnumLogUppercase::Zero.to_str(), "ZERO");
226
        assert_eq!(
227
            TestEnumLogUppercase::BestValueEver.to_str(),
228
            "BESTVALUEEVER"
229
        );
230
        assert_eq!(
231
            TestEnumLogUppercase::from_str("zero"),
232
            Some(TestEnumLogUppercase::Zero)
233
        );
234
        assert_eq!(
235
            TestEnumLogUppercase::from_str("BEST_VALUE_EVER"),
236
            Some(TestEnumLogUppercase::BestValueEver)
237
        );
238
    }
239

240
    #[derive(Clone, Debug, PartialEq, EnumStringU8)]
241
    #[repr(u8)]
242
    #[suricata(enum_string_style = "UPPERCASE")]
243
    pub enum TestEnumUppercase {
244
        Zero = 0,
245
        BestValueEver = 42,
246
    }
247

248
    #[test]
249
    fn test_enum_string_uppercase() {
250
        assert_eq!(TestEnumUppercase::Zero.to_str(), "ZERO");
251
        assert_eq!(TestEnumUppercase::BestValueEver.to_str(), "BESTVALUEEVER");
252
        assert_eq!(
253
            TestEnumUppercase::from_str("zero"),
254
            Some(TestEnumUppercase::Zero)
255
        );
256
        assert_eq!(
257
            TestEnumUppercase::from_str("BESTVALUEEVER"),
258
            Some(TestEnumUppercase::BestValueEver)
259
        );
260
    }
261
}
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