This is an automated email from the ASF dual-hosted git repository.

kturner pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/accumulo-access.git


The following commit(s) were added to refs/heads/main by this push:
     new 5d7a944  improves validation in unquote() (#104)
5d7a944 is described below

commit 5d7a94492832121f507029d9d7e7627fd88e95ba
Author: Keith Turner <[email protected]>
AuthorDate: Tue Mar 10 16:06:38 2026 -0700

    improves validation in unquote() (#104)
    
    
    
    Co-authored-by: Christopher Tubbs <[email protected]>
---
 .../accumulo/access/impl/AccessEvaluatorImpl.java  |  3 +--
 .../accumulo/access/impl/AccessExpressionImpl.java | 12 +++++++--
 .../apache/accumulo/access/impl/CharsWrapper.java  |  2 +-
 .../accumulo/access/tests/AccessEvaluatorTest.java | 29 ++++++++++++++++++++--
 4 files changed, 39 insertions(+), 7 deletions(-)

diff --git 
a/modules/core/src/main/java/org/apache/accumulo/access/impl/AccessEvaluatorImpl.java
 
b/modules/core/src/main/java/org/apache/accumulo/access/impl/AccessEvaluatorImpl.java
index 403872a..cc888d3 100644
--- 
a/modules/core/src/main/java/org/apache/accumulo/access/impl/AccessEvaluatorImpl.java
+++ 
b/modules/core/src/main/java/org/apache/accumulo/access/impl/AccessEvaluatorImpl.java
@@ -99,8 +99,7 @@ public final class AccessEvaluatorImpl implements 
AccessEvaluator {
           }
         } else if (isQuoteSymbol(c)) {
           // should only see quote after a slash
-          throw new IllegalArgumentException(
-              "Illegal character after slash in auth String : " + auth);
+          throw new IllegalArgumentException("Unescaped quote in auth : " + 
auth);
         }
 
         unescapedCopy[pos++] = c;
diff --git 
a/modules/core/src/main/java/org/apache/accumulo/access/impl/AccessExpressionImpl.java
 
b/modules/core/src/main/java/org/apache/accumulo/access/impl/AccessExpressionImpl.java
index 42fd3dc..2668152 100644
--- 
a/modules/core/src/main/java/org/apache/accumulo/access/impl/AccessExpressionImpl.java
+++ 
b/modules/core/src/main/java/org/apache/accumulo/access/impl/AccessExpressionImpl.java
@@ -78,8 +78,16 @@ public final class AccessExpressionImpl extends 
AccessExpression {
 
   public static CharSequence unquote(CharSequence term) {
     final int len = term.length();
-    if (len >= 2 && term.charAt(0) == '"' && term.charAt(len - 1) == '"') {
-      term = len == 2 ? "" : AccessEvaluatorImpl.unescape(term.subSequence(1, 
len - 1));
+    if (len >= 1) {
+      final boolean firstIsQuote = term.charAt(0) == '"';
+      final boolean lastIsQuote = term.charAt(len - 1) == '"';
+      if (firstIsQuote || lastIsQuote) {
+        if (len == 1 || (firstIsQuote != lastIsQuote)) {
+          throw new IllegalArgumentException("Unbalanced quotes : " + term);
+        }
+
+        term = len == 2 ? "" : 
AccessEvaluatorImpl.unescape(term.subSequence(1, len - 1));
+      }
     }
     if (term.isEmpty()) {
       throw new IllegalArgumentException("Empty strings are not legal 
authorizations.");
diff --git 
a/modules/core/src/main/java/org/apache/accumulo/access/impl/CharsWrapper.java 
b/modules/core/src/main/java/org/apache/accumulo/access/impl/CharsWrapper.java
index 1929bd9..17c47c6 100644
--- 
a/modules/core/src/main/java/org/apache/accumulo/access/impl/CharsWrapper.java
+++ 
b/modules/core/src/main/java/org/apache/accumulo/access/impl/CharsWrapper.java
@@ -21,7 +21,7 @@ package org.apache.accumulo.access.impl;
 import java.util.Arrays;
 import java.util.Objects;
 
-public final class CharsWrapper implements CharSequence {
+final class CharsWrapper implements CharSequence {
   private char[] wrapped;
   private int offset;
   private int len;
diff --git 
a/modules/core/src/test/java/org/apache/accumulo/access/tests/AccessEvaluatorTest.java
 
b/modules/core/src/test/java/org/apache/accumulo/access/tests/AccessEvaluatorTest.java
index 8df473a..a3b0e3b 100644
--- 
a/modules/core/src/test/java/org/apache/accumulo/access/tests/AccessEvaluatorTest.java
+++ 
b/modules/core/src/test/java/org/apache/accumulo/access/tests/AccessEvaluatorTest.java
@@ -26,6 +26,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.IOException;
 import java.lang.reflect.Type;
+import java.nio.CharBuffer;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -38,6 +39,7 @@ import org.apache.accumulo.access.AccessEvaluator;
 import org.apache.accumulo.access.AuthorizationValidator;
 import org.apache.accumulo.access.InvalidAccessExpressionException;
 import org.apache.accumulo.access.impl.AccessEvaluatorImpl;
+import org.apache.accumulo.access.impl.AccessExpressionImpl;
 import org.junit.jupiter.api.Test;
 
 import com.google.gson.Gson;
@@ -200,8 +202,31 @@ public class AccessEvaluatorTest {
     assertEquals("九", access.unquote(access.quote("九")));
     assertEquals("\"五十\"", access.quote("五十"));
     assertEquals("五十", access.unquote(access.quote("五十")));
-    assertThrows(IllegalArgumentException.class, () -> access.quote(""));
-    assertThrows(IllegalArgumentException.class, () -> access.unquote(""));
+
+    var e = assertThrows(IllegalArgumentException.class, () -> 
access.quote(""));
+    assertTrue(e.getMessage().contains("Empty string"));
+
+    testUnquoteError(access, "\"\"\"\"", "Unescaped quote");
+
+    for (var illegalInput : List.of("", "\"\"")) {
+      testUnquoteError(access, illegalInput, "Empty string");
+    }
+
+    for (var illegalInput : List.of("\"", "AB\"", "\"AB", "\"A", "B\"")) {
+      testUnquoteError(access, illegalInput, "Unbalanced quotes");
+    }
+  }
+
+  private static void testUnquoteError(Access access, String illegalInput,
+      String expectedErrorMsg) {
+    var e = assertThrows(IllegalArgumentException.class, () -> 
access.unquote(illegalInput),
+        illegalInput);
+    assertTrue(e.getMessage().contains(expectedErrorMsg));
+    // test with an input that is not a string
+    CharSequence charSeq = CharBuffer.wrap(illegalInput);
+    e = assertThrows(IllegalArgumentException.class, () -> 
AccessExpressionImpl.unquote(charSeq),
+        illegalInput);
+    assertTrue(e.getMessage().contains(expectedErrorMsg));
   }
 
   private static String unescape(String s) {

Reply via email to