You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2018/08/05 15:33:30 UTC

[05/19] jena git commit: ARQ:Query:ParameterizedSparqlString - "validateValuesSafeToInject" method now performed when applying the values. The variables which will be used in the substitution are identified then each variable is checked against the relev

ARQ:Query:ParameterizedSparqlString - "validateValuesSafeToInject" method now performed when applying the values. The variables which will be used in the substitution are identified then each variable is checked against the relevant item.

Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/a5f18c3d
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/a5f18c3d
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/a5f18c3d

Branch: refs/heads/master
Commit: a5f18c3d468a703954de464887b699e4ca95822a
Parents: 93c6780
Author: Greg Albiston <gr...@hotmail.com>
Authored: Mon Jul 30 15:48:42 2018 +0100
Committer: Greg Albiston <gr...@hotmail.com>
Committed: Mon Jul 30 15:48:42 2018 +0100

----------------------------------------------------------------------
 .../jena/query/ParameterizedSparqlString.java   | 57 ++++++++++++++++++--
 .../query/TestParameterizedSparqlString.java    | 39 ++++++++++++++
 2 files changed, 93 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/a5f18c3d/jena-arq/src/main/java/org/apache/jena/query/ParameterizedSparqlString.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/query/ParameterizedSparqlString.java b/jena-arq/src/main/java/org/apache/jena/query/ParameterizedSparqlString.java
index ab3bfcc..cba1e6d 100644
--- a/jena-arq/src/main/java/org/apache/jena/query/ParameterizedSparqlString.java
+++ b/jena-arq/src/main/java/org/apache/jena/query/ParameterizedSparqlString.java
@@ -1850,6 +1850,24 @@ public class ParameterizedSparqlString implements PrefixMapping {
         return command;
     }
 
+    private static final String VALUES_KEYWORD = "values";
+
+    protected static String[] extractTargetVars(String command, String varName) {
+        String[] targetVars;
+
+        int varIndex = command.indexOf(varName);
+        if (varIndex > -1) {
+            String subCmd = command.substring(0, varIndex).toLowerCase(); //Truncate the command at the varName. Lowercase to search both types of values.
+            int valuesIndex = subCmd.lastIndexOf(VALUES_KEYWORD);
+            int bracesIndex = subCmd.lastIndexOf("{");
+            String vars = command.substring(valuesIndex + VALUES_KEYWORD.length(), bracesIndex);
+            targetVars = vars.replaceAll("[(?)]", "").trim().split(" ");
+        } else {
+            targetVars = new String[]{};
+        }
+        return targetVars;
+    }
+
     /**
      * Performs replacement of VALUES in query string.
      *
@@ -1884,10 +1902,11 @@ public class ParameterizedSparqlString implements PrefixMapping {
                 return command;
             }
 
-            String target = createTarget(varName);
+            validateValuesSafeToInject(command);
 
-            StringBuilder replacement;
+            String target = createTarget();
 
+            StringBuilder replacement;
             if (isGrouped) {
                 replacement = groupedApply();
             } else {
@@ -1943,7 +1962,7 @@ public class ParameterizedSparqlString implements PrefixMapping {
          * @param varName
          * @return
          */
-        private String createTarget(String varName) {
+        private String createTarget() {
             String target;
 
             if (varName.startsWith("?") || varName.startsWith("$")) {
@@ -1954,6 +1973,38 @@ public class ParameterizedSparqlString implements PrefixMapping {
             return target;
         }
 
+        protected void validateValuesSafeToInject(String command) {
+
+            String[] targetVars = extractTargetVars(command, varName);
+
+            for (int i = 0; i < targetVars.length; i++) {
+                String targetVar = targetVars[i];
+                if (isGrouped) {
+                    //Iterate through each group according to the position of var and item.
+                    for (List<? extends RDFNode> group : groupedItems) {
+                        RDFNode item = group.get(i);
+                        validateSafeToInject(command, targetVar, item.asNode());
+                    }
+                } else {
+                    if (targetVars.length > 1) {
+                        if (items instanceof List) {
+                            //Multiple vars with items in an ordered list. Each var is checked against the item.
+                            List<? extends RDFNode> listItems = (List<? extends RDFNode>) items;
+                            RDFNode item = listItems.get(i);
+                            validateSafeToInject(command, targetVar, item.asNode());
+                        } else {
+                            //Multiple vars with items not in an ordered list. This is parsing error.
+                            throw new ARQException("Multiple VALUES variables (" + String.join(", ", targetVars) + ") being used without an ordered list of items: " + items.toString());
+                        }
+                    } else {
+                        //Single var with one or more items so all are checked.
+                        for (RDFNode item : items) {
+                            validateSafeToInject(command, targetVar, item.asNode());
+                        }
+                    }
+                }
+            }
+        }
     }
     
 }

http://git-wip-us.apache.org/repos/asf/jena/blob/a5f18c3d/jena-arq/src/test/java/org/apache/jena/query/TestParameterizedSparqlString.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/query/TestParameterizedSparqlString.java b/jena-arq/src/test/java/org/apache/jena/query/TestParameterizedSparqlString.java
index 69c50bf..90e5385 100644
--- a/jena-arq/src/test/java/org/apache/jena/query/TestParameterizedSparqlString.java
+++ b/jena-arq/src/test/java/org/apache/jena/query/TestParameterizedSparqlString.java
@@ -2070,4 +2070,43 @@ public class TestParameterizedSparqlString {
         Assert.fail("Attempt to do SPARQL injection should result in an exception");
     }
 
+    @Test
+    public void test_extract_target_vars() {
+        // Identifies the vars in the VALUES clause according to the substituting varName.
+        String cmd = "SELECT * WHERE { VALUES ?o {?objs} ?s ?p ?o }";
+        String varName = "objs";
+        String[] res = ParameterizedSparqlString.extractTargetVars(cmd, varName);
+        String[] exp = new String[]{"o"};
+
+        //System.out.println("Exp: " + exp);
+        //System.out.println("Res: " + res);
+        Assert.assertArrayEquals(exp, res);
+    }
+
+    @Test
+    public void test_extract_two_target_vars() {
+        // Identifies the vars in the VALUES clause according to the substituting varName.
+        String cmd = "SELECT * WHERE { VALUES(?p ?o){?vars} ?s ?p ?o }";
+        String varName = "vars";
+        String[] res = ParameterizedSparqlString.extractTargetVars(cmd, varName);
+        String[] exp = new String[]{"p", "o"};
+
+        //System.out.println("Exp: " + exp);
+        //System.out.println("Res: " + res);
+        Assert.assertArrayEquals(exp, res);
+    }
+
+    @Test
+    public void test_extract_multiple_target_vars() {
+        // Identifies the vars in the VALUES clause according to the substituting varName.
+        String cmd = "SELECT * WHERE { VALUES ?p {?props} VALUES ?o {?objs} ?s ?p ?o }";
+        String varName = "objs";
+        String[] res = ParameterizedSparqlString.extractTargetVars(cmd, varName);
+        String[] exp = new String[]{"o"};
+
+        //System.out.println("Exp: " + exp);
+        //System.out.println("Res: " + res);
+        Assert.assertArrayEquals(exp, res);
+    }
+
 }