]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect/content: fix offset for negative distance
authorVictor Julien <vjulien@oisf.net>
Wed, 20 Dec 2023 20:40:47 +0000 (21:40 +0100)
committerVictor Julien <vjulien@oisf.net>
Tue, 9 Jan 2024 08:21:30 +0000 (09:21 +0100)
Fix offset calculation on sigs with negative distance. Can lead to FN
in certain cases.

Bug: #6661.
(cherry picked from commit 2911656d6c11e8ef64a55ce64216382cd22151fe)

src/detect-content.c
src/tests/detect-engine-content-inspection.c

index 5bbe9e9b3cae27623da66e788bb46bfb2e7ed76b..be1f12559491ed64a8f30fb214820bb5f173db3f 100644 (file)
@@ -574,10 +574,21 @@ static void PropagateLimits(Signature *s, SigMatch *sm_head)
                 SCLogDebug("stored: offset %u depth %u offset_plus_pat %u "
                            "has_active_depth_chain %s",
                         offset, depth, offset_plus_pat, has_active_depth_chain ? "true" : "false");
-                if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) {
-                    VALIDATE((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX);
-                    offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
-                    SCLogDebug("updated content to have offset %u", cd->offset);
+                if (cd->flags & DETECT_CONTENT_DISTANCE) {
+                    if (cd->distance >= 0) {
+                        VALIDATE((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX);
+                        offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
+                        SCLogDebug("distance %d: updated content to have offset %u", cd->distance,
+                                cd->offset);
+                    } else {
+                        if (abs(cd->distance) > offset_plus_pat)
+                            offset = cd->offset = 0;
+                        else
+                            offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
+                        offset_plus_pat = offset + cd->content_len;
+                        SCLogDebug("distance %d: updated content to have offset %u", cd->distance,
+                                cd->offset);
+                    }
                 }
                 if (has_active_depth_chain) {
                     if (offset_plus_pat && cd->flags & DETECT_CONTENT_WITHIN && cd->within >= 0) {
index ee1b605f2c0d7254ab62dbed025963f307570b3b..8539d465de4b7e7552800e2e9f2aac8b3e626d4f 100644 (file)
@@ -273,6 +273,17 @@ static int DetectEngineContentInspectionTest13(void) {
     TEST_FOOTER;
 }
 
+/** \brief negative distance */
+static int DetectEngineContentInspectionTest17(void)
+{
+    TEST_HEADER;
+    TEST_RUN("aaabbbcccdddee", 14,
+            "content:\"aaa\"; content:\"ee\"; within:2; distance:9; content:\"bbb\"; within:3; "
+            "distance:-11; content:\"ccc\"; within:3; distance:0;",
+            true, 4);
+    TEST_FOOTER;
+}
+
 void DetectEngineContentInspectionRegisterTests(void)
 {
     UtRegisterTest("DetectEngineContentInspectionTest01",
@@ -301,6 +312,8 @@ void DetectEngineContentInspectionRegisterTests(void)
                    DetectEngineContentInspectionTest12);
     UtRegisterTest("DetectEngineContentInspectionTest13 mix startswith/endswith",
                    DetectEngineContentInspectionTest13);
+    UtRegisterTest("DetectEngineContentInspectionTest17 negative distance",
+            DetectEngineContentInspectionTest17);
 }
 
 #undef TEST_HEADER