Repository: fluent/fluent-bit (C)

Issue:
Segv from simple wildcard
## Bug Report

**Describe the bug** 
SIGSEGV

**To Reproduce**
```shell
$ docker run -v `pwd`:/foo --rm -it fluent/fluent-bit -c /foo/conf
Fluent Bit v2.1.2
* Copyright (C) 2015-2022 The Fluent Bit Authors
* Fluent Bit is a CNCF sub-project under the umbrella of Fluentd
* https://fluentbit.io

[2023/05/12 01:28:53] [ info] [fluent bit] version=2.1.2, commit=113c7c00d2, pid=1
[2023/05/12 01:28:53] [ info] [storage] ver=1.4.0, type=memory, sync=normal, checksum=off, max_chunks_up=128
[2023/05/12 01:28:53] [ info] [cmetrics] version=0.6.1
[2023/05/12 01:28:53] [ info] [ctraces ] version=0.3.0
[2023/05/12 01:28:53] [ info] [input:dummy:dummy.0] initializing
[2023/05/12 01:28:53] [ info] [input:dummy:dummy.0] storage_strategy='memory' (memory only)
ret=-113. start=*s3 end=
ret=-113. start=*s3 end=
[2023/05/12 01:28:53] [debug] [filter:modify:modify.0] Initialized modify filter with 0 conditions and 1 rules
[2023/05/12 01:28:53] [ info] [sp] stream processor started
[2023/05/12 01:28:53] [ info] [output:stdout:stdout.0] worker #0 started
[2023/05/12 01:28:55] [ warn] [engine] service will shutdown in max 2 seconds
[2023/05/12 01:28:55] [ info] [input] pausing dummy.0
[0] dummy.0: [[1683854934.165236446, {}], {"r1"=>"someval", "s1"=>{"s2"=>nil, "s3"=>nil}, "r2"=>{"x"=>0}}]
[2023/05/12 01:28:56] [ info] [engine] service has stopped (0 pending tasks)
[2023/05/12 01:28:56] [ info] [input] pausing dummy.0
[2023/05/12 01:28:56] [engine] caught signal (SIGSEGV)
#0  0x5599036f4623      in  flb_regex_destroy() at src/flb_regex.c:312
#1  0x559903b2f227      in  teardown() at plugins/filter_modify/modify.c:82
#2  0x559903b3419c      in  cb_modify_exit() at plugins/filter_modify/modify.c:1531
#3  0x559903642f90      in  flb_filter_instance_exit() at src/flb_filter.c:352
#4  0x559903642ff6      in  flb_filter_exit() at src/flb_filter.c:370
#5  0x55990366f1f6      in  flb_engine_shutdown() at src/flb_engine.c:1046
#6  0x55990366ee62      in  flb_engine_start() at src/flb_engine.c:942
#7  0x559903613531      in  flb_lib_worker() at src/flb_lib.c:638
#8  0x7f94f304bea6      in  ???() at ???:0
#9  0x7f94f28fea2e      in  ???() at ???:0
#10 0xffffffffffffffff  in  ???() at ???:0
```

- Steps to reproduce the problem:

**Expected behavior**
Print an error saying what I did wrong and continue.

**Your Environment**

* Version used: docker x86 v2.1.2
* Configuration:
```
[SERVICE]
    Flush      1
    Grace      2
    Log_Level  info

[INPUT]
    Name       dummy
    Dummy      {"r1": "someval", "s1": {"s2": null, "s3": null}, "r2": {"x": 0}}
    Samples    1

[FILTER]
    Name                 modify
    Match                *
    Log_Level            debug
    Remove_wildcard      *s3

[OUTPUT]
    Name  stdout
    Match *

[OUTPUT]
    Name exit
    Match *
```


**Additional context**
I suspect it's the bad wildcard.


Discussion: The problem is that the filters initialization routine has a few flaws : 

1. The [regex](https://github.com/fluent/fluent-bit/blob/master/plugins/filter_modify/modify.c#L446) [compilation](https://github.com/fluent/fluent-bit/blob/master/plugins/filter_modify/modify.c#L455) results are not checked and thus an invalid regex will just leave an invalid value (`NULL`) in place which will be later on [used](https://github.com/fluent/fluent-bit/blob/master/plugins/filter_modify/modify.c#L502)  and I suspect that wouldn't go well. << this is NOT your case
2. The teardown routine unconditionally tries to dispose of all the rule components without checking their state (ie. a [regex field](https://github.com/fluent/fluent-bit/blob/master/plugins/filter_modify/modify.c#L82) wasn't or couldn't be initialized).

Would you like to take a stab at fixing it? I can't give you an ETA for the fix but I can provide any assistance you might need if you try to contribute a patch.

Thanks for reporting this issue.
I sent a patch https://github.com/fluent/fluent-bit/pull/7378



Fix (patch):
diff --git a/plugins/filter_modify/modify.c b/plugins/filter_modify/modify.c
index a1281a2f98f..4bc1a28514b 100644
--- a/plugins/filter_modify/modify.c
+++ b/plugins/filter_modify/modify.c
@@ -41,24 +41,69 @@
 
 static void condition_free(struct modify_condition *condition)
 {
-    flb_sds_destroy(condition->a);
-    flb_free(condition->b);
-    flb_free(condition->raw_k);
-    flb_free(condition->raw_v);
+    if (condition == NULL) {
+        return;
+    }
+
+    if (condition->a) {
+        flb_sds_destroy(condition->a);
+    }
+    if (condition->b) {
+        flb_free(condition->b);
+    }
+    if (condition->raw_k) {
+        flb_free(condition->raw_k);
+    }
+    if (condition->raw_v) {
+        flb_free(condition->raw_v);
+    }
 
-    if (condition->a_is_regex) {
+    if (condition->a_regex) {
         flb_regex_destroy(condition->a_regex);
     }
-    if (condition->b_is_regex) {
+    if (condition->b_regex) {
         flb_regex_destroy(condition->b_regex);
     }
     if (condition->ra_a) {
         flb_ra_destroy(condition->ra_a);
         condition->ra_a = NULL;
     }
+    if (!mk_list_entry_is_orphan(&condition->_head)) {
+        mk_list_del(&condition->_head);
+    }
     flb_free(condition);
 }
 
+static void rule_free(struct modify_rule *rule)
+{
+    if (rule == NULL) {
+        return;
+    }
+
+    if (rule->key) {
+        flb_free(rule->key);
+    }
+    if (rule->val) {
+        flb_free(rule->val);
+    }
+    if (rule->raw_k) {
+        flb_free(rule->raw_k);
+    }
+    if (rule->raw_v) {
+        flb_free(rule->raw_v);
+    }
+    if (rule->key_regex) {
+        flb_regex_destroy(rule->key_regex);
+    }
+    if (rule->val_regex) {
+        flb_regex_destroy(rule->val_regex);
+    }
+    if (!mk_list_entry_is_orphan(&rule->_head)) {
+        mk_list_del(&rule->_head);
+    }
+    flb_free(rule);
+}
+
 static void teardown(struct filter_modify_ctx *ctx)
 {
     struct mk_list *tmp;
@@ -69,20 +114,12 @@ static void teardown(struct filter_modify_ctx *ctx)
 
     mk_list_foreach_safe(head, tmp, &ctx->conditions) {
         condition = mk_list_entry(head, struct modify_condition, _head);
-        mk_list_del(&condition->_head);
         condition_free(condition);
     }
 
     mk_list_foreach_safe(head, tmp, &ctx->rules) {
         rule = mk_list_entry(head, struct modify_rule, _head);
-        flb_free(rule->key);
-        flb_free(rule->val);
-        flb_free(rule->raw_k);
-        flb_free(rule->raw_v);
-        flb_regex_destroy(rule->key_regex);
-        flb_regex_destroy(rule->val_regex);
-        mk_list_del(&rule->_head);
-        flb_free(rule);
+        rule_free(rule);
     }
 }
 
@@ -271,6 +308,7 @@ static int setup(struct filter_modify_ctx *ctx,
                     flb_plg_error(ctx->ins, "Unable to create regex for "
                                   "condition %s %s",
                                   condition->raw_k, condition->raw_v);
+                    teardown(ctx);
                     condition_free(condition);
                     flb_utils_split_free(split);
                     return -1;
@@ -290,6 +328,7 @@ static int setup(struct filter_modify_ctx *ctx,
                     flb_plg_error(ctx->ins, "Unable to create regex "
                                   "for condition %s %s",
                                   condition->raw_k, condition->raw_v);
+                    teardown(ctx);
                     condition_free(condition);
                     flb_utils_split_free(split);
                     return -1;
@@ -314,7 +353,7 @@ static int setup(struct filter_modify_ctx *ctx,
             // Build a rule
             //
 
-            rule = flb_malloc(sizeof(struct modify_rule));
+            rule = flb_calloc(1, sizeof(struct modify_rule));
             if (!rule) {
                 flb_plg_error(ctx->ins, "Unable to allocate memory for rule");
                 teardown(ctx);
@@ -329,7 +368,7 @@ static int setup(struct filter_modify_ctx *ctx,
                 flb_errno();
                 flb_plg_error(ctx->ins, "Unable to allocate memory for rule->raw_k");
                 teardown(ctx);
-                flb_free(rule);
+                rule_free(rule);
                 flb_utils_split_free(split);
                 return -1;
             }
@@ -338,8 +377,7 @@ static int setup(struct filter_modify_ctx *ctx,
                 flb_errno();
                 flb_plg_error(ctx->ins, "Unable to allocate memory for rule->raw_v");
                 teardown(ctx);
-                flb_free(rule->raw_k);
-                flb_free(rule);
+                rule_free(rule);
                 flb_utils_split_free(split);
                 return -1;
             }
@@ -351,9 +389,7 @@ static int setup(struct filter_modify_ctx *ctx,
                 flb_errno();
                 flb_plg_error(ctx->ins, "Unable to allocate memory for rule->key");
                 teardown(ctx);
-                flb_free(rule->raw_v);
-                flb_free(rule->raw_k);
-                flb_free(rule);
+                rule_free(rule);
                 flb_utils_split_free(split);
                 return -1;
             }
@@ -365,10 +401,7 @@ static int setup(struct filter_modify_ctx *ctx,
                 flb_errno();
                 flb_plg_error(ctx->ins, "Unable to allocate memory for rule->val");
                 teardown(ctx);
-                flb_free(rule->key);
-                flb_free(rule->raw_v);
-                flb_free(rule->raw_k);
-                flb_free(rule);
+                rule_free(rule);
                 flb_utils_split_free(split);
                 return -1;
             }
@@ -397,7 +430,7 @@ static int setup(struct filter_modify_ctx *ctx,
                     flb_plg_error(ctx->ins, "Invalid operation %s : %s in "
                                   "configuration", kv->key, kv->val);
                     teardown(ctx);
-                    flb_free(rule);
+                    rule_free(rule);
                     return -1;
                 }
             }
@@ -430,7 +463,7 @@ static int setup(struct filter_modify_ctx *ctx,
                     flb_plg_error(ctx->ins, "Invalid operation %s : %s in "
                                   "configuration", kv->key, kv->val);
                     teardown(ctx);
-                    flb_free(rule);
+                    rule_free(rule);
                     return -1;
                 }
             }
@@ -439,22 +472,38 @@ static int setup(struct filter_modify_ctx *ctx,
                 flb_plg_error(ctx->ins, "Unable to create regex for rule %s %s",
                               rule->raw_k, rule->raw_v);
                 teardown(ctx);
-                flb_free(rule);
+                rule_free(rule);
                 return -1;
             }
             else {
                 rule->key_regex =
                     flb_regex_create(rule->key);
+                if (rule->key_regex == NULL) {
+                    flb_plg_error(ctx->ins, "Unable to create regex(key) from %s",
+                                  rule->key);
+                    teardown(ctx);
+                    rule_free(rule);
+                    return -1;
+                }
             }
 
             if (rule->val_is_regex && rule->val_len == 0) {
                 flb_plg_error(ctx->ins, "Unable to create regex for rule %s %s",
                               rule->raw_k, rule->raw_v);
+                teardown(ctx);
+                rule_free(rule);
                 return -1;
             }
             else {
                 rule->val_regex =
                     flb_regex_create(rule->val);
+                if (rule->val_regex == NULL) {
+                    flb_plg_error(ctx->ins, "Unable to create regex(val) from %s",
+                                  rule->val);
+                    teardown(ctx);
+                    rule_free(rule);
+                    return -1;
+                }
             }
 
             mk_list_add(&rule->_head, &ctx->rules);
diff --git a/src/flb_regex.c b/src/flb_regex.c
index c203b00c42a..b2a1a5d5713 100644
--- a/src/flb_regex.c
+++ b/src/flb_regex.c
@@ -140,7 +140,6 @@ static int str_to_regex(const char *pattern, OnigRegex *reg)
                    ONIG_ENCODING_UTF8, ONIG_SYNTAX_RUBY, &einfo);
 
     if (ret != ONIG_NORMAL) {
-        printf("ret=%d. start=%s end=%c\n", ret, start, *end);
         return -1;
     }
     return 0;