Skip to content

Commit 0a5f86b

Browse files
committed
test: add tests on range access to fragmented memory
1 parent ec0349e commit 0a5f86b

File tree

2 files changed

+523
-24
lines changed

2 files changed

+523
-24
lines changed

boreal/tests/it/hash.rs

Lines changed: 192 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::libyara_compat::util::TEXT_1024_BYTES;
2-
use crate::utils::check;
2+
use crate::utils::{check, Checker};
3+
4+
const TEXT: &[u8] = TEXT_1024_BYTES.as_bytes();
35

46
fn make_rule(cond: &str) -> String {
57
format!(
@@ -25,11 +27,11 @@ fn test_md5() {
2527
);
2628
test(
2729
r#"hash.md5(0, filesize) == "dcc824971a00e589619ba0c0bba41515""#,
28-
TEXT_1024_BYTES.as_bytes(),
30+
TEXT,
2931
);
3032
test(
3133
r#"hash.md5(50, 100) == "5c026f2a09609f79c46a7dab7398d4ac""#,
32-
TEXT_1024_BYTES.as_bytes(),
34+
TEXT,
3335
);
3436

3537
test(
@@ -54,6 +56,43 @@ fn test_md5() {
5456
test(r#"not defined hash.md5(5, filesize)"#, b"a");
5557
test(r#"not defined hash.md5(-1, filesize)"#, b"a");
5658
test(r#"not defined hash.md5(0, -1)"#, b"a");
59+
60+
// Test that fragmented memory still works if chunks are contiguous
61+
let mut checker = Checker::new(&make_rule(
62+
r#"hash.md5(50, 100) == "5c026f2a09609f79c46a7dab7398d4ac""#,
63+
));
64+
checker.check_fragmented(&[(0, Some(TEXT))], true);
65+
checker.check_fragmented(&[(0, Some(&TEXT[0..75])), (75, Some(&TEXT[75..150]))], true);
66+
checker.check_fragmented(&[(0, Some(&TEXT[0..75])), (75, Some(&TEXT[75..]))], true);
67+
checker.check_fragmented(
68+
&[
69+
(0, Some(&TEXT[0..50])),
70+
(50, Some(&TEXT[50..70])),
71+
(70, Some(&TEXT[70..130])),
72+
(130, Some(&TEXT[130..150])),
73+
(150, Some(&TEXT[150..])),
74+
],
75+
true,
76+
);
77+
78+
// Will still return a result if last region truncates the range
79+
let mut checker = Checker::new(&make_rule(
80+
r#"hash.md5(50, 200) == "5c026f2a09609f79c46a7dab7398d4ac""#,
81+
));
82+
checker.check_fragmented(
83+
&[
84+
(0, Some(&TEXT[0..50])),
85+
(50, Some(&TEXT[50..70])),
86+
(70, Some(&TEXT[70..150])),
87+
],
88+
true,
89+
);
90+
91+
// Missing starting bytes of holes means undefined
92+
let mut checker = Checker::new(&make_rule("not defined hash.md5(50, 100)"));
93+
checker.check_fragmented(&[(0, Some(&TEXT[0..40])), (51, Some(&TEXT[51..]))], true);
94+
checker.check_fragmented(&[(0, Some(&TEXT[0..40])), (170, Some(&TEXT[170..]))], true);
95+
checker.check_fragmented(&[(0, Some(&TEXT[0..70])), (80, Some(&TEXT[80..]))], true);
5796
}
5897

5998
#[test]
@@ -64,11 +103,11 @@ fn test_sha1() {
64103
);
65104
test(
66105
r#"hash.sha1(0, filesize) == "ccb665bf4d6e19b56d3f70e9cc2837dfe3f3a745""#,
67-
TEXT_1024_BYTES.as_bytes(),
106+
TEXT,
68107
);
69108
test(
70109
r#"hash.sha1(50, 100) == "1d17cf1bd2c85210e088796fe302d08beb27dd5a""#,
71-
TEXT_1024_BYTES.as_bytes(),
110+
TEXT,
72111
);
73112

74113
test(
@@ -93,6 +132,43 @@ fn test_sha1() {
93132
test(r#"not defined hash.sha1(5, filesize)"#, b"a");
94133
test(r#"not defined hash.sha1(-1, filesize)"#, b"a");
95134
test(r#"not defined hash.sha1(0, -1)"#, b"a");
135+
136+
// Test that fragmented memory still works if chunks are contiguous
137+
let mut checker = Checker::new(&make_rule(
138+
r#"hash.sha1(50, 100) == "1d17cf1bd2c85210e088796fe302d08beb27dd5a""#,
139+
));
140+
checker.check_fragmented(&[(0, Some(TEXT))], true);
141+
checker.check_fragmented(&[(0, Some(&TEXT[0..75])), (75, Some(&TEXT[75..150]))], true);
142+
checker.check_fragmented(&[(0, Some(&TEXT[0..75])), (75, Some(&TEXT[75..]))], true);
143+
checker.check_fragmented(
144+
&[
145+
(0, Some(&TEXT[0..50])),
146+
(50, Some(&TEXT[50..70])),
147+
(70, Some(&TEXT[70..130])),
148+
(130, Some(&TEXT[130..150])),
149+
(150, Some(&TEXT[150..])),
150+
],
151+
true,
152+
);
153+
154+
// Will still return a result if last region truncates the range
155+
let mut checker = Checker::new(&make_rule(
156+
r#"hash.sha1(50, 200) == "1d17cf1bd2c85210e088796fe302d08beb27dd5a""#,
157+
));
158+
checker.check_fragmented(
159+
&[
160+
(0, Some(&TEXT[0..50])),
161+
(50, Some(&TEXT[50..70])),
162+
(70, Some(&TEXT[70..150])),
163+
],
164+
true,
165+
);
166+
167+
// Missing starting bytes of holes means undefined
168+
let mut checker = Checker::new(&make_rule("not defined hash.sha1(50, 100)"));
169+
checker.check_fragmented(&[(0, Some(&TEXT[0..40])), (51, Some(&TEXT[51..]))], true);
170+
checker.check_fragmented(&[(0, Some(&TEXT[0..40])), (170, Some(&TEXT[170..]))], true);
171+
checker.check_fragmented(&[(0, Some(&TEXT[0..70])), (80, Some(&TEXT[80..]))], true);
96172
}
97173

98174
#[test]
@@ -105,12 +181,12 @@ fn test_sha256() {
105181
test(
106182
"hash.sha256(0, filesize) == \
107183
\"62b33f9e7880055a0cb2f195e296f5c5f88043e08d5521199d1ae4f16df7b17b\"",
108-
TEXT_1024_BYTES.as_bytes(),
184+
TEXT,
109185
);
110186
test(
111187
"hash.sha256(50, 100) == \
112188
\"a8b65993e5cda9e8c6a93b8913062ae503df81cdebe0af070fd5ec3de4cf7dbf\"",
113-
TEXT_1024_BYTES.as_bytes(),
189+
TEXT,
114190
);
115191

116192
test(
@@ -137,19 +213,52 @@ fn test_sha256() {
137213
test(r#"not defined hash.sha256(5, filesize)"#, b"a");
138214
test(r#"not defined hash.sha256(-1, filesize)"#, b"a");
139215
test(r#"not defined hash.sha256(0, -1)"#, b"a");
216+
217+
// Test that fragmented memory still works if chunks are contiguous
218+
let mut checker = Checker::new(&make_rule(
219+
"hash.sha256(50, 100) == \
220+
\"a8b65993e5cda9e8c6a93b8913062ae503df81cdebe0af070fd5ec3de4cf7dbf\"",
221+
));
222+
checker.check_fragmented(&[(0, Some(TEXT))], true);
223+
checker.check_fragmented(&[(0, Some(&TEXT[0..75])), (75, Some(&TEXT[75..150]))], true);
224+
checker.check_fragmented(&[(0, Some(&TEXT[0..75])), (75, Some(&TEXT[75..]))], true);
225+
checker.check_fragmented(
226+
&[
227+
(0, Some(&TEXT[0..50])),
228+
(50, Some(&TEXT[50..70])),
229+
(70, Some(&TEXT[70..130])),
230+
(130, Some(&TEXT[130..150])),
231+
(150, Some(&TEXT[150..])),
232+
],
233+
true,
234+
);
235+
236+
// Will still return a result if last region truncates the range
237+
let mut checker = Checker::new(&make_rule(
238+
"hash.sha256(50, 200) == \
239+
\"a8b65993e5cda9e8c6a93b8913062ae503df81cdebe0af070fd5ec3de4cf7dbf\"",
240+
));
241+
checker.check_fragmented(
242+
&[
243+
(0, Some(&TEXT[0..50])),
244+
(50, Some(&TEXT[50..70])),
245+
(70, Some(&TEXT[70..150])),
246+
],
247+
true,
248+
);
249+
250+
// Missing starting bytes of holes means undefined
251+
let mut checker = Checker::new(&make_rule("not defined hash.sha256(50, 100)"));
252+
checker.check_fragmented(&[(0, Some(&TEXT[0..40])), (51, Some(&TEXT[51..]))], true);
253+
checker.check_fragmented(&[(0, Some(&TEXT[0..40])), (170, Some(&TEXT[170..]))], true);
254+
checker.check_fragmented(&[(0, Some(&TEXT[0..70])), (80, Some(&TEXT[80..]))], true);
140255
}
141256

142257
#[test]
143258
fn test_checksum32() {
144259
test("hash.checksum32(0, filesize) == 97", b"a");
145-
test(
146-
"hash.checksum32(0, filesize) == 52946",
147-
TEXT_1024_BYTES.as_bytes(),
148-
);
149-
test(
150-
"hash.checksum32(50, 100) == 5215",
151-
TEXT_1024_BYTES.as_bytes(),
152-
);
260+
test("hash.checksum32(0, filesize) == 52946", TEXT);
261+
test("hash.checksum32(50, 100) == 5215", TEXT);
153262

154263
test(
155264
"hash.checksum32(\"abcdefghijklmnopqrstuvwxyz\") == 2847",
@@ -168,19 +277,46 @@ fn test_checksum32() {
168277
test(r#"not defined hash.checksum32(5, filesize)"#, b"a");
169278
test(r#"not defined hash.checksum32(-1, filesize)"#, b"a");
170279
test(r#"not defined hash.checksum32(0, -1)"#, b"a");
280+
281+
// Test that fragmented memory still works if chunks are contiguous
282+
let mut checker = Checker::new(&make_rule("hash.checksum32(50, 100) == 5215"));
283+
checker.check_fragmented(&[(0, Some(TEXT))], true);
284+
checker.check_fragmented(&[(0, Some(&TEXT[0..75])), (75, Some(&TEXT[75..150]))], true);
285+
checker.check_fragmented(&[(0, Some(&TEXT[0..75])), (75, Some(&TEXT[75..]))], true);
286+
checker.check_fragmented(
287+
&[
288+
(0, Some(&TEXT[0..50])),
289+
(50, Some(&TEXT[50..70])),
290+
(70, Some(&TEXT[70..130])),
291+
(130, Some(&TEXT[130..150])),
292+
(150, Some(&TEXT[150..])),
293+
],
294+
true,
295+
);
296+
297+
// Will still return a result if last region truncates the range
298+
let mut checker = Checker::new(&make_rule("hash.checksum32(50, 200) == 5215"));
299+
checker.check_fragmented(
300+
&[
301+
(0, Some(&TEXT[0..50])),
302+
(50, Some(&TEXT[50..70])),
303+
(70, Some(&TEXT[70..150])),
304+
],
305+
true,
306+
);
307+
308+
// Missing starting bytes of holes means undefined
309+
let mut checker = Checker::new(&make_rule("not defined hash.checksum32(50, 100)"));
310+
checker.check_fragmented(&[(0, Some(&TEXT[0..40])), (51, Some(&TEXT[51..]))], true);
311+
checker.check_fragmented(&[(0, Some(&TEXT[0..40])), (170, Some(&TEXT[170..]))], true);
312+
checker.check_fragmented(&[(0, Some(&TEXT[0..70])), (80, Some(&TEXT[80..]))], true);
171313
}
172314

173315
#[test]
174316
fn test_crc32() {
175317
test("hash.crc32(0, filesize) == 0xe8b7be43", b"a");
176-
test(
177-
"hash.crc32(0, filesize) == 0x74cb171",
178-
TEXT_1024_BYTES.as_bytes(),
179-
);
180-
test(
181-
"hash.crc32(50, 100) == 0x25c34eec",
182-
TEXT_1024_BYTES.as_bytes(),
183-
);
318+
test("hash.crc32(0, filesize) == 0x74cb171", TEXT);
319+
test("hash.crc32(50, 100) == 0x25c34eec", TEXT);
184320

185321
test(
186322
"hash.crc32(\"abcdefghijklmnopqrstuvwxyz\") == 0x4c2750bd",
@@ -199,4 +335,37 @@ fn test_crc32() {
199335
test(r#"not defined hash.crc32(5, filesize)"#, b"a");
200336
test(r#"not defined hash.crc32(-1, filesize)"#, b"a");
201337
test(r#"not defined hash.crc32(0, -1)"#, b"a");
338+
339+
// Test that fragmented memory still works if chunks are contiguous
340+
let mut checker = Checker::new(&make_rule("hash.crc32(50, 100) == 0x25c34eec"));
341+
checker.check_fragmented(&[(0, Some(TEXT))], true);
342+
checker.check_fragmented(&[(0, Some(&TEXT[0..75])), (75, Some(&TEXT[75..150]))], true);
343+
checker.check_fragmented(&[(0, Some(&TEXT[0..75])), (75, Some(&TEXT[75..]))], true);
344+
checker.check_fragmented(
345+
&[
346+
(0, Some(&TEXT[0..50])),
347+
(50, Some(&TEXT[50..70])),
348+
(70, Some(&TEXT[70..130])),
349+
(130, Some(&TEXT[130..150])),
350+
(150, Some(&TEXT[150..])),
351+
],
352+
true,
353+
);
354+
355+
// Will still return a result if last region truncates the range
356+
let mut checker = Checker::new(&make_rule("hash.crc32(50, 200) == 0x25c34eec"));
357+
checker.check_fragmented(
358+
&[
359+
(0, Some(&TEXT[0..50])),
360+
(50, Some(&TEXT[50..70])),
361+
(70, Some(&TEXT[70..150])),
362+
],
363+
true,
364+
);
365+
366+
// Missing starting bytes of holes means undefined
367+
let mut checker = Checker::new(&make_rule("not defined hash.crc32(50, 100)"));
368+
checker.check_fragmented(&[(0, Some(&TEXT[0..40])), (51, Some(&TEXT[51..]))], true);
369+
checker.check_fragmented(&[(0, Some(&TEXT[0..40])), (170, Some(&TEXT[170..]))], true);
370+
checker.check_fragmented(&[(0, Some(&TEXT[0..70])), (80, Some(&TEXT[80..]))], true);
202371
}

0 commit comments

Comments
 (0)