Skip to content

Commit 1ac43fc

Browse files
committed
filterx: unwrap references where downcasts are used
FilterXRef can mimic the functionality of its referenced value, but only through virtual methods. Where (implicit) downcasts are used, it is impossible to be transparent about references, so these unwrap methods have to be used. This is far from ideal, but doing downcasts based on is_type() is the original and real problem here. Signed-off-by: László Várady <[email protected]>
1 parent 1223b0d commit 1ac43fc

28 files changed

+192
-94
lines changed

lib/filterx/expr-comparison.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "filterx/object-datetime.h"
3333
#include "filterx/object-message-value.h"
3434
#include "filterx/filterx-object-istype.h"
35+
#include "filterx/filterx-ref.h"
3536
#include "object-primitive.h"
3637
#include "generic-number.h"
3738
#include "parse-number.h"
@@ -141,6 +142,9 @@ _evaluate_as_num(FilterXObject *lhs, FilterXObject *rhs, gint operator)
141142
static gboolean
142143
_evaluate_type_aware(FilterXObject *lhs, FilterXObject *rhs, gint operator)
143144
{
145+
filterx_assert_not_ref(lhs);
146+
filterx_assert_not_ref(rhs);
147+
144148
if (lhs->type == rhs->type &&
145149
(filterx_object_is_type(lhs, &FILTERX_TYPE_NAME(string)) ||
146150
filterx_object_is_type(lhs, &FILTERX_TYPE_NAME(bytes)) ||
@@ -165,6 +169,9 @@ _evaluate_type_aware(FilterXObject *lhs, FilterXObject *rhs, gint operator)
165169
static gboolean
166170
_evaluate_type_and_value_based(FilterXObject *lhs, FilterXObject *rhs, gint operator)
167171
{
172+
filterx_assert_not_ref(lhs);
173+
filterx_assert_not_ref(rhs);
174+
168175
if (operator == FCMPX_EQ)
169176
{
170177
if (lhs->type != rhs->type)
@@ -202,15 +209,17 @@ _eval(FilterXExpr *s)
202209
return NULL;
203210
}
204211

212+
FilterXObject *lhs = filterx_ref_unwrap_ro(lhs_object);
213+
FilterXObject *rhs = filterx_ref_unwrap_ro(rhs_object);
205214
gboolean result = TRUE;
206215
if (compare_mode & FCMPX_TYPE_AWARE)
207-
result = _evaluate_type_aware(lhs_object, rhs_object, operator);
216+
result = _evaluate_type_aware(lhs, rhs, operator);
208217
else if (compare_mode & FCMPX_STRING_BASED)
209-
result = _evaluate_as_string(lhs_object, rhs_object, operator);
218+
result = _evaluate_as_string(lhs, rhs, operator);
210219
else if (compare_mode & FCMPX_NUM_BASED)
211-
result = _evaluate_as_num(lhs_object, rhs_object, operator);
220+
result = _evaluate_as_num(lhs, rhs, operator);
212221
else if (compare_mode & FCMPX_TYPE_AND_VALUE_BASED)
213-
result = _evaluate_type_and_value_based(lhs_object, rhs_object, operator);
222+
result = _evaluate_type_and_value_based(lhs, rhs, operator);
214223
else
215224
g_assert_not_reached();
216225

lib/filterx/expr-plus-generator.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "object-string.h"
2626
#include "filterx-eval.h"
2727
#include "filterx/filterx-object-istype.h"
28+
#include "filterx/filterx-ref.h"
2829
#include "scratch-buffers.h"
2930
#include "expr-generator.h"
3031
#include "object-list-interface.h"
@@ -40,6 +41,8 @@ typedef struct FilterXOperatorPlusGenerator
4041
static gboolean
4142
_generate_obj(FilterXOperatorPlusGenerator *self, FilterXObject *obj, FilterXObject *fillable)
4243
{
44+
fillable = filterx_ref_unwrap_rw(fillable);
45+
4346
if (filterx_object_is_type(fillable, &FILTERX_TYPE_NAME(list)))
4447
return filterx_list_merge(fillable, obj);
4548

lib/filterx/expr-regexp.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "filterx/object-dict-interface.h"
3030
#include "filterx/expr-function.h"
3131
#include "filterx/filterx-object-istype.h"
32+
#include "filterx/filterx-ref.h"
3233
#include "compat/pcre.h"
3334
#include "scratch-buffers.h"
3435

@@ -269,6 +270,8 @@ _store_matches_to_dict(pcre2_code_8 *pattern, const FilterXReMatchState *state,
269270
static gboolean
270271
_store_matches(pcre2_code_8 *pattern, const FilterXReMatchState *state, FilterXObject *fillable)
271272
{
273+
fillable = filterx_ref_unwrap_rw(fillable);
274+
272275
if (filterx_object_is_type(fillable, &FILTERX_TYPE_NAME(list)))
273276
return _store_matches_to_list(pattern, state, fillable);
274277

lib/filterx/filterx-metrics-labels.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,14 +227,15 @@ _format_expr_to_cache(FilterXExpr *expr, DynMetricsStore *cache)
227227

228228
gboolean success = FALSE;
229229

230-
if (!filterx_object_is_type(obj, &FILTERX_TYPE_NAME(dict)))
230+
FilterXObject *typed_obj = filterx_ref_unwrap_ro(obj);
231+
if (!filterx_object_is_type(typed_obj, &FILTERX_TYPE_NAME(dict)))
231232
{
232233
filterx_eval_push_error_info("failed to format metrics labels, labels must be a dict", expr,
233234
g_strdup_printf("got %s instead", obj->type->name), TRUE);
234235
goto exit;
235236
}
236237

237-
success = filterx_dict_iter(obj, _format_dict_elem_to_cache, cache);
238+
success = filterx_dict_iter(typed_obj, _format_dict_elem_to_cache, cache);
238239
if (!success)
239240
goto exit;
240241

lib/filterx/func-flatten.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "filterx/object-string.h"
2929
#include "filterx/filterx-eval.h"
3030
#include "filterx/filterx-object-istype.h"
31+
#include "filterx/filterx-ref.h"
3132
#include "scratch-buffers.h"
3233

3334
#define FILTERX_FUNC_FLATTEN_USAGE "Usage: flatten(dict, separator=\".\")"
@@ -71,7 +72,8 @@ _collect_modifications_from_elem(FilterXObject *key, FilterXObject *value, gpoin
7172
GString *key_buffer = ((gpointer *) user_data)[3];
7273
gboolean is_top_level = (gboolean) GPOINTER_TO_INT(((gpointer *) user_data)[4]);
7374

74-
if (filterx_object_is_type(value, &FILTERX_TYPE_NAME(dict)))
75+
FilterXObject *dict = filterx_ref_unwrap_ro(value);
76+
if (filterx_object_is_type(dict, &FILTERX_TYPE_NAME(dict)))
7577
{
7678
if (is_top_level)
7779
*top_level_dict_keys = g_list_prepend(*top_level_dict_keys, filterx_object_ref(key));
@@ -85,7 +87,7 @@ _collect_modifications_from_elem(FilterXObject *key, FilterXObject *value, gpoin
8587
g_string_append(key_buffer, self->separator);
8688

8789
gpointer inner_user_data[] = { self, flattened_kvs, NULL, key_buffer, GINT_TO_POINTER(FALSE)};
88-
gboolean result = filterx_dict_iter(value, _collect_modifications_from_elem, inner_user_data);
90+
gboolean result = filterx_dict_iter(dict, _collect_modifications_from_elem, inner_user_data);
8991

9092
g_string_truncate(key_buffer, orig_len);
9193
return result;
@@ -185,12 +187,13 @@ _eval(FilterXExpr *s)
185187
{
186188
FilterXFunctionFlatten *self = (FilterXFunctionFlatten *) s;
187189

188-
FilterXObject *dict = filterx_expr_eval_typed(self->dict_expr);
189-
if (!dict)
190+
FilterXObject *obj = filterx_expr_eval_typed(self->dict_expr);
191+
if (!obj)
190192
return NULL;
191193

192194
gboolean result = FALSE;
193195

196+
FilterXObject *dict = filterx_ref_unwrap_rw(obj);
194197
if (!filterx_object_is_type(dict, &FILTERX_TYPE_NAME(dict)))
195198
{
196199
filterx_eval_push_error_info("object must be a dict", self->dict_expr,
@@ -201,7 +204,7 @@ _eval(FilterXExpr *s)
201204
result = _flatten(self, dict);
202205

203206
exit:
204-
filterx_object_unref(dict);
207+
filterx_object_unref(obj);
205208
return result ? filterx_boolean_new(TRUE) : NULL;
206209
}
207210

lib/filterx/func-istype.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "filterx/filterx-eval.h"
3030
#include "filterx/filterx-globals.h"
3131
#include "filterx/filterx-object-istype.h"
32+
#include "filterx/filterx-ref.h"
3233

3334
#define FILTERX_FUNC_ISTYPE_USAGE "Usage: istype(object, type_str)"
3435

@@ -51,7 +52,9 @@ _eval(FilterXExpr *s)
5152
return NULL;
5253
}
5354

54-
gboolean result = filterx_object_is_type(object_expr, self->type);
55+
FilterXObject *obj = filterx_ref_unwrap_ro(object_expr);
56+
gboolean result = filterx_object_is_type(obj, self->type);
57+
5558
filterx_object_unref(object_expr);
5659
return filterx_boolean_new(result);
5760
}

lib/filterx/func-str.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,9 @@ _expr_affix_eval_needle(FilterXExprAffix *self)
247247
g_ptr_array_add(needles, str_value);
248248
return needles;
249249
}
250-
if (filterx_object_is_type(needle_obj, &FILTERX_TYPE_NAME(list)))
250+
251+
FilterXObject *list_needle = filterx_ref_unwrap_ro(needle_obj);
252+
if (filterx_object_is_type(list_needle, &FILTERX_TYPE_NAME(list)))
251253
{
252254
guint64 len;
253255
filterx_object_len(needle_obj, &len);
@@ -261,7 +263,7 @@ _expr_affix_eval_needle(FilterXExprAffix *self)
261263

262264
for (guint64 i = 0; i < len; i++)
263265
{
264-
FilterXObject *elem = filterx_list_get_subscript(needle_obj, i);
266+
FilterXObject *elem = filterx_list_get_subscript(list_needle, i);
265267

266268
GString *str_value = _obj_format(elem, self->ignore_case);
267269
filterx_object_unref(elem);

lib/filterx/func-unset-empties.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "filterx/expr-literal-generator.h"
3737
#include "filterx/expr-literal.h"
3838
#include "filterx/filterx-object-istype.h"
39+
#include "filterx/filterx-ref.h"
3940

4041
#define FILTERX_FUNC_UNSET_EMPTIES_USAGE "Usage: unset_empties(object, " \
4142
FILTERX_FUNC_UNSET_EMPTIES_ARG_NAME_RECURSIVE"=bool, " \
@@ -105,6 +106,8 @@ static gboolean _should_unset_string(FilterXFunctionUnsetEmpties *self, FilterXO
105106
static gboolean
106107
_should_unset(FilterXFunctionUnsetEmpties *self, FilterXObject *obj)
107108
{
109+
filterx_assert_not_ref(obj);
110+
108111
if (check_flag(self->flags, FILTERX_FUNC_UNSET_EMPTIES_FLAG_REPLACE_NULL) &&
109112
filterx_object_is_type(obj, &FILTERX_TYPE_NAME(null)))
110113
return TRUE;
@@ -128,6 +131,7 @@ _add_key_to_unset_list_if_needed(FilterXObject *key, FilterXObject *value, gpoin
128131
FilterXFunctionUnsetEmpties *self = ((gpointer *) user_data)[0];
129132
GList **keys_to_unset = ((gpointer *) user_data)[1];
130133

134+
value = filterx_ref_unwrap_rw(value);
131135
if (check_flag(self->flags, FILTERX_FUNC_UNSET_EMPTIES_FLAG_RECURSIVE))
132136
{
133137
if (filterx_object_is_type(value, &FILTERX_TYPE_NAME(dict)) && !_process_dict(self, value))
@@ -189,22 +193,23 @@ _process_list(FilterXFunctionUnsetEmpties *self, FilterXObject *obj)
189193
for (gint64 i = ((gint64) len) - 1; i >= 0; i--)
190194
{
191195
FilterXObject *elem = filterx_list_get_subscript(obj, i);
196+
FilterXObject *elem_unwrapped = filterx_ref_unwrap_rw(elem);
192197

193198
if (check_flag(self->flags, FILTERX_FUNC_UNSET_EMPTIES_FLAG_RECURSIVE))
194199
{
195-
if (filterx_object_is_type(elem, &FILTERX_TYPE_NAME(dict)) && !_process_dict(self, elem))
200+
if (filterx_object_is_type(elem_unwrapped, &FILTERX_TYPE_NAME(dict)) && !_process_dict(self, elem_unwrapped))
196201
{
197202
filterx_object_unref(elem);
198203
return FALSE;
199204
}
200-
if (filterx_object_is_type(elem, &FILTERX_TYPE_NAME(list)) && !_process_list(self, elem))
205+
if (filterx_object_is_type(elem_unwrapped, &FILTERX_TYPE_NAME(list)) && !_process_list(self, elem_unwrapped))
201206
{
202207
filterx_object_unref(elem);
203208
return FALSE;
204209
}
205210
}
206211

207-
if (_should_unset(self, elem))
212+
if (_should_unset(self, elem_unwrapped))
208213
{
209214
if (self->replacement)
210215
{
@@ -248,11 +253,12 @@ _eval(FilterXExpr *s)
248253
return NULL;
249254
}
250255

251-
if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(dict)))
252-
return _eval_on_dict(self, obj);
256+
FilterXObject *obj_unwrapped = filterx_ref_unwrap_rw(obj);
257+
if (filterx_object_is_type(obj_unwrapped, &FILTERX_TYPE_NAME(dict)))
258+
return _eval_on_dict(self, obj_unwrapped);
253259

254-
if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(list)))
255-
return _eval_on_list(self, obj);
260+
if (filterx_object_is_type(obj_unwrapped, &FILTERX_TYPE_NAME(list)))
261+
return _eval_on_list(self, obj_unwrapped);
256262

257263
filterx_eval_push_error("Object must be dict or list. " FILTERX_FUNC_UNSET_EMPTIES_USAGE, s, obj);
258264
filterx_object_unref(obj);
@@ -351,6 +357,9 @@ _handle_target_object(FilterXFunctionUnsetEmpties *self, FilterXObject *target,
351357
{
352358
g_assert(target);
353359
guint64 len;
360+
361+
target = filterx_ref_unwrap_ro(target);
362+
354363
if (filterx_object_is_type(target, &FILTERX_TYPE_NAME(null)))
355364
set_flag(&self->flags, FILTERX_FUNC_UNSET_EMPTIES_FLAG_REPLACE_NULL, TRUE);
356365
else if (filterx_object_is_type(target, &FILTERX_TYPE_NAME(list)))

lib/filterx/object-dict-interface.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "filterx/object-string.h"
2727
#include "filterx/object-json.h"
2828
#include "filterx/filterx-object-istype.h"
29+
#include "filterx/filterx-ref.h"
2930
#include "str-utils.h"
3031

3132
gboolean
@@ -54,6 +55,7 @@ filterx_dict_merge(FilterXObject *s, FilterXObject *other)
5455
{
5556
FilterXDict *self = (FilterXDict *) s;
5657

58+
other = filterx_ref_unwrap_ro(other);
5759
g_assert(filterx_object_is_type(other, &FILTERX_TYPE_NAME(dict)));
5860
return filterx_dict_iter(other, _add_elem_to_dict, self);
5961
}
@@ -215,6 +217,7 @@ filterx_dict_init_instance(FilterXDict *self, FilterXType *type)
215217
static FilterXObject *
216218
_add(FilterXObject *lhs_object, FilterXObject *rhs_object)
217219
{
220+
rhs_object = filterx_ref_unwrap_ro(rhs_object);
218221
if (!filterx_object_is_type(rhs_object, &FILTERX_TYPE_NAME(dict)))
219222
return NULL;
220223

lib/filterx/object-json-array.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "filterx/expr-function.h"
3232
#include "filterx/filterx-eval.h"
3333
#include "filterx/filterx-object-istype.h"
34+
#include "filterx/filterx-ref.h"
3435

3536
#include "logmsg/type-hinting.h"
3637
#include "str-repr/encode.h"
@@ -329,7 +330,8 @@ filterx_json_array_new_from_args(FilterXExpr *s, GPtrArray *args)
329330

330331
FilterXObject *arg = (FilterXObject *) g_ptr_array_index(args, 0);
331332

332-
if (filterx_object_is_type(arg, &FILTERX_TYPE_NAME(json_array)))
333+
FilterXObject *json_arr = filterx_ref_unwrap_ro(arg);
334+
if (filterx_object_is_type(json_arr, &FILTERX_TYPE_NAME(json_array)))
333335
return filterx_object_ref(arg);
334336

335337
struct json_object *jso;
@@ -355,22 +357,23 @@ filterx_json_array_new_empty(void)
355357
const gchar *
356358
filterx_json_array_to_json_literal(FilterXObject *s)
357359
{
358-
FilterXJsonArray *self = (FilterXJsonArray *) s;
359-
360+
s = filterx_ref_unwrap_ro(s);
360361
if (!filterx_object_is_type(s, &FILTERX_TYPE_NAME(json_array)))
361362
return NULL;
363+
364+
FilterXJsonArray *self = (FilterXJsonArray *) s;
362365
return _json_string(self);
363366
}
364367

365368
/* NOTE: Consider using filterx_object_extract_json_array() to also support message_value. */
366369
struct json_object *
367370
filterx_json_array_get_value(FilterXObject *s)
368371
{
372+
s = filterx_ref_unwrap_ro(s);
369373
if (!filterx_object_is_type(s, &FILTERX_TYPE_NAME(json_array)))
370374
return NULL;
371375

372376
FilterXJsonArray *self = (FilterXJsonArray *) s;
373-
374377
return self->jso;
375378
}
376379

lib/filterx/object-json-object.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "filterx/filterx-weakrefs.h"
3030
#include "filterx/object-dict-interface.h"
3131
#include "filterx/filterx-object-istype.h"
32+
#include "filterx/filterx-ref.h"
3233
#include "syslog-ng.h"
3334
#include "str-utils.h"
3435
#include "logmsg/type-hinting.h"
@@ -294,22 +295,23 @@ filterx_json_object_new_empty(void)
294295
const gchar *
295296
filterx_json_object_to_json_literal(FilterXObject *s)
296297
{
297-
FilterXJsonObject *self = (FilterXJsonObject *) s;
298-
298+
s = filterx_ref_unwrap_ro(s);
299299
if (!filterx_object_is_type(s, &FILTERX_TYPE_NAME(json_object)))
300300
return NULL;
301+
302+
FilterXJsonObject *self = (FilterXJsonObject *) s;
301303
return _json_string(self);
302304
}
303305

304306
/* NOTE: Consider using filterx_object_extract_json_object() to also support message_value. */
305307
struct json_object *
306308
filterx_json_object_get_value(FilterXObject *s)
307309
{
310+
s = filterx_ref_unwrap_ro(s);
308311
if (!filterx_object_is_type(s, &FILTERX_TYPE_NAME(json_object)))
309312
return NULL;
310313

311314
FilterXJsonObject *self = (FilterXJsonObject *) s;
312-
313315
return self->jso;
314316
}
315317

0 commit comments

Comments
 (0)