From e362dfd686c1dadd1dd9324373819be446fd4f04 Mon Sep 17 00:00:00 2001 From: Andrew Coleman Date: Tue, 19 May 2026 08:30:37 +0100 Subject: [PATCH] Prevent object contructor setting internal flags The evaluator internally represents functions and lambdas using objects tagged with the properties `_jsonata_function` or `_jsonata_lambda`. This commit prevents expressions from setting these flags in the object constructor, which could potentially interfere with the processing of the expression. Signed-off-by: Andrew Coleman --- src/jsonata.js | 11 +++++++++++ test/implementation-tests.js | 15 +++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/jsonata.js b/src/jsonata.js index 5f9bf2c7..514b5abf 100644 --- a/src/jsonata.js +++ b/src/jsonata.js @@ -941,6 +941,16 @@ var jsonata = (function() { } if (key !== undefined) { + // reject any attempts to set the internal JSONata flags + if (key === '_jsonata_lambda' || key === '_jsonata_function') { + // this is a restriction of this implementation rather than JSONata itself + throw { + code: "D1013", + stack: (new Error()).stack, + position: expr.position, + value: key + }; + } var entry = {data: item, exprIndex: pairIndex}; if (groups.hasOwnProperty(key)) { // a value already exists in this slot @@ -2012,6 +2022,7 @@ var jsonata = (function() { "T1010": "The matcher function argument passed to function {{token}} does not return the correct object structure", "D1011": "Stack overflow. Check for non-terminating recursive function. Consider rewriting as tail-recursive", "D1012": "Evaluation timeout after {{value}} milliseconds. Check for infinite loop", + "D1013": "Object property names starting with _jsonata_ are reserved for internal use: {{value}}", "T2001": "The left side of the {{token}} operator must evaluate to a number", "T2002": "The right side of the {{token}} operator must evaluate to a number", "T2003": "The left side of the range operator (..) must evaluate to an integer", diff --git a/test/implementation-tests.js b/test/implementation-tests.js index 102334f0..bcb878c4 100644 --- a/test/implementation-tests.js +++ b/test/implementation-tests.js @@ -1124,6 +1124,21 @@ describe("Tests that include infinite recursion", () => { }); }); +describe("Tests invalid object creation", () => { + it("prevents creating an object mimicking a lambda", () => { + const expr = jsonata('($lambda = {"_jsonata_lambda": true}; $lambda())'); + expect(expr.evaluate()).to.eventually.be.rejected.to.deep.contain({ + code: "D1013", + }); + }) + it("prevents creating an object mimicking a function", () => { + const expr = jsonata('($fn = {"_jsonata_function": true}; $fn())'); + expect(expr.evaluate()).to.eventually.be.rejected.to.deep.contain({ + code: "D1013", + }); + }) +}) + describe("Tests that use internal frame push callbacks", () => { describe("frame push callback bound to expression", function() { it("calls callback when new frame created", function(done) {