From 9f19325e6773e61b4c188bc313a551b318cd809d Mon Sep 17 00:00:00 2001 From: Ahmed Hany Gamal Date: Wed, 4 Mar 2026 21:05:26 +0200 Subject: [PATCH 1/2] fix: reject invalid escape sequences in JSON Pointer strings --- lib/index.js | 4 +++ lib/pointerSegments.test.js | 60 +++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 lib/pointerSegments.test.js diff --git a/lib/index.js b/lib/index.js index 74d9707..4d05cfb 100644 --- a/lib/index.js +++ b/lib/index.js @@ -10,6 +10,10 @@ export const pointerSegments = function* (pointer) { throw Error("Invalid JSON Pointer"); } + if (pointer.search(/~(?![01])/) !== -1) { + throw Error("Invalid JSON Pointer"); + } + let segmentStart = 1; let segmentEnd = 0; diff --git a/lib/pointerSegments.test.js b/lib/pointerSegments.test.js new file mode 100644 index 0000000..151244b --- /dev/null +++ b/lib/pointerSegments.test.js @@ -0,0 +1,60 @@ +import { describe, expect, test } from "vitest"; +import { pointerSegments } from "./index.js"; + + +describe("JsonPointer", () => { + describe("pointerSegments", () => { + /** @type [string, string[]][] */ + const tests = [ + ["", []], + ["/", [""]], + ["/foo", ["foo"]], + ["/foo/bar", ["foo", "bar"]], + ["/foo/0", ["foo", "0"]], + ["/a~1b", ["a/b"]], + ["/m~0n", ["m~n"]], + ["/~00", ["~0"]], + ["/~01", ["~1"]], + ["/~10", ["/0"]], + ["/~11", ["/1"]], + ["/~01~10", ["~1/0"]], + ["/~00/~11", ["~0", "/1"]], + ["/ ", [" "]], + ["/c%d", ["c%d"]], + ["/e^f", ["e^f"]], + ["/g|h", ["g|h"]], + ["/i\\j", ["i\\j"]], + ["/k\"l", ["k\"l"]] + ]; + + tests.forEach(([pointer, expected]) => { + test(`${JSON.stringify(pointer)} => ${JSON.stringify(expected)}`, () => { + expect([...pointerSegments(pointer)]).to.eql(expected); + }); + }); + }); + + describe("a pointer that doesn't start with '/'", () => { + test("should throw an error", () => { + expect(() => [...pointerSegments("foo")]).to.throw(Error, "Invalid JSON Pointer"); + }); + }); + + describe("a pointer with an invalid escape sequence", () => { + /** @type string[] */ + const tests = [ + "/~", + "/~2", + "/~a", + "/a~", + "/~~", + "/~0~" + ]; + + tests.forEach((pointer) => { + test(`${JSON.stringify(pointer)} should throw an error`, () => { + expect(() => [...pointerSegments(pointer)]).to.throw(Error, "Invalid JSON Pointer"); + }); + }); + }); +}); From b61af58e352423c89cbc36cfc5879b681b5d127d Mon Sep 17 00:00:00 2001 From: Ahmed Hany Gamal Date: Thu, 5 Mar 2026 01:57:30 +0200 Subject: [PATCH 2/2] refactor: use RegExp.test instead of String.search for escape validation --- lib/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index 4d05cfb..bf522a9 100644 --- a/lib/index.js +++ b/lib/index.js @@ -10,7 +10,7 @@ export const pointerSegments = function* (pointer) { throw Error("Invalid JSON Pointer"); } - if (pointer.search(/~(?![01])/) !== -1) { + if (/~(?![01])/.test(pointer)) { throw Error("Invalid JSON Pointer"); }