From 0bd7db301e5b9694214986b85cb8bf4ca58992f0 Mon Sep 17 00:00:00 2001 From: Jeroen van der Heijden Date: Mon, 13 May 2024 11:24:03 +0200 Subject: [PATCH] Fix #381 --- inc/ti/fn/fnjsonload.h | 30 +++++++++++------------------- inc/ti/version.h | 4 ++-- itest/test_advanced.py | 33 +++++++++++++++++++++++---------- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/inc/ti/fn/fnjsonload.h b/inc/ti/fn/fnjsonload.h index bf26a279..10d5b267 100644 --- a/inc/ti/fn/fnjsonload.h +++ b/inc/ti/fn/fnjsonload.h @@ -142,12 +142,6 @@ static int jload__start_array(void * ctx) jload__convert_t * c = (jload__convert_t *) ctx; ti_val_t * val; - if (++c->deep >= YAJL_MAX_DEPTH) - { - ex_set(c->e, EX_OPERATION, "JSON max depth exceeded"); - return 0; /* error */ - } - val = (ti_val_t *) ti_varr_create(7); if (!val) { @@ -155,6 +149,15 @@ static int jload__start_array(void * ctx) return 0; /* failed */ } + if (c->callbacks[c->deep](c->parents[c->deep], val, c->e)) + return 0; /* failed */ + + if (++c->deep >= YAJL_MAX_DEPTH) + { + ex_set(c->e, EX_OPERATION, "JSON max depth exceeded"); + return 0; /* error */ + } + c->parents[c->deep] = val; c->callbacks[c->deep] = (jload__set_cb) jload__array_cb; return 1; /* success */ @@ -163,8 +166,8 @@ static int jload__start_array(void * ctx) static int jload__end_array(void * ctx) { jload__convert_t * c = (jload__convert_t *) ctx; - ti_val_t * val = c->parents[c->deep--]; - return 0 == c->callbacks[c->deep](c->parents[c->deep], val, c->e); + --c->deep; + return 1; /* success */ } static yajl_callbacks jload__callbacks = { @@ -233,17 +236,6 @@ static int do__f_json_load(ti_query_t * query, cleri_node_t * nd, ex_t * e) else ex_set_mem(e); } - while (ctx.deep) - { - /* - * Each but the last parent is a value type. If an array, then the - * value exists but is not appended to another type. Thus, we need - * to clear the array's in the list. - */ - ti_val_t * val = ctx.parents[ctx.deep--]; - if (val && ti_val_is_array(val)) - ti_val_unsafe_drop(val); - } ti_val_drop(ctx.out); free(jload__key); diff --git a/inc/ti/version.h b/inc/ti/version.h index b9ea859e..7914881d 100644 --- a/inc/ti/version.h +++ b/inc/ti/version.h @@ -6,7 +6,7 @@ #define TI_VERSION_MAJOR 1 #define TI_VERSION_MINOR 6 -#define TI_VERSION_PATCH 1 +#define TI_VERSION_PATCH 2 /* The syntax version is used to test compatibility with functions * using the `ti_nodes_check_syntax()` function */ @@ -25,7 +25,7 @@ * "-rc0" * "" */ -#define TI_VERSION_PRE_RELEASE "" +#define TI_VERSION_PRE_RELEASE "-alpha0" #define TI_MAINTAINER \ "Jeroen van der Heijden " diff --git a/itest/test_advanced.py b/itest/test_advanced.py index f05777d2..886bd5cb 100755 --- a/itest/test_advanced.py +++ b/itest/test_advanced.py @@ -98,7 +98,7 @@ async def test_qcache_recursion(self, client): self.assertEqual(len(res), 532) async def test_extend_restrict(self, client): - res = await client.query(r"""//ti + _res = await client.query(r"""//ti set_type('A', {arr: '[str]'}); """) with self.assertRaisesRegex( @@ -1174,7 +1174,7 @@ async def test_mod_del_in_use(self, client): OperationError, r'cannot change type `X` while one of the ' r'instances is in use'): - res = await client.query(''' + _res = await client.query(''' set_type('X', { a: 'int', b: 'int', @@ -1666,7 +1666,7 @@ async def test_ren_after_mod(self, client): self.assertNotIn('m', methods) self.assertEqual(len(methods), 1) - async def test_mod_with_restriction(self, client): + async def test_mod_with_restric_199(self, client): # bug #199 res = await client.query(r"""//ti set_type('Test', {i: 'pint'}); @@ -1675,7 +1675,7 @@ async def test_mod_with_restriction(self, client): """) self.assertEqual(res, {"i": 0}) - async def test_mod_with_restriction(self, client): + async def test_mod_with_restrict_200(self, client): # bug #200 with self.assertRaisesRegex( OperationError, @@ -1829,7 +1829,7 @@ async def test_future_to_type(self, client): }; """) - async def test_in_use_on_dict(self, client): + async def test_in_use_on_dict_242(self, client): # bug #242 await client.query(".set('non name key', nil);") with self.assertRaisesRegex( @@ -1844,7 +1844,7 @@ async def test_in_use_on_dict(self, client): }) """) - async def test_in_use_on_dict(self, client): + async def test_in_use_on_dict_243(self, client): # bug #243 res = await client.query(r"""//ti new_type('A'); @@ -1887,14 +1887,14 @@ async def test_replace_rev_large(self, client): self.assertEqual(s, res) async def test_loop_gc(self, client): - res = await client.query(r"""//ti + _res = await client.query(r"""//ti for (x in range(10)) { x = {}; x.me = x; }; """) # bug #259 - res = await client.query(r"""//ti + _res = await client.query(r"""//ti range(10).sort(|a, b| { a = {}; // overwrite the closure argument a.me = a; // create a self reference @@ -2140,9 +2140,9 @@ async def test_no_declaration_after_flags(self, client): set_type("A", {x: "&"}); """) - async def test_(self, client): + async def test_309(self, client): # bug #309 - res = await client.query("""//ti + _res = await client.query("""//ti new_type('A'); new_type('C'); set_type('A',{ @@ -2587,6 +2587,19 @@ async def test_utf8_range(self, client): """) self.assertEqual(res, {"u": "D"}) + async def test_json_load_i(self, client): + # bug #381 + await client.query("""//ti + json_load('{"a": [{"b": 123}]}'); + """) + + with self.assertRaisesRegex( + ValueError, + r'lexical error: invalid char in json text'): + await client.query("""//ti + json_load('[{"a": [{"b": [1, 1], "c": [3, ..]}]}]'); + """) + if __name__ == '__main__': run_test(TestAdvanced())