You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mu...@apache.org on 2019/06/24 17:39:30 UTC

[lucene-solr] branch branch_8x updated: SOLR-13187: Fix NPE when invalid qParser is specified

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

munendrasn pushed a commit to branch branch_8x
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git


The following commit(s) were added to refs/heads/branch_8x by this push:
     new 3ef5c0e  SOLR-13187: Fix NPE when invalid qParser is specified
3ef5c0e is described below

commit 3ef5c0ee74ec3fc939a530c7733e6632a98661a2
Author: Munendra S N <mu...@apache.org>
AuthorDate: Mon Jun 24 22:58:58 2019 +0530

    SOLR-13187: Fix NPE when invalid qParser is specified
    
    * When non-existent qParser is specified return 400 error code
    * SOLR-13197: Fix NPE when createQParser is called in StatsField
---
 solr/CHANGES.txt                                   |  3 ++
 .../apache/solr/handler/component/StatsField.java  | 12 ++++--
 .../src/java/org/apache/solr/search/QParser.java   |  9 ++++-
 .../org/apache/solr/search/QueryParsingTest.java   | 46 +++++++++++++++++++++-
 4 files changed, 63 insertions(+), 7 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 6496beb..dfae69e 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -139,6 +139,9 @@ Bug Fixes
 * SOLR-12127: Updates containing 'set' operation with value null or empty list should be considered as Atomic Update
   (Oliver Kuldmäe, Munendra S N, Ishan Chattopadhyaya)
 
+* SOLR-13187: Fix NPE when invalid query parser is specified and return 400 error code.
+  (Cesar Rodriguez, Marek, Charles Sanders, Munendra S N, Mikhail Khludnev)
+
 Other Changes
 ----------------------
 
diff --git a/solr/core/src/java/org/apache/solr/handler/component/StatsField.java b/solr/core/src/java/org/apache/solr/handler/component/StatsField.java
index 3ca35f3..0483bb0 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/StatsField.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/StatsField.java
@@ -149,7 +149,7 @@ public class StatsField {
     }
     
     /**
-     * Given a String, returns the corrisponding Stat enum value if any, otherwise returns null.
+     * Given a String, returns the corresponding Stat enum value if any, otherwise returns null.
      */
     public static Stat forName(String paramKey) {
       try {
@@ -245,16 +245,20 @@ public class StatsField {
       } else {
         // we have a non trivial request to compute stats over a query (or function)
 
-        // NOTE we could use QParser.getParser(...) here, but that would redundently
+        // NOTE we could use QParser.getParser(...) here, but that would redundantly
         // reparse everything.  ( TODO: refactor a common method in QParser ?)
         QParserPlugin qplug = rb.req.getCore().getQueryPlugin(parserName);
-        QParser qp =  qplug.createParser(localParams.get(QueryParsing.V), 
+        if (qplug == null) {
+          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "invalid query parser '" + parserName +
+              (originalParam == null? "'": "' for query '" + originalParam + "'"));
+        }
+        QParser qp = qplug.createParser(localParams.get(QueryParsing.V),
                                          localParams, params, rb.req);
 
         // figure out what type of query we are dealing, get the most direct ValueSource
         vs = extractValueSource(qp.parse());
 
-        // if this ValueSource directly corrisponds to a SchemaField, act as if
+        // if this ValueSource directly corresponds to a SchemaField, act as if
         // we were asked to compute stats on it directly
         // ie:  "stats.field={!func key=foo}field(foo)" == "stats.field=foo"
         sf = extractSchemaField(vs, searcher.getSchema());
diff --git a/solr/core/src/java/org/apache/solr/search/QParser.java b/solr/core/src/java/org/apache/solr/search/QParser.java
index 8a89a70..5ebb05e 100644
--- a/solr/core/src/java/org/apache/solr/search/QParser.java
+++ b/solr/core/src/java/org/apache/solr/search/QParser.java
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.lucene.search.Query;
+import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
@@ -360,10 +361,16 @@ public abstract class QParser {
       }
 
       parserName = localParams.get(QueryParsing.TYPE,parserName);
-      qstr = localParams.get("v");
+      qstr = localParams.get(QueryParsing.V);
     }
 
     QParserPlugin qplug = req.getCore().getQueryPlugin(parserName);
+    if (qplug == null) {
+      // there should a way to include parameter for which parsing failed
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+          "invalid query parser '" + parserName + (stringIncludingLocalParams == null?
+              "'": "' for query '" + stringIncludingLocalParams + "'"));
+    }
     QParser parser =  qplug.createParser(qstr, localParams, req.getParams(), req);
 
     parser.stringIncludingLocalParams = stringIncludingLocalParams;
diff --git a/solr/core/src/test/org/apache/solr/search/QueryParsingTest.java b/solr/core/src/test/org/apache/solr/search/QueryParsingTest.java
index 20ea941..2e695be 100644
--- a/solr/core/src/test/org/apache/solr/search/QueryParsingTest.java
+++ b/solr/core/src/test/org/apache/solr/search/QueryParsingTest.java
@@ -17,6 +17,7 @@
 package org.apache.solr.search;
 import org.apache.lucene.search.Query;
 import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.request.SolrQueryRequest;
 import org.junit.BeforeClass;
@@ -54,10 +55,10 @@ public class QueryParsingTest extends SolrTestCaseJ4 {
         try {
           parser = QParser.getParser(qstr, defType, req);
         } catch (Exception e) {
-          throw new RuntimeException("getParser excep using defType=" + 
+          throw new RuntimeException("getParser excep using defType=" +
                                      defType + " with qstr="+qstr, e);
         }
-        
+
         Query q = parser.parse();
         assertNull("expected no query",q);
       }
@@ -94,4 +95,45 @@ public class QueryParsingTest extends SolrTestCaseJ4 {
                   ("strdist(\"a value\",literal('a value'),edit)",
                    NAME, req).getQuery());
   }
+
+  public void testGetQParser() throws Exception {
+    // invalid defType
+    SolrException exception = expectThrows(SolrException.class, () -> h.query(req("q", "ad", "defType", "bleh")));
+    assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, exception.code());
+    assertEquals("invalid query parser 'bleh' for query 'ad'", exception.getMessage());
+
+    // invalid qparser override in the local params
+    exception = expectThrows(SolrException.class, () -> h.query(req("q", "{!bleh}")));
+    assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, exception.code());
+    assertEquals("invalid query parser 'bleh' for query '{!bleh}'", exception.getMessage());
+
+    // invalid qParser with fq params
+    exception = expectThrows(SolrException.class, () -> h.query(req("q", "*:*", "fq", "{!some}")));
+    assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, exception.code());
+    assertEquals("invalid query parser 'some' for query '{!some}'", exception.getMessage());
+
+    // invalid qparser with function queries
+    exception = expectThrows(SolrException.class, () -> h.query(req("q", "*:*", "defType", "edismax", "boost", "{!hmm}")));
+    assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, exception.code());
+    assertEquals("invalid query parser 'hmm' for query '{!hmm}'", exception.getMessage());
+
+    exception = expectThrows(SolrException.class, () -> h.query(req("q", "*:*", "defType", "edismax", "boost", "query({!bleh v=ak})")));
+    assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, exception.code());
+    assertEquals("invalid query parser 'bleh' for query '{!bleh v=ak}'", exception.getMessage());
+
+    exception = expectThrows(SolrException.class, () ->
+        h.query(req("q", "*:*", "defType", "edismax", "boost", "query($qq)", "qq", "{!bleh v=a}")));
+    assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, exception.code());
+    assertEquals("invalid query parser 'bleh' for query '{!bleh v=a}'", exception.getMessage());
+
+    // ranking doesn't use defType
+    exception = expectThrows(SolrException.class, () -> h.query(req("q", "*:*", "rq", "{!bleh}")));
+    assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, exception.code());
+    assertEquals("invalid query parser 'bleh' for query '{!bleh}'", exception.getMessage());
+
+    // with stats.field
+    exception = expectThrows(SolrException.class, () -> h.query(req("q", "*:*", "stats", "true", "stats.field", "{!bleh}")));
+    assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, exception.code());
+    assertEquals("invalid query parser 'bleh' for query '{!bleh}'", exception.getMessage());
+  }
 }