Fix missing format strings in calls to DruidException.build (#15056)

* Fix the NPE bug in nonStrictFormat

* using non null format string

* using Assert.assertThrows
This commit is contained in:
Pranav 2023-09-29 17:00:36 -07:00 committed by GitHub
parent 86087cee0a
commit 07c28f17ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 51 additions and 8 deletions

View File

@ -217,7 +217,7 @@ public class SqlStatementResource
return buildNonOkResponse( return buildNonOkResponse(
DruidException.forPersona(DruidException.Persona.DEVELOPER) DruidException.forPersona(DruidException.Persona.DEVELOPER)
.ofCategory(DruidException.Category.UNCATEGORIZED) .ofCategory(DruidException.Category.UNCATEGORIZED)
.build(e.getMessage()) .build("%s", e.getMessage())
); );
} }
finally { finally {

View File

@ -170,7 +170,7 @@ public class SqlTaskResource
sqlQueryId, sqlQueryId,
DruidException.forPersona(DruidException.Persona.DEVELOPER) DruidException.forPersona(DruidException.Persona.DEVELOPER)
.ofCategory(DruidException.Category.UNCATEGORIZED) .ofCategory(DruidException.Category.UNCATEGORIZED)
.build(e.getMessage()) .build("%s", e.getMessage())
); );
} }
finally { finally {

View File

@ -234,7 +234,7 @@ public class SqlStatementResourceHelper
null, null,
DruidException.forPersona(DruidException.Persona.DEVELOPER) DruidException.forPersona(DruidException.Persona.DEVELOPER)
.ofCategory(DruidException.Category.UNCATEGORIZED) .ofCategory(DruidException.Category.UNCATEGORIZED)
.build(taskResponse.getStatus().getErrorMsg()).toErrorResponse() .build("%s", taskResponse.getStatus().getErrorMsg()).toErrorResponse()
)); ));
} }

View File

@ -204,7 +204,7 @@ public class ErrorResponse
{ {
return bob.forPersona(cause.getTargetPersona()) return bob.forPersona(cause.getTargetPersona())
.ofCategory(cause.getCategory()) .ofCategory(cause.getCategory())
.build(cause, cause.getMessage()) .build(cause, "%s", cause.getMessage())
.withContext(cause.getContext()); .withContext(cause.getContext());
} }
} }

View File

@ -47,7 +47,7 @@ public class QueryExceptionCompat extends DruidException.Failure
{ {
return bob.forPersona(DruidException.Persona.OPERATOR) return bob.forPersona(DruidException.Persona.OPERATOR)
.ofCategory(convertFailType(exception.getFailType())) .ofCategory(convertFailType(exception.getFailType()))
.build(exception, exception.getMessage()) .build(exception, "%s", exception.getMessage())
.withContext("host", exception.getHost()) .withContext("host", exception.getHost())
.withContext("errorClass", exception.getErrorClass()) .withContext("errorClass", exception.getErrorClass())
.withContext("legacyErrorCode", exception.getErrorCode()); .withContext("legacyErrorCode", exception.getErrorCode());

View File

@ -107,4 +107,32 @@ public class ErrorResponseTest
.expectMessageIs("Query did not complete within configured timeout period. You can increase query timeout or tune the performance of query.") .expectMessageIs("Query did not complete within configured timeout period. You can increase query timeout or tune the performance of query.")
); );
} }
@Test
public void testQueryExceptionCompatWithNullMessage()
{
ErrorResponse response = new ErrorResponse(DruidException.fromFailure(new QueryExceptionCompat(new QueryTimeoutException(
null,
"hostname"
))));
final Map<String, Object> asMap = response.getAsMap();
MatcherAssert.assertThat(
asMap,
DruidMatchers.mapMatcher(
"error",
"Query timeout",
"errorCode",
"legacyQueryException",
"persona",
"OPERATOR",
"category",
"TIMEOUT",
"errorMessage",
"null"
)
);
}
} }

View File

@ -386,4 +386,19 @@ public class StringUtilsTest
} }
} }
} }
@Test()
public void testNonStrictFormatWithNullMessage()
{
Assert.assertThrows(NullPointerException.class, () -> StringUtils.nonStrictFormat(null, 1, 2));
}
@Test
public void testNonStrictFormatWithStringContainingPercent()
{
Assert.assertEquals(
"some string containing % %s %d %f",
StringUtils.nonStrictFormat("%s", "some string containing % %s %d %f")
);
}
} }

View File

@ -345,7 +345,7 @@ public class DruidPlanner implements Closeable
return DruidException.forPersona(DruidException.Persona.USER) return DruidException.forPersona(DruidException.Persona.USER)
.ofCategory(DruidException.Category.INVALID_INPUT) .ofCategory(DruidException.Category.INVALID_INPUT)
.withErrorCode("invalidInput") .withErrorCode("invalidInput")
.build(inner, inner.getMessage()).withContext("sourceType", "sql"); .build(inner, "%s", inner.getMessage()).withContext("sourceType", "sql");
} else { } else {
final String theUnexpectedToken = getUnexpectedTokenString(parseException); final String theUnexpectedToken = getUnexpectedTokenString(parseException);
@ -390,14 +390,14 @@ public class DruidPlanner implements Closeable
catch (RelOptPlanner.CannotPlanException inner) { catch (RelOptPlanner.CannotPlanException inner) {
return DruidException.forPersona(DruidException.Persona.USER) return DruidException.forPersona(DruidException.Persona.USER)
.ofCategory(DruidException.Category.INVALID_INPUT) .ofCategory(DruidException.Category.INVALID_INPUT)
.build(inner, inner.getMessage()); .build(inner, "%s", inner.getMessage());
} }
catch (Exception inner) { catch (Exception inner) {
// Anything else. Should not get here. Anything else should already have // Anything else. Should not get here. Anything else should already have
// been translated to a DruidException unless it is an unexpected exception. // been translated to a DruidException unless it is an unexpected exception.
return DruidException.forPersona(DruidException.Persona.ADMIN) return DruidException.forPersona(DruidException.Persona.ADMIN)
.ofCategory(DruidException.Category.UNCATEGORIZED) .ofCategory(DruidException.Category.UNCATEGORIZED)
.build(inner, inner.getMessage()); .build(inner, "%s", inner.getMessage());
} }
} }