Repository: xerial/sqlite-jdbc
Pull request #1161 (2024-08-19 19:19:39)

fix: possible StringIndexOutOfBoundsException in ExtendedCommand
This PR proposes a fix for #1141 .

gotson: do you think you could add a test covering this ?
arthurscchan: @gotson Really sorry for missing your comment. I have added in the unit test for the removeQuotation method.
gotson: > @gotson Really sorry for missing your comment. I have added in the unit test for the removeQuotation method.

the test code doesn't compile
gotson: i've refactored your test code:

```java
@ParameterizedTest
  @MethodSource
  public void removeQuotation(String input, String expected) throws SQLException {
    assertThat(ExtendedCommand.removeQuotation(input)).isEqualTo(expected);
  }

  private static Stream<Arguments> removeQuotation() {
    return Stream.of(
        Arguments.of(null, null), // Null String
        Arguments.of("'", "'"), // String with one single quotation only
        Arguments.of("\"", "\""), // String with one double quotation only
        Arguments.of("'Test\"", "'Test\""), // String with two mismatch quotations
        Arguments.of("'Test'", "Test"), // String with two matching single quotations
        Arguments.of("\"Test\"", "Test"), // String with two matching double quotations
        Arguments.of("'Te's\"t'", "Te's\"t") // String with more than two quotations
    );
  }
```

Patch:
diff --git a/src/main/java/org/sqlite/ExtendedCommand.java b/src/main/java/org/sqlite/ExtendedCommand.java
index 1a1e205d..b863f7c8 100755
--- a/src/main/java/org/sqlite/ExtendedCommand.java
+++ b/src/main/java/org/sqlite/ExtendedCommand.java
@@ -54,7 +54,7 @@ public class ExtendedCommand {
         if (s == null) return s;
 
         if ((s.startsWith("\"") && s.endsWith("\"")) || (s.startsWith("'") && s.endsWith("'")))
-            return s.substring(1, s.length() - 1);
+            return (s.length() >= 2) ? s.substring(1, s.length() - 1) : s;
         else return s;
     }
 


Test patch:
diff --git a/src/test/java/org/sqlite/ExtendedCommandTest.java b/src/test/java/org/sqlite/ExtendedCommandTest.java
index ae18f789..429ce179 100755
--- a/src/test/java/org/sqlite/ExtendedCommandTest.java
+++ b/src/test/java/org/sqlite/ExtendedCommandTest.java
@@ -12,7 +12,11 @@ package org.sqlite;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.sql.SQLException;
+import java.util.stream.Stream;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.sqlite.ExtendedCommand.BackupCommand;
 import org.sqlite.ExtendedCommand.RestoreCommand;
 import org.sqlite.ExtendedCommand.SQLExtension;
@@ -69,4 +73,22 @@ public class ExtendedCommandTest {
         assertThat(b.targetDB).isEqualTo("main");
         assertThat(b.srcFile).isEqualTo("target/sample.db");
     }
+
+    @ParameterizedTest
+    @MethodSource
+    public void removeQuotation(String input, String expected) throws SQLException {
+        assertThat(ExtendedCommand.removeQuotation(input)).isEqualTo(expected);
+    }
+
+    private static Stream<Arguments> removeQuotation() {
+        return Stream.of(
+                Arguments.of(null, null), // Null String
+                Arguments.of("'", "'"), // String with one single quotation only
+                Arguments.of("\"", "\""), // String with one double quotation only
+                Arguments.of("'Test\"", "'Test\""), // String with two mismatch quotations
+                Arguments.of("'Test'", "Test"), // String with two matching single quotations
+                Arguments.of("\"Test\"", "Test"), // String with two matching double quotations
+                Arguments.of("'Te's\"t'", "Te's\"t") // String with more than two quotations
+                );
+    }
 }