]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
pcre2: migrate transform pcrexform
authorPhilippe Antoine <contact@catenacyber.fr>
Tue, 13 Apr 2021 12:02:28 +0000 (14:02 +0200)
committerPhilippe Antoine <contact@catenacyber.fr>
Tue, 28 Sep 2021 15:46:19 +0000 (17:46 +0200)
src/detect-transform-pcrexform.c
src/tests/detect-transform-pcrexform.c

index 54da1b5412b068830bf3b66fc49a23f7c37353fb..19fff556e0ed4cee5db17fa50fdb9744dd979229 100644 (file)
 
 #include "suricata-common.h"
 
+#include <pcre2.h>
 #include "detect.h"
 #include "detect-engine.h"
 #include "detect-parse.h"
 #include "detect-transform-pcrexform.h"
 
-typedef DetectParseRegex DetectTransformPcrexformData;
+typedef struct DetectTransformPcrexformData {
+    pcre2_code *regex;
+    pcre2_match_data *match_data;
+} DetectTransformPcrexformData;
 
 static int DetectTransformPcrexformSetup (DetectEngineCtx *, Signature *, const char *);
 static void DetectTransformPcrexformFree(DetectEngineCtx *, void *);
@@ -61,9 +65,12 @@ static void DetectTransformPcrexformFree(DetectEngineCtx *de_ctx, void *ptr)
 {
     if (ptr != NULL) {
         DetectTransformPcrexformData *pxd = (DetectTransformPcrexformData *) ptr;
+        pcre2_code_free(pxd->regex);
+        pcre2_match_data_free(pxd->match_data);
         SCFree(pxd);
     }
 }
+
 /**
  *  \internal
  *  \brief Apply the pcrexform keyword to the last pattern match
@@ -78,20 +85,43 @@ static int DetectTransformPcrexformSetup (DetectEngineCtx *de_ctx, Signature *s,
     SCEnter();
 
     // Create pxd from regexstr
-    DetectTransformPcrexformData *pxd = SCCalloc(sizeof(*pxd), 1);
+    DetectTransformPcrexformData *pxd = SCCalloc(1, sizeof(*pxd));
     if (pxd == NULL) {
         SCLogDebug("pxd allocation failed");
         SCReturnInt(-1);
     }
 
-    if (!DetectSetupParseRegexesOpts(regexstr, pxd, 0)) {
+    int en;
+    PCRE2_SIZE eo;
+    pxd->regex = pcre2_compile((PCRE2_SPTR8)regexstr, PCRE2_ZERO_TERMINATED, 0, &en, &eo, NULL);
+    if (pxd->regex == NULL) {
+        PCRE2_UCHAR buffer[256];
+        pcre2_get_error_message(en, buffer, sizeof(buffer));
+        SCLogError(SC_ERR_PCRE_COMPILE,
+                "pcre2 compile of \"%s\" failed at "
+                "offset %d: %s",
+                regexstr, (int)eo, buffer);
         SCFree(pxd);
         SCReturnInt(-1);
     }
+    // check pcd->regex has exactly one capture expression
+    uint32_t nb;
+    if (pcre2_pattern_info(pxd->regex, PCRE2_INFO_CAPTURECOUNT, &nb) < 0) {
+        SCLogError(SC_ERR_INVALID_SIGNATURE, "pcrexform failed getting info about capturecount");
+        DetectTransformPcrexformFree(de_ctx, pxd);
+        SCReturnInt(-1);
+    }
+    if (nb != 1) {
+        SCLogError(SC_ERR_INVALID_SIGNATURE,
+                "pcrexform needs exactly one substring capture, found %" PRIu32, nb);
+        DetectTransformPcrexformFree(de_ctx, pxd);
+        SCReturnInt(-1);
+    }
+    pxd->match_data = pcre2_match_data_create_from_pattern(pxd->regex, NULL);
 
     int r = DetectSignatureAddTransform(s, DETECT_TRANSFORM_PCREXFORM, pxd);
     if (r != 0) {
-        SCFree(pxd);
+        DetectTransformPcrexformFree(de_ctx, pxd);
     }
 
     SCReturnInt(r);
@@ -103,17 +133,16 @@ static void DetectTransformPcrexform(InspectionBuffer *buffer, void *options)
     const uint32_t input_len = buffer->inspect_len;
     DetectTransformPcrexformData *pxd = options;
 
-    int ov[MAX_SUBSTRINGS];
-    int ret = DetectParsePcreExecLen(pxd, input, input_len, 0, 0, ov, MAX_SUBSTRINGS);
+    int ret = pcre2_match(pxd->regex, (PCRE2_SPTR8)input, input_len, 0, 0, pxd->match_data, NULL);
 
     if (ret > 0) {
         const char *str;
-        ret = pcre_get_substring((char *) buffer->inspect, ov,
-                                  MAX_SUBSTRINGS, ret - 1, &str);
+        PCRE2_SIZE caplen;
+        ret = pcre2_substring_get_bynumber(pxd->match_data, 0, (PCRE2_UCHAR8 **)&str, &caplen);
 
         if (ret >= 0) {
-            InspectionBufferCopy(buffer, (uint8_t *)str, (uint32_t) ret);
-            pcre_free_substring(str);
+            InspectionBufferCopy(buffer, (uint8_t *)str, (uint32_t)caplen);
+            pcre2_substring_free((PCRE2_UCHAR8 *)str);
         }
     }
 }
index a9b3962d78ba8554106db10074a5221a3e9ab6af..be236152681e2e076d9593c7d13be2aab48d54be 100644 (file)
@@ -57,6 +57,24 @@ static int DetectTransformPcrexformParseTest02 (void)
     PASS;
 }
 
+/**
+ * \test signature with a pcrexform value without substring capture
+ */
+
+static int DetectTransformPcrexformParseTest03(void)
+{
+    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
+    FAIL_IF_NULL(de_ctx);
+
+    Signature *sig = DetectEngineAppendSig(de_ctx,
+            "alert http any any -> any any (msg:\"HTTP with pcrexform\"; http.request_line; "
+            "pcrexform:\"No-match\"; content:\"/no-match.jpg\"; sid:1;)");
+    FAIL_IF_NOT_NULL(sig);
+
+    DetectEngineCtxFree(de_ctx);
+    PASS;
+}
+
 /**
  * \brief this function registers unit tests for DetectTransformPcrexform
  */
@@ -64,4 +82,5 @@ void DetectTransformPcrexformRegisterTests(void)
 {
     UtRegisterTest("DetectTransformPcrexformParseTest01", DetectTransformPcrexformParseTest01);
     UtRegisterTest("DetectTransformPcrexformParseTest02", DetectTransformPcrexformParseTest02);
+    UtRegisterTest("DetectTransformPcrexformParseTest03", DetectTransformPcrexformParseTest03);
 }