]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect/content: simplify int bounds checking
authorVictor Julien <vjulien@oisf.net>
Thu, 9 Jun 2022 20:25:08 +0000 (22:25 +0200)
committerVictor Julien <vjulien@oisf.net>
Mon, 13 Jun 2022 05:59:41 +0000 (07:59 +0200)
Use a macro to validate the ranges for overflows. This removes
the clutter of all the checks and warnings, and also no longer
puts the state machine in an undefined state when hitting such
a condition.

src/detect-content.c

index 47f9de452b562224f9a3ca9abffbe914fe05e9fb..e491b47414f2053d5c4ee0cd650a53b599dfc9ee 100644 (file)
@@ -445,6 +445,10 @@ bool DetectContentPMATCHValidateCallback(const Signature *s)
  */
 void DetectContentPropagateLimits(Signature *s)
 {
+#define VALIDATE(e)                                                                                \
+    if (!(e)) {                                                                                    \
+        return;                                                                                    \
+    }
     BUG_ON(s == NULL || s->init_data == NULL);
 
     uint32_t list = 0;
@@ -505,11 +509,8 @@ void DetectContentPropagateLimits(Signature *s)
                     SCLogDebug("stored: offset %u depth %u offset_plus_pat %u", offset, depth, offset_plus_pat);
 
                     if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) {
-                        if ((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX) {
-                            offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
-                        } else {
-                            SCLogDebug("not updated content offset as it would overflow : %u + %d", offset_plus_pat, cd->distance);
-                        }
+                        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 (have_anchor && !last_reset && offset_plus_pat && cd->flags & DETECT_CONTENT_WITHIN && cd->within >= 0) {
@@ -520,23 +521,13 @@ void DetectContentPropagateLimits(Signature *s)
                                 SCLogDebug("distance to add: %u. depth + dist %u", dist, depth + dist);
                             }
                             SCLogDebug("depth %u + cd->within %u", depth, cd->within);
-                            if (depth + cd->within + dist < 0 ||
-                                    depth + cd->within + dist > UINT16_MAX) {
-                                SCLogDebug("not updated content depth as it would overflow : %u + "
-                                           "%d + %u",
-                                        depth, cd->within, dist);
-                            } else {
-                                depth = cd->depth = (uint16_t)(depth + cd->within + dist);
-                            }
+                            VALIDATE(depth + cd->within + dist >= 0 &&
+                                     depth + cd->within + dist <= UINT16_MAX);
+                            depth = cd->depth = (uint16_t)(depth + cd->within + dist);
                         } else {
                             SCLogDebug("offset %u + cd->within %u", offset, cd->within);
-                            if (depth + cd->within < 0 || depth + cd->within > UINT16_MAX) {
-                                SCLogDebug(
-                                        "not updated content depth as it would overflow : %u + %d",
-                                        offset, cd->within);
-                            } else {
-                                depth = cd->depth = (uint16_t)(offset + cd->within);
-                            }
+                            VALIDATE(depth + cd->within >= 0 && depth + cd->within <= UINT16_MAX);
+                            depth = cd->depth = (uint16_t)(offset + cd->within);
                         }
                         SCLogDebug("updated content to have depth %u", cd->depth);
                     } else {
@@ -544,25 +535,15 @@ void DetectContentPropagateLimits(Signature *s)
                             if (cd->within > 0) {
                                 SCLogDebug("within %d distance %d", cd->within, cd->distance);
                                 if (cd->flags & DETECT_CONTENT_DISTANCE && cd->distance >= 0) {
-                                    if (offset_plus_pat + cd->distance < 0 ||
-                                            offset_plus_pat + cd->distance > UINT16_MAX) {
-                                        SCLogDebug("not updated content offset as it would "
-                                                   "overflow : %u + %d",
-                                                offset_plus_pat, cd->distance);
-                                    } else {
-                                        cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
-                                    }
+                                    VALIDATE(offset_plus_pat + cd->distance >= 0 &&
+                                             offset_plus_pat + cd->distance <= UINT16_MAX);
+                                    cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
                                     SCLogDebug("updated content to have offset %u", cd->offset);
                                 }
 
-                                if (depth + cd->within < 0 || depth + cd->within > UINT16_MAX) {
-                                    SCLogDebug("not updated content depth as it would overflow : "
-                                               "%u + %d",
-                                            offset, cd->within);
-                                } else {
-                                    cd->depth = (uint16_t)(cd->within + depth);
-                                }
-                                depth = cd->depth;
+                                VALIDATE(depth + cd->within >= 0 &&
+                                         depth + cd->within <= UINT16_MAX);
+                                depth = cd->depth = (uint16_t)(cd->within + depth);
                                 SCLogDebug("updated content to have depth %u", cd->depth);
 
                                 if (cd->flags & DETECT_CONTENT_ENDS_WITH) {
@@ -585,11 +566,8 @@ void DetectContentPropagateLimits(Signature *s)
                             (cd->flags & (DETECT_CONTENT_DEPTH|DETECT_CONTENT_OFFSET|DETECT_CONTENT_WITHIN|DETECT_CONTENT_DISTANCE)) == (DETECT_CONTENT_DISTANCE)) {
                         if (cd->distance >= 0) {
                             // only distance
-                            if ((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX) {
-                                offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
-                            } else {
-                                SCLogDebug("not updated content offset as it would overflow : %u + %d", offset_plus_pat, cd->distance);
-                            }
+                            VALIDATE((uint32_t)offset_plus_pat + cd->distance <= UINT16_MAX);
+                            offset = cd->offset = (uint16_t)(offset_plus_pat + cd->distance);
                             offset_plus_pat = offset + cd->content_len;
                             SCLogDebug("offset %u offset_plus_pat %u", offset, offset_plus_pat);
                         }
@@ -657,6 +635,7 @@ void DetectContentPropagateLimits(Signature *s)
             }
         }
     }
+#undef VALIDATE
 }
 
 static inline bool NeedsAsHex(uint8_t c)
@@ -798,7 +777,8 @@ static int DetectContentDepthTest01(void)
     // hi end: depth '13' (4+9) + distance 55 = 68 + within 2 = 70
     TEST_RUN("content:\"=\"; offset:4; depth:9; content:\"=&\"; distance:55; within:2;", 60, 70);
 
-    TEST_RUN("content:\"0123456789\"; content:\"abcdef\"; distance:2147483647;", 10, 0);
+    // distance value is too high so we bail and not set anything on this content
+    TEST_RUN("content:\"0123456789\"; content:\"abcdef\"; distance:2147483647;", 0, 0);
 
     TEST_DONE;
 }