From f15c797edae52af16892ef60ab8d438368cee6e7 Mon Sep 17 00:00:00 2001 From: Sander Mertens Date: Tue, 12 Dec 2023 13:17:59 -0800 Subject: [PATCH] Fix crash in query DSL parser when using Rel(X, Y, Z) syntax --- flecs.c | 2 + src/filter.c | 2 + test/addons/project.json | 3 ++ test/addons/src/Parser.c | 104 +++++++++++++++++++++++++++++++++++++++ test/addons/src/main.c | 17 ++++++- 5 files changed, 127 insertions(+), 1 deletion(-) diff --git a/flecs.c b/flecs.c index 737a077d87..fe64996965 100644 --- a/flecs.c +++ b/flecs.c @@ -11305,6 +11305,8 @@ ecs_filter_t* ecs_filter_init( if (ptr[0] == '\n') { break; } + + ecs_os_zeromem(extra_args); } if (!ptr) { diff --git a/src/filter.c b/src/filter.c index 09694a6bd9..e8fca54233 100644 --- a/src/filter.c +++ b/src/filter.c @@ -1530,6 +1530,8 @@ ecs_filter_t* ecs_filter_init( if (ptr[0] == '\n') { break; } + + ecs_os_zeromem(extra_args); } if (!ptr) { diff --git a/test/addons/project.json b/test/addons/project.json index 9fc316ed39..258e271e80 100644 --- a/test/addons/project.json +++ b/test/addons/project.json @@ -245,6 +245,9 @@ "pair_4_args", "pair_4_args_implicit_this", "pair_3_args_2_terms", + "pair_3_args_this_tgt", + "pair_3_args_2_terms_this_tgt", + "pair_3_args_2_terms_this_tgt_implicit_this", "cascade_desc" ] }, { diff --git a/test/addons/src/Parser.c b/test/addons/src/Parser.c index 925434527c..b01377fa2b 100644 --- a/test/addons/src/Parser.c +++ b/test/addons/src/Parser.c @@ -5555,3 +5555,107 @@ void Parser_cascade_desc(void) { ecs_fini(world); } + +void Parser_pair_3_args_this_tgt(void) { + ecs_world_t *world = ecs_mini(); + + ECS_TAG(world, Rel); + ECS_TAG(world, Tgt); + + ecs_filter_t f = ECS_FILTER_INIT; + test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){ + .storage = &f, + .expr = "ChildOf($grandchild, $child, $this)" + })); + + test_int(filter_count(&f), 2); + + ecs_term_t *terms = filter_terms(&f); + test_first(terms[0], EcsChildOf, EcsSelf|EcsIsEntity); + test_src_var(terms[0], 0, EcsSelf|EcsIsVariable, "grandchild"); + test_second_var(terms[0], 0, EcsSelf|EcsIsVariable, "child"); + test_int(terms[0].oper, EcsAnd); + test_int(terms[0].inout, EcsInOutDefault); + + test_first(terms[1], EcsChildOf, EcsSelf|EcsIsEntity); + test_src_var(terms[1], 0, EcsSelf|EcsIsVariable, "child"); + test_second(terms[1], EcsThis, EcsSelf|EcsIsVariable); + test_int(terms[1].oper, EcsAnd); + test_int(terms[1].inout, EcsInOutDefault); + + ecs_filter_fini(&f); + + ecs_fini(world); +} + +void Parser_pair_3_args_2_terms_this_tgt(void) { + ecs_world_t *world = ecs_mini(); + + ECS_TAG(world, Rel); + + ecs_filter_t f = ECS_FILTER_INIT; + test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){ + .storage = &f, + .expr = "ChildOf($grandchild, $child, $this), Rel($this)" + })); + + test_int(filter_count(&f), 3); + + ecs_term_t *terms = filter_terms(&f); + test_first(terms[0], EcsChildOf, EcsSelf|EcsIsEntity); + test_src_var(terms[0], 0, EcsSelf|EcsIsVariable, "grandchild"); + test_second_var(terms[0], 0, EcsSelf|EcsIsVariable, "child"); + test_int(terms[0].oper, EcsAnd); + test_int(terms[0].inout, EcsInOutDefault); + + test_first(terms[1], EcsChildOf, EcsSelf|EcsIsEntity); + test_src_var(terms[1], 0, EcsSelf|EcsIsVariable, "child"); + test_second(terms[1], EcsThis, EcsSelf|EcsIsVariable); + test_int(terms[1].oper, EcsAnd); + test_int(terms[1].inout, EcsInOutDefault); + + test_first(terms[2], Rel, EcsSelf|EcsIsEntity); + test_src(terms[2], EcsThis, EcsSelf|EcsUp|EcsIsVariable); + test_int(terms[2].oper, EcsAnd); + test_int(terms[2].inout, EcsInOutDefault); + + ecs_filter_fini(&f); + + ecs_fini(world); +} + +void Parser_pair_3_args_2_terms_this_tgt_implicit_this(void) { + ecs_world_t *world = ecs_mini(); + + ECS_TAG(world, Rel); + + ecs_filter_t f = ECS_FILTER_INIT; + test_assert(NULL != ecs_filter_init(world, &(ecs_filter_desc_t){ + .storage = &f, + .expr = "ChildOf($grandchild, $child, $this), Rel" + })); + + test_int(filter_count(&f), 3); + + ecs_term_t *terms = filter_terms(&f); + test_first(terms[0], EcsChildOf, EcsSelf|EcsIsEntity); + test_src_var(terms[0], 0, EcsSelf|EcsIsVariable, "grandchild"); + test_second_var(terms[0], 0, EcsSelf|EcsIsVariable, "child"); + test_int(terms[0].oper, EcsAnd); + test_int(terms[0].inout, EcsInOutDefault); + + test_first(terms[1], EcsChildOf, EcsSelf|EcsIsEntity); + test_src_var(terms[1], 0, EcsSelf|EcsIsVariable, "child"); + test_second(terms[1], EcsThis, EcsSelf|EcsIsVariable); + test_int(terms[1].oper, EcsAnd); + test_int(terms[1].inout, EcsInOutDefault); + + test_first(terms[2], Rel, EcsSelf|EcsIsEntity); + test_src(terms[2], EcsThis, EcsSelf|EcsUp|EcsIsVariable); + test_int(terms[2].oper, EcsAnd); + test_int(terms[2].inout, EcsInOutDefault); + + ecs_filter_fini(&f); + + ecs_fini(world); +} diff --git a/test/addons/src/main.c b/test/addons/src/main.c index e192ca7611..7258cd736a 100644 --- a/test/addons/src/main.c +++ b/test/addons/src/main.c @@ -240,6 +240,9 @@ void Parser_pair_3_args_implicit_this(void); void Parser_pair_4_args(void); void Parser_pair_4_args_implicit_this(void); void Parser_pair_3_args_2_terms(void); +void Parser_pair_3_args_this_tgt(void); +void Parser_pair_3_args_2_terms_this_tgt(void); +void Parser_pair_3_args_2_terms_this_tgt_implicit_this(void); void Parser_cascade_desc(void); // Testsuite 'Plecs' @@ -2674,6 +2677,18 @@ bake_test_case Parser_testcases[] = { "pair_3_args_2_terms", Parser_pair_3_args_2_terms }, + { + "pair_3_args_this_tgt", + Parser_pair_3_args_this_tgt + }, + { + "pair_3_args_2_terms_this_tgt", + Parser_pair_3_args_2_terms_this_tgt + }, + { + "pair_3_args_2_terms_this_tgt_implicit_this", + Parser_pair_3_args_2_terms_this_tgt_implicit_this + }, { "cascade_desc", Parser_cascade_desc @@ -8506,7 +8521,7 @@ static bake_test_suite suites[] = { "Parser", NULL, NULL, - 232, + 235, Parser_testcases }, {