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-Casbin.NET.git
The following commit(s) were added to refs/heads/master by this push:
new 771066d fix: handle escaped quotes and brackets in literal in-lists
771066d is described below
commit 771066d0e94df76f84e10c7fffbf648c4b926151
Author: Yang Luo <[email protected]>
AuthorDate: Sun Oct 25 22:02:20 2026 +0800
fix: handle escaped quotes and brackets in literal in-lists
---
Casbin.UnitTests/ModelTests/EnforcerTest.cs | 26 ++++++++++++++++++++++
Casbin.UnitTests/UtilTests/StringUtilTest.cs | 18 ++++++++++++++++
Casbin/Util/StringUtil.cs | 32 +++++++++++++++++-----------
3 files changed, 63 insertions(+), 13 deletions(-)
diff --git a/Casbin.UnitTests/ModelTests/EnforcerTest.cs
b/Casbin.UnitTests/ModelTests/EnforcerTest.cs
index 578c2c6..5ebdf69 100644
--- a/Casbin.UnitTests/ModelTests/EnforcerTest.cs
+++ b/Casbin.UnitTests/ModelTests/EnforcerTest.cs
@@ -1291,6 +1291,32 @@ public class EnforcerTest
#endregion
+ [Fact]
+ public void TestInOperatorWithLiteralList()
+ {
+ string text =
+ "[request_definition]\n"
+ + "r = sub, obj, act\n"
+ + "\n"
+ + "[policy_definition]\n"
+ + "p = sub, obj, act\n"
+ + "\n"
+ + "[policy_effect]\n"
+ + "e = some(where (p.eft == allow))\n"
+ + "\n"
+ + "[matchers]\n"
+ + "m = r.sub == p.sub && r.obj in (\"a, \\\"b,c\\\"\", \"f(x)\")
&& r.act in ['read', 'write']\n";
+
+ Enforcer e = new(DefaultModel.CreateFromText(text));
+ e.AddPolicy("alice", "any", "any");
+
+ Assert.True(e.Enforce("alice", "a, \"b,c\"", "read"));
+ Assert.True(e.Enforce("alice", "f(x)", "write"));
+ Assert.False(e.Enforce("alice", "a", "read"));
+ Assert.False(e.Enforce("alice", "f(x)", "delete"));
+ Assert.False(e.Enforce("bob", "f(x)", "read"));
+ }
+
#if !NET452
#region ExpressionHandler Tests
diff --git a/Casbin.UnitTests/UtilTests/StringUtilTest.cs
b/Casbin.UnitTests/UtilTests/StringUtilTest.cs
index bd5daf7..1a697c1 100644
--- a/Casbin.UnitTests/UtilTests/StringUtilTest.cs
+++ b/Casbin.UnitTests/UtilTests/StringUtilTest.cs
@@ -61,6 +61,24 @@ public class StringUtilTest
]
];
+ public static IEnumerable<object[]> ReplaceInListOperatorTestData =
+ [
+ ["r.obj in (\"a\", \"b\")", "(r.obj == \"a\" || r.obj == \"b\")"],
+ ["r.obj in [\"a\", \"b\"]", "(r.obj == \"a\" || r.obj == \"b\")"],
+ ["r.obj in (\"a\")", "(r.obj == \"a\")"],
+ ["r.obj in (\"a,b\", \"c\")", "(r.obj == \"a,b\" || r.obj == \"c\")"],
+ ["r.obj in (\"a, \\\"b,c\\\"\", \"d\")", "(r.obj == \"a, \\\"b,c\\\"\"
|| r.obj == \"d\")"],
+ ["r.obj in (\"a\\\\\", \"b\")", "(r.obj == \"a\\\\\" || r.obj ==
\"b\")"],
+ ["r.obj in (\"f(x)\", \"[y]\")", "(r.obj == \"f(x)\" || r.obj ==
\"[y]\")"],
+ ["r.obj in [\"f(x)\", \"[y]\"]", "(r.obj == \"f(x)\" || r.obj ==
\"[y]\")"],
+ ["r.obj in (p.obj)", "r.obj in (p.obj)"]
+ ];
+
+ [Theory]
+ [MemberData(nameof(ReplaceInListOperatorTestData))]
+ public void TestReplaceInListOperator(string expressionString, string
expected) =>
+ Assert.Equal(expected,
StringUtil.ReplaceInListOperator(expressionString));
+
[Theory]
[MemberData(nameof(RemoveCommentsTestData))]
public void TestRemoveComments(string except, string actual) =>
Assert.Equal(except, actual.RemoveComments());
diff --git a/Casbin/Util/StringUtil.cs b/Casbin/Util/StringUtil.cs
index c6cbd73..d82dda1 100644
--- a/Casbin/Util/StringUtil.cs
+++ b/Casbin/Util/StringUtil.cs
@@ -9,7 +9,7 @@ namespace Casbin.Util
{
private static readonly Regex s_evalRegex =
new(@"\beval\((?<rule>[^)]*)\)");
private static readonly Regex s_inOperatorRegex =
new(@"([a-zA-Z0-9_.()""]+) in ([a-zA-Z0-9_.()""]+)");
- private static readonly Regex s_inListOperatorRegex =
new(@"([a-zA-Z0-9_.]+)\s+in\s+(?:\(([^()]*)\)|\[([^\[\]]*)\])");
+ private static readonly Regex s_inListOperatorRegex =
new(@"([a-zA-Z0-9_.]+)\s+in\s+(?:\(((?:""(?:[^""\\]|\\.)*""|[^()""])*)\)|\[((?:""(?:[^""\\]|\\.)*""|[^\[\]""])*)\])");
/// <summary>
/// Removes the comments starting with # in the text.
@@ -138,28 +138,34 @@ namespace Casbin.Util
List<string> values = new();
int start = 0;
bool inQuotes = false;
- for (int i = 0; i <= list.Length; i++)
+ for (int i = 0; i < list.Length; i++)
{
- if (i < list.Length && list[i] is '"')
+ switch (list[i])
{
- inQuotes = !inQuotes;
+ case '\\' when inQuotes:
+ i++;
+ break;
+ case '"':
+ inQuotes = !inQuotes;
+ break;
+ case ',' when inQuotes is false:
+ AddValue(list.Substring(start, i - start));
+ start = i + 1;
+ break;
}
+ }
- if (i < list.Length && (inQuotes || list[i] is not ','))
- {
- continue;
- }
+ AddValue(list.Substring(start));
+ return values;
- string value = list.Substring(start, i - start).Trim();
+ void AddValue(string value)
+ {
+ value = value.Trim();
if (value.Length is not 0)
{
values.Add(value);
}
-
- start = i + 1;
}
-
- return values;
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]