SQL: supplement input checks on received request parameters (#52229) (#52277)

* Add more checks around parameter conversions

This commit adds two necessary verifications on received parameters:
- it checks the validity of the parameter's data type: if the declared
data type is resolved to an ES or Java type;
- it checks if the returned converter is non-null (i.e. a conversion is
possible) and generates an appropriate exception otherwise.

(cherry picked from commit eda30ac9c69383165324328c599ace39ac064342)
This commit is contained in:
Bogdan Pintea 2020-02-12 19:45:12 +01:00 committed by GitHub
parent fc964643bd
commit 5dfe27601e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 1 deletions

View File

@ -39,4 +39,20 @@ public class RestSqlIT extends RestSqlTestCase {
containsString("Cannot generate a query DSL for a special SQL command " +
"(e.g.: DESCRIBE, SHOW), sql statement: [SHOW FUNCTIONS]"));
}
public void testErrorMessageForInvalidParamDataType() throws IOException {
expectBadRequest(() -> runTranslateSql(
"{\"query\":\"SELECT null WHERE 0 = ? \", \"mode\": \"odbc\", \"params\":[{\"type\":\"invalid\", \"value\":\"irrelevant\"}]}"
),
containsString("Invalid parameter data type [invalid]")
);
}
public void testErrorMessageForInvalidParamSpec() throws IOException {
expectBadRequest(() -> runTranslateSql(
"{\"query\":\"SELECT null WHERE 0 = ? \", \"mode\": \"odbc\", \"params\":[{\"type\":\"SHAPE\", \"value\":false}]}"
),
containsString("Cannot cast value [false] of type [BOOLEAN] to parameter type [SHAPE]")
);
}
}

View File

@ -129,7 +129,8 @@ import java.util.StringJoiner;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.elasticsearch.xpack.ql.type.DataTypeConverter.converterFor;
import static org.elasticsearch.xpack.sql.type.SqlDataTypeConverter.canConvert;
import static org.elasticsearch.xpack.sql.type.SqlDataTypeConverter.converterFor;
import static org.elasticsearch.xpack.sql.util.DateUtils.asTimeOnly;
import static org.elasticsearch.xpack.sql.util.DateUtils.dateOfEscapedLiteral;
import static org.elasticsearch.xpack.sql.util.DateUtils.dateTimeOfEscapedLiteral;
@ -700,6 +701,9 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
SqlTypedParamValue param = param(ctx.PARAM());
DataType dataType = SqlDataTypes.fromTypeName(param.type);
Source source = source(ctx);
if (dataType == null) {
throw new ParsingException(source, "Invalid parameter data type [{}]", param.type);
}
if (param.value == null) {
// no conversion is required for null values
return new Literal(source, null, dataType);
@ -717,6 +721,10 @@ abstract class ExpressionBuilder extends IdentifierBuilder {
}
// otherwise we need to make sure that xcontent-serialized value is converted to the correct type
try {
if (canConvert(sourceType, dataType) == false) {
throw new ParsingException(source, "Cannot cast value [{}] of type [{}] to parameter type [{}]", param.value, sourceType,
dataType);
}
return new Literal(source, converterFor(sourceType, dataType).convert(param.value), dataType);
} catch (QlIllegalArgumentException ex) {
throw new ParsingException(ex, source, "Unexpected actual parameter type [{}] for type [{}]", sourceType, param.type);