Skip to content

Commit 9751859

Browse files
jdconradbreskeby
authored andcommitted
fix workaround
1 parent 5597e8b commit 9751859

File tree

5 files changed

+38
-9
lines changed

5 files changed

+38
-9
lines changed

modules/lang-painless/src/main/java/org/elasticsearch/painless/DefBootstrap.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -201,14 +201,10 @@ protected MethodHandle computeValue(Class<?> receiverType) {
201201
try {
202202
return lookup(flavor, name, receiverType).asType(type);
203203
} catch (Throwable t) {
204-
// ClassValue.getFromHashMap wraps checked exceptions as Error, but
205-
// we do not want to crash here because we could not process the type
206-
// correctly as part of a script, so we instead unwrap the Error and
207-
// rethrow the original exception
208-
if (t instanceof Error && ((Error) t).getCause() instanceof Exception) {
209-
t = (Exception) ((Error) t).getCause();
210-
}
211-
Def.rethrow(t);
204+
// ClassValue.getFromHashMap wraps checked exceptions as Error, so we
205+
// use a sentinel class [PainlessWrapperError] here to work around
206+
// this issue and later unwrap the original exception
207+
Def.rethrow(new PainlessWrappedError(t));
212208
throw new AssertionError();
213209
}
214210
}

modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScript.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ public interface PainlessScript {
4646
* @return The generated ScriptException.
4747
*/
4848
default ScriptException convertToScriptException(Throwable t, Map<String, List<String>> extraMetadata) {
49+
if (t instanceof PainlessWrappedError) {
50+
t = t.getCause();
51+
}
4952
// create a script stack: this is just the script portion
5053
List<String> scriptStack = new ArrayList<>();
5154
ScriptException.Position pos = null;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.painless;
11+
12+
/**
13+
* Checked exceptions are wrapped in {@link ClassValue}#getFromHashMap in Error
14+
* which leads to unexpected behavior in Painless. This class is used as a
15+
* workaround for that exception wrapping.
16+
*/
17+
public class PainlessWrappedError extends Error {
18+
19+
/**
20+
* Constructor.
21+
* @param cause The {@link Throwable} cause.
22+
*/
23+
public PainlessWrappedError(final Throwable cause) {
24+
super(cause);
25+
}
26+
}

modules/lang-painless/src/main/java/org/elasticsearch/painless/phase/PainlessUserTreeToIRTreePhase.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.elasticsearch.painless.Location;
1313
import org.elasticsearch.painless.PainlessError;
1414
import org.elasticsearch.painless.PainlessExplainError;
15+
import org.elasticsearch.painless.PainlessWrappedError;
1516
import org.elasticsearch.painless.ScriptClassInfo;
1617
import org.elasticsearch.painless.ScriptClassInfo.MethodArgument;
1718
import org.elasticsearch.painless.ir.BinaryImplNode;
@@ -415,6 +416,7 @@ protected static void injectSandboxExceptions(FunctionNode irFunctionNode) {
415416

416417
for (Class<? extends Throwable> throwable : List.of(
417418
PainlessError.class,
419+
PainlessWrappedError.class,
418420
LinkageError.class,
419421
OutOfMemoryError.class,
420422
StackOverflowError.class,

modules/lang-painless/src/test/java/org/elasticsearch/painless/DefBootstrapTests.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,11 @@ public void testMegamorphic() throws Throwable {
139139
map.put("a", "b");
140140
assertEquals(2, (int) handle.invokeExact((Object) map));
141141

142-
final IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> {
142+
final PainlessWrappedError pwe = expectThrows(PainlessWrappedError.class, () -> {
143143
Integer.toString((int) handle.invokeExact(new Object()));
144144
});
145+
assertTrue(pwe.getCause() instanceof IllegalArgumentException);
146+
IllegalArgumentException iae = (IllegalArgumentException) pwe.getCause();
145147
assertEquals("dynamic method [java.lang.Object, size/0] not found", iae.getMessage());
146148
assertTrue("Does not fail inside ClassValue.computeValue()", Arrays.stream(iae.getStackTrace()).anyMatch(e -> {
147149
return e.getMethodName().equals("computeValue") && e.getClassName().startsWith("org.elasticsearch.painless.DefBootstrap$PIC$");

0 commit comments

Comments
 (0)