diff --git a/lib/filterx/expr-assign.c b/lib/filterx/expr-assign.c index c0bda7fd3..9c14c7190 100644 --- a/lib/filterx/expr-assign.c +++ b/lib/filterx/expr-assign.c @@ -22,6 +22,7 @@ */ #include "filterx/expr-assign.h" #include "filterx/object-primitive.h" +#include "filterx/filterx-ref.h" #include "scratch-buffers.h" static FilterXObject * @@ -29,7 +30,8 @@ _eval(FilterXExpr *s) { FilterXBinaryOp *self = (FilterXBinaryOp *) s; - FilterXObject *value = filterx_expr_eval(self->rhs); + FilterXObject *v = filterx_expr_eval(self->rhs); + FilterXObject *value = filterx_ref_new(v); if (!value) return NULL; diff --git a/lib/filterx/expr-comparison.c b/lib/filterx/expr-comparison.c index 9bb3484ea..b4ae480ac 100644 --- a/lib/filterx/expr-comparison.c +++ b/lib/filterx/expr-comparison.c @@ -24,6 +24,7 @@ #include "filterx/expr-comparison.h" #include "filterx/object-datetime.h" #include "filterx/filterx-globals.h" +#include "filterx/filterx-ref.h" #include "filterx/object-extractor.h" #include "filterx/object-primitive.h" #include "filterx/object-null.h" @@ -140,6 +141,8 @@ _evaluate_as_num(FilterXObject *lhs, FilterXObject *rhs, gint operator) static gboolean _evaluate_type_aware(FilterXObject *lhs, FilterXObject *rhs, gint operator) { + lhs = filterx_ref_get_readonly_value(lhs); + if (lhs->type == rhs->type && (filterx_object_is_type(lhs, &FILTERX_TYPE_NAME(string)) || filterx_object_is_type(lhs, &FILTERX_TYPE_NAME(bytes)) || diff --git a/lib/filterx/expr-literal-generator.c b/lib/filterx/expr-literal-generator.c index b970be48f..91caf6566 100644 --- a/lib/filterx/expr-literal-generator.c +++ b/lib/filterx/expr-literal-generator.c @@ -23,6 +23,7 @@ #include "filterx/expr-literal-generator.h" #include "filterx/object-primitive.h" +#include "filterx/filterx-ref.h" struct FilterXLiteralGeneratorElem_ { @@ -83,7 +84,7 @@ _eval_elements(FilterXObject *fillable, GList *elements) return FALSE; } - FilterXObject *value = filterx_expr_eval(elem->value); + FilterXObject *value = filterx_ref_new(filterx_expr_eval(elem->value)); if (!value) { filterx_object_unref(key); diff --git a/lib/filterx/expr-plus-generator.c b/lib/filterx/expr-plus-generator.c index 79c305a86..997f53b0d 100644 --- a/lib/filterx/expr-plus-generator.c +++ b/lib/filterx/expr-plus-generator.c @@ -24,6 +24,7 @@ #include "expr-plus.h" #include "object-string.h" #include "filterx-eval.h" +#include "filterx-ref.h" #include "scratch-buffers.h" #include "expr-generator.h" #include "object-list-interface.h" @@ -39,6 +40,8 @@ typedef struct FilterXOperatorPlusGenerator static gboolean _generate_obj(FilterXOperatorPlusGenerator *self, FilterXObject *obj, FilterXObject *fillable) { + fillable = filterx_ref_get_writable_value(fillable); + if (filterx_object_is_type(fillable, &FILTERX_TYPE_NAME(list))) return filterx_list_merge(fillable, obj); diff --git a/lib/filterx/expr-regexp.c b/lib/filterx/expr-regexp.c index 3a092ac7a..dcc81fb67 100644 --- a/lib/filterx/expr-regexp.c +++ b/lib/filterx/expr-regexp.c @@ -28,6 +28,7 @@ #include "filterx/object-list-interface.h" #include "filterx/object-dict-interface.h" #include "filterx/expr-function.h" +#include "filterx/filterx-ref.h" #include "compat/pcre.h" #include "scratch-buffers.h" @@ -268,6 +269,8 @@ _store_matches_to_dict(pcre2_code_8 *pattern, const FilterXReMatchState *state, static gboolean _store_matches(pcre2_code_8 *pattern, const FilterXReMatchState *state, FilterXObject *fillable) { + fillable = filterx_ref_get_writable_value(fillable); + if (filterx_object_is_type(fillable, &FILTERX_TYPE_NAME(list))) return _store_matches_to_list(pattern, state, fillable); diff --git a/lib/filterx/expr-set-subscript.c b/lib/filterx/expr-set-subscript.c index 9f6e7149e..c83d6dc93 100644 --- a/lib/filterx/expr-set-subscript.c +++ b/lib/filterx/expr-set-subscript.c @@ -23,6 +23,7 @@ #include "filterx/expr-set-subscript.h" #include "filterx/object-primitive.h" #include "filterx/filterx-eval.h" +#include "filterx/filterx-ref.h" #include "scratch-buffers.h" typedef struct _FilterXSetSubscript @@ -62,7 +63,7 @@ _eval(FilterXExpr *s) goto exit; } - new_value = filterx_expr_eval(self->new_value); + new_value = filterx_ref_new(filterx_expr_eval(self->new_value)); if (!new_value) goto exit; diff --git a/lib/filterx/expr-setattr.c b/lib/filterx/expr-setattr.c index c88a2d479..02989c7fe 100644 --- a/lib/filterx/expr-setattr.c +++ b/lib/filterx/expr-setattr.c @@ -24,6 +24,7 @@ #include "filterx/object-primitive.h" #include "filterx/object-string.h" #include "filterx/filterx-eval.h" +#include "filterx/filterx-ref.h" #include "scratch-buffers.h" typedef struct _FilterXSetAttr @@ -50,7 +51,7 @@ _eval(FilterXExpr *s) goto exit; } - FilterXObject *new_value = filterx_expr_eval(self->new_value); + FilterXObject *new_value = filterx_ref_new(filterx_expr_eval(self->new_value)); if (!new_value) goto exit; diff --git a/lib/filterx/filterx-metrics-labels.c b/lib/filterx/filterx-metrics-labels.c index 42b2a7d9c..65d6ffd09 100644 --- a/lib/filterx/filterx-metrics-labels.c +++ b/lib/filterx/filterx-metrics-labels.c @@ -24,6 +24,7 @@ #include "filterx-metrics-labels.h" #include "filterx-eval.h" +#include "filterx-ref.h" #include "expr-literal.h" #include "expr-literal-generator.h" #include "object-string.h" @@ -226,14 +227,15 @@ _format_expr_to_cache(FilterXExpr *expr, DynMetricsStore *cache) gboolean success = FALSE; - if (!filterx_object_is_type(obj, &FILTERX_TYPE_NAME(dict))) + FilterXObject *inner_obj = filterx_ref_get_readonly_value(obj); + if (!filterx_object_is_type(inner_obj, &FILTERX_TYPE_NAME(dict))) { filterx_eval_push_error_info("failed to format metrics labels, labels must be a dict", expr, - g_strdup_printf("got %s instead", obj->type->name), TRUE); + g_strdup_printf("got %s instead", inner_obj->type->name), TRUE); goto exit; } - success = filterx_dict_iter(obj, _format_dict_elem_to_cache, cache); + success = filterx_dict_iter(inner_obj, _format_dict_elem_to_cache, cache); if (!success) goto exit; diff --git a/lib/filterx/func-flatten.c b/lib/filterx/func-flatten.c index e78954487..5c585c7c5 100644 --- a/lib/filterx/func-flatten.c +++ b/lib/filterx/func-flatten.c @@ -27,6 +27,7 @@ #include "filterx/object-primitive.h" #include "filterx/object-string.h" #include "filterx/filterx-eval.h" +#include "filterx/filterx-ref.h" #include "scratch-buffers.h" #define FILTERX_FUNC_FLATTEN_USAGE "Usage: flatten(dict, separator=\".\")" @@ -70,7 +71,8 @@ _collect_modifications_from_elem(FilterXObject *key, FilterXObject *value, gpoin GString *key_buffer = ((gpointer *) user_data)[3]; gboolean is_top_level = (gboolean) GPOINTER_TO_INT(((gpointer *) user_data)[4]); - if (filterx_object_is_type(value, &FILTERX_TYPE_NAME(dict))) + FilterXObject *inner_value = filterx_ref_get_readonly_value(value); + if (filterx_object_is_type(inner_value, &FILTERX_TYPE_NAME(dict))) { if (is_top_level) *top_level_dict_keys = g_list_prepend(*top_level_dict_keys, filterx_object_ref(key)); @@ -84,7 +86,7 @@ _collect_modifications_from_elem(FilterXObject *key, FilterXObject *value, gpoin g_string_append(key_buffer, self->separator); gpointer inner_user_data[] = { self, flattened_kvs, NULL, key_buffer, GINT_TO_POINTER(FALSE)}; - gboolean result = filterx_dict_iter(value, _collect_modifications_from_elem, inner_user_data); + gboolean result = filterx_dict_iter(inner_value, _collect_modifications_from_elem, inner_user_data); g_string_truncate(key_buffer, orig_len); return result; @@ -190,14 +192,15 @@ _eval(FilterXExpr *s) gboolean result = FALSE; - if (!filterx_object_is_type(dict, &FILTERX_TYPE_NAME(dict))) + FilterXObject *inner_dict = filterx_ref_get_writable_value(dict); + if (!filterx_object_is_type(inner_dict, &FILTERX_TYPE_NAME(dict))) { filterx_eval_push_error_info("object must be a dict", self->dict_expr, - g_strdup_printf("got %s instead", dict->type->name), TRUE); + g_strdup_printf("got %s instead", inner_dict->type->name), TRUE); goto exit; } - result = _flatten(self, dict); + result = _flatten(self, inner_dict); exit: filterx_object_unref(dict); diff --git a/lib/filterx/func-unset-empties.c b/lib/filterx/func-unset-empties.c index fff1affca..b9e544420 100644 --- a/lib/filterx/func-unset-empties.c +++ b/lib/filterx/func-unset-empties.c @@ -32,6 +32,7 @@ #include "filterx/object-list-interface.h" #include "filterx/filterx-eval.h" #include "filterx/filterx-globals.h" +#include "filterx/filterx-ref.h" #include "filterx/func-flags.h" #include "filterx/expr-literal-generator.h" #include "filterx/expr-literal.h" @@ -104,6 +105,8 @@ static gboolean _should_unset_string(FilterXFunctionUnsetEmpties *self, FilterXO static gboolean _should_unset(FilterXFunctionUnsetEmpties *self, FilterXObject *obj) { + obj = filterx_ref_get_readonly_value(obj); + if (check_flag(self->flags, FILTERX_FUNC_UNSET_EMPTIES_FLAG_REPLACE_NULL) && filterx_object_is_type(obj, &FILTERX_TYPE_NAME(null))) return TRUE; @@ -129,6 +132,8 @@ _add_key_to_unset_list_if_needed(FilterXObject *key, FilterXObject *value, gpoin if (check_flag(self->flags, FILTERX_FUNC_UNSET_EMPTIES_FLAG_RECURSIVE)) { + value = filterx_ref_get_readonly_value(value); + if (filterx_object_is_type(value, &FILTERX_TYPE_NAME(dict)) && !_process_dict(self, value)) return FALSE; if (filterx_object_is_type(value, &FILTERX_TYPE_NAME(list)) && !_process_list(self, value)) @@ -189,14 +194,16 @@ _process_list(FilterXFunctionUnsetEmpties *self, FilterXObject *obj) { FilterXObject *elem = filterx_list_get_subscript(obj, i); + FilterXObject *inner_elem = filterx_ref_get_readonly_value(elem); + if (check_flag(self->flags, FILTERX_FUNC_UNSET_EMPTIES_FLAG_RECURSIVE)) { - if (filterx_object_is_type(elem, &FILTERX_TYPE_NAME(dict)) && !_process_dict(self, elem)) + if (filterx_object_is_type(inner_elem, &FILTERX_TYPE_NAME(dict)) && !_process_dict(self, inner_elem)) { filterx_object_unref(elem); return FALSE; } - if (filterx_object_is_type(elem, &FILTERX_TYPE_NAME(list)) && !_process_list(self, elem)) + if (filterx_object_is_type(inner_elem, &FILTERX_TYPE_NAME(list)) && !_process_list(self, inner_elem)) { filterx_object_unref(elem); return FALSE; @@ -247,13 +254,15 @@ _eval(FilterXExpr *s) return NULL; } - if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(dict))) - return _eval_on_dict(self, obj); + FilterXObject *inner_obj = filterx_ref_get_writable_value(obj); - if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(list))) - return _eval_on_list(self, obj); + if (filterx_object_is_type(inner_obj, &FILTERX_TYPE_NAME(dict))) + return _eval_on_dict(self, inner_obj); - filterx_eval_push_error("Object must be dict or list. " FILTERX_FUNC_UNSET_EMPTIES_USAGE, s, obj); + if (filterx_object_is_type(inner_obj, &FILTERX_TYPE_NAME(list))) + return _eval_on_list(self, inner_obj); + + filterx_eval_push_error("Object must be dict or list. " FILTERX_FUNC_UNSET_EMPTIES_USAGE, s, inner_obj); filterx_object_unref(obj); return NULL; } @@ -350,6 +359,9 @@ _handle_target_object(FilterXFunctionUnsetEmpties *self, FilterXObject *target, { g_assert(target); guint64 len; + + target = filterx_ref_get_readonly_value(target); + if (filterx_object_is_type(target, &FILTERX_TYPE_NAME(null))) set_flag(&self->flags, FILTERX_FUNC_UNSET_EMPTIES_FLAG_REPLACE_NULL, TRUE); else if (filterx_object_is_type(target, &FILTERX_TYPE_NAME(list))) diff --git a/lib/filterx/object-dict-interface.c b/lib/filterx/object-dict-interface.c index aa185400f..5111c5b04 100644 --- a/lib/filterx/object-dict-interface.c +++ b/lib/filterx/object-dict-interface.c @@ -25,6 +25,7 @@ #include "filterx/object-extractor.h" #include "filterx/object-string.h" #include "filterx/object-json.h" +#include "filterx/filterx-ref.h" #include "str-utils.h" gboolean @@ -53,6 +54,7 @@ filterx_dict_merge(FilterXObject *s, FilterXObject *other) { FilterXDict *self = (FilterXDict *) s; + other = filterx_ref_get_readonly_value(other); g_assert(filterx_object_is_type(other, &FILTERX_TYPE_NAME(dict))); return filterx_dict_iter(other, _add_elem_to_dict, self); } @@ -214,6 +216,9 @@ filterx_dict_init_instance(FilterXDict *self, FilterXType *type) static FilterXObject * _add(FilterXObject *lhs_object, FilterXObject *rhs_object) { + lhs_object = filterx_ref_get_readonly_value(lhs_object); + rhs_object = filterx_ref_get_readonly_value(rhs_object); + if (!filterx_object_is_type(lhs_object, &FILTERX_TYPE_NAME(dict)) || !filterx_object_is_type(rhs_object, &FILTERX_TYPE_NAME(dict))) return NULL; diff --git a/lib/filterx/object-json-array.c b/lib/filterx/object-json-array.c index 49f5d5eff..5b12ab6f6 100644 --- a/lib/filterx/object-json-array.c +++ b/lib/filterx/object-json-array.c @@ -30,6 +30,7 @@ #include "filterx/object-list-interface.h" #include "filterx/expr-function.h" #include "filterx/filterx-eval.h" +#include "filterx/filterx-ref.h" #include "logmsg/type-hinting.h" #include "str-repr/encode.h" @@ -328,6 +329,7 @@ filterx_json_array_new_from_args(FilterXExpr *s, GPtrArray *args) FilterXObject *arg = (FilterXObject *) g_ptr_array_index(args, 0); + arg = filterx_ref_get_readonly_value(arg); if (filterx_object_is_type(arg, &FILTERX_TYPE_NAME(json_array))) return filterx_object_ref(arg); @@ -354,6 +356,8 @@ filterx_json_array_new_empty(void) const gchar * filterx_json_array_to_json_literal(FilterXObject *s) { + s = filterx_ref_get_readonly_value(s); + FilterXJsonArray *self = (FilterXJsonArray *) s; if (!filterx_object_is_type(s, &FILTERX_TYPE_NAME(json_array))) @@ -365,6 +369,8 @@ filterx_json_array_to_json_literal(FilterXObject *s) struct json_object * filterx_json_array_get_value(FilterXObject *s) { + s = filterx_ref_get_readonly_value(s); + if (!filterx_object_is_type(s, &FILTERX_TYPE_NAME(json_array))) return NULL; diff --git a/lib/filterx/object-json-object.c b/lib/filterx/object-json-object.c index d8848d872..6455cce4b 100644 --- a/lib/filterx/object-json-object.c +++ b/lib/filterx/object-json-object.c @@ -27,6 +27,7 @@ #include "filterx/object-primitive.h" #include "filterx/object-string.h" #include "filterx/filterx-weakrefs.h" +#include "filterx/filterx-ref.h" #include "filterx/object-dict-interface.h" #include "syslog-ng.h" #include "str-utils.h" @@ -293,6 +294,8 @@ filterx_json_object_new_empty(void) const gchar * filterx_json_object_to_json_literal(FilterXObject *s) { + s = filterx_ref_get_readonly_value(s); + FilterXJsonObject *self = (FilterXJsonObject *) s; if (!filterx_object_is_type(s, &FILTERX_TYPE_NAME(json_object))) @@ -304,6 +307,8 @@ filterx_json_object_to_json_literal(FilterXObject *s) struct json_object * filterx_json_object_get_value(FilterXObject *s) { + s = filterx_ref_get_readonly_value(s); + if (!filterx_object_is_type(s, &FILTERX_TYPE_NAME(json_object))) return NULL; diff --git a/lib/filterx/object-json.c b/lib/filterx/object-json.c index 79aae3c73..a70a63cb1 100644 --- a/lib/filterx/object-json.c +++ b/lib/filterx/object-json.c @@ -29,6 +29,7 @@ #include "filterx/object-list-interface.h" #include "filterx/object-message-value.h" #include "filterx/filterx-eval.h" +#include "filterx/filterx-ref.h" #include "scanner/list-scanner/list-scanner.h" #include "str-repr/encode.h" @@ -197,6 +198,8 @@ filterx_json_new_from_args(FilterXExpr *s, GPtrArray *args) FilterXObject *arg = (FilterXObject *) g_ptr_array_index(args, 0); + arg = filterx_ref_get_readonly_value(arg); + if (filterx_object_is_type(arg, &FILTERX_TYPE_NAME(json_array)) || filterx_object_is_type(arg, &FILTERX_TYPE_NAME(json_object))) return filterx_object_ref(arg); @@ -252,6 +255,8 @@ filterx_json_new_from_object(struct json_object *jso) const gchar * filterx_json_to_json_literal(FilterXObject *s) { + s = filterx_ref_get_readonly_value(s); + if (filterx_object_is_type(s, &FILTERX_TYPE_NAME(json_object))) return filterx_json_object_to_json_literal(s); if (filterx_object_is_type(s, &FILTERX_TYPE_NAME(json_array))) diff --git a/lib/filterx/object-list-interface.c b/lib/filterx/object-list-interface.c index 497ca0e99..679d3aaeb 100644 --- a/lib/filterx/object-list-interface.c +++ b/lib/filterx/object-list-interface.c @@ -24,6 +24,7 @@ #include "filterx/object-list-interface.h" #include "filterx/object-primitive.h" #include "filterx/object-json.h" +#include "filterx/filterx-ref.h" FilterXObject * filterx_list_get_subscript(FilterXObject *s, gint64 index) @@ -64,6 +65,7 @@ filterx_list_unset_index(FilterXObject *s, gint64 index) gboolean filterx_list_merge(FilterXObject *s, FilterXObject *other) { + other = filterx_ref_get_readonly_value(other); g_assert(filterx_object_is_type(other, &FILTERX_TYPE_NAME(list))); guint64 len; @@ -301,6 +303,9 @@ filterx_list_init_instance(FilterXList *self, FilterXType *type) static FilterXObject * _add(FilterXObject *lhs_object, FilterXObject *rhs_object) { + lhs_object = filterx_ref_get_readonly_value(lhs_object); + rhs_object = filterx_ref_get_readonly_value(rhs_object); + if (!filterx_object_is_type(lhs_object, &FILTERX_TYPE_NAME(list)) || !filterx_object_is_type(rhs_object, &FILTERX_TYPE_NAME(list))) return NULL; diff --git a/modules/csvparser/filterx-func-format-csv.c b/modules/csvparser/filterx-func-format-csv.c index 9d51f00a7..bf03f4666 100644 --- a/modules/csvparser/filterx-func-format-csv.c +++ b/modules/csvparser/filterx-func-format-csv.c @@ -27,6 +27,7 @@ #include "filterx/object-dict-interface.h" #include "filterx/object-list-interface.h" #include "filterx/filterx-eval.h" +#include "filterx/filterx-ref.h" #include "scratch-buffers.h" #include "utf8utils.h" @@ -54,11 +55,12 @@ _append_to_buffer(FilterXObject *key, FilterXObject *value, gpointer user_data) if (!value) value = self->default_value; - if (filterx_object_is_type(value, &FILTERX_TYPE_NAME(dict)) || - filterx_object_is_type(value, &FILTERX_TYPE_NAME(list))) + FilterXObject *inner_value = filterx_ref_get_readonly_value(value); + if (filterx_object_is_type(inner_value, &FILTERX_TYPE_NAME(dict)) || + filterx_object_is_type(inner_value, &FILTERX_TYPE_NAME(list))) { msg_debug("FilterX: format_csv(): skipping object, type not supported", - evt_tag_str("type", value->type->name)); + evt_tag_str("type", inner_value->type->name)); return TRUE; } @@ -113,7 +115,8 @@ _handle_dict_input(FilterXFunctionFormatCSV *self, FilterXObject *csv_data, GStr if (self->columns) { FilterXObject *cols = filterx_expr_eval(self->columns); - if (!cols || !filterx_object_is_type(cols, &FILTERX_TYPE_NAME(list)) || !filterx_object_len(cols, &size)) + FilterXObject *inner_cols = filterx_ref_get_readonly_value(cols); + if (!inner_cols || !filterx_object_is_type(inner_cols, &FILTERX_TYPE_NAME(list)) || !filterx_object_len(cols, &size)) { filterx_object_unref(cols); filterx_eval_push_error("Columns must represented as list. " FILTERX_FUNC_FORMAT_CSV_USAGE, &self->super.super, NULL); @@ -148,9 +151,10 @@ _eval(FilterXExpr *s) gboolean success = FALSE; GString *formatted = scratch_buffers_alloc(); - if (filterx_object_is_type(csv_data, &FILTERX_TYPE_NAME(list))) + FilterXObject *inner_csv_data = filterx_ref_get_readonly_value(csv_data); + if (filterx_object_is_type(inner_csv_data, &FILTERX_TYPE_NAME(list))) success = _handle_list_input(self, csv_data, formatted); - else if (filterx_object_is_type(csv_data, &FILTERX_TYPE_NAME(dict))) + else if (filterx_object_is_type(inner_csv_data, &FILTERX_TYPE_NAME(dict))) success = _handle_dict_input(self, csv_data, formatted); else filterx_eval_push_error("input must be a dict or list. " FILTERX_FUNC_FORMAT_CSV_USAGE, s, csv_data);