You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@casbin.apache.org by hs...@apache.org on 2026/10/20 14:30:15 UTC
(casbin-node-casbin) branch master updated: fix: protect single-quoted literals in escapeAssertion
This is an automated email from the ASF dual-hosted git repository.
hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin-node-casbin.git
The following commit(s) were added to refs/heads/master by this push:
new 18d8696 fix: protect single-quoted literals in escapeAssertion
18d8696 is described below
commit 18d8696faa491161516c88f3b576d433907e0859
Author: Yang Luo <hs...@gmail.com>
AuthorDate: Tue Oct 20 22:30:04 2026 +0800
fix: protect single-quoted literals in escapeAssertion
---
src/model/model.ts | 10 ----------
src/util/util.ts | 24 ++++++++++++++++++++++++
test/util.test.ts | 4 ++++
3 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/src/model/model.ts b/src/model/model.ts
index 49a7cd1..d31666d 100644
--- a/src/model/model.ts
+++ b/src/model/model.ts
@@ -96,18 +96,8 @@ export class Model {
ast.tokens = tokens;
} else if (sec === 'm') {
- const stringArguments = value.match(/\"(.*?)\"/g) || [];
-
- stringArguments.forEach((n, index) => {
- value = value.replace(n, `$<${index}>`);
- });
-
value = util.escapeAssertion(value);
- stringArguments.forEach((n, index) => {
- value = value.replace(`$<${index}>`, n);
- });
-
const invalidOperators = /(?<![&|])&(?!&)|(?<![&|])\|(?!\|)|&{3,}|\|{3,}/g;
if (invalidOperators.test(value)) {
throw new Error(`Invalid operator in matcher`);
diff --git a/src/util/util.ts b/src/util/util.ts
index 8ceead7..1646107 100644
--- a/src/util/util.ts
+++ b/src/util/util.ts
@@ -19,7 +19,31 @@ import { mustGetDefaultFileSystem } from '../persist';
const escapeAssertionReg = new RegExp(/([()\s|&,=!><+\-*/]|^)((r|p)[0-9]*)\./g);
+// Quoted string literals are kept as they are.
function escapeAssertion(s: string): string {
+ let res = '';
+ let start = 0;
+ for (let i = 0; i < s.length; i++) {
+ const quote = s[i];
+ if (quote !== '"' && quote !== "'") {
+ continue;
+ }
+ let end = i + 1;
+ while (end < s.length && s[end] !== quote) {
+ if (s[end] === '\\') {
+ end++;
+ }
+ end++;
+ }
+ end = Math.min(end + 1, s.length);
+ res += escapeAssertionUnquoted(s.slice(start, i)) + s.slice(i, end);
+ start = end;
+ i = end - 1;
+ }
+ return res + escapeAssertionUnquoted(s.slice(start));
+}
+
+function escapeAssertionUnquoted(s: string): string {
s = s.replace(escapeAssertionReg, (match) => {
// Replace only the last dot with underscore (preserve the prefix character)
const lastDotIdx = match.lastIndexOf('.');
diff --git a/test/util.test.ts b/test/util.test.ts
index 44cdcc2..d5b9509 100644
--- a/test/util.test.ts
+++ b/test/util.test.ts
@@ -367,4 +367,8 @@ test('test escapeAssertion', () => {
// Test that patterns inside strings are not escaped
expect(util.escapeAssertion('r.sub == "a.p.p.l.e"')).toEqual('r_sub == "a.p.p.l.e"');
expect(util.escapeAssertion('r.sub == "test.p.value"')).toEqual('r_sub == "test.p.value"');
+ expect(util.escapeAssertion(`r.obj == 'https://p.example.com' && p.sub == r.sub`)).toEqual(
+ `r_obj == 'https://p.example.com' && p_sub == r_sub`
+ );
+ expect(util.escapeAssertion(`r.obj == "a\\"/p.b" || p.obj == '/r.c'`)).toEqual(`r_obj == "a\\"/p.b" || p_obj == '/r.c'`);
});
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@casbin.apache.org
For additional commands, e-mail: commits-help@casbin.apache.org