Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions runtime/src/main/java/dev/cel/runtime/DefaultInterpreter.java
Original file line number Diff line number Diff line change
Expand Up @@ -585,9 +585,8 @@ private IntermediateResult mergeBooleanUnknowns(IntermediateResult lhs, Intermed
return rhs;
}

// Otherwise fallback to normal impl
return IntermediateResult.create(
InterpreterUtil.shortcircuitUnknownOrThrowable(lhsVal, rhsVal));
// Otherwise, enforce strictness on both args
return IntermediateResult.create(InterpreterUtil.enforceStrictness(lhsVal, rhsVal));
}

private enum ShortCircuitableOperators {
Expand Down
39 changes: 3 additions & 36 deletions runtime/src/main/java/dev/cel/runtime/InterpreterUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

import com.google.errorprone.annotations.CheckReturnValue;
import dev.cel.common.annotations.Internal;
import java.util.LinkedHashSet;
import java.util.Set;
import org.jspecify.annotations.Nullable;

/**
Expand Down Expand Up @@ -74,42 +72,11 @@ static AccumulatedUnknowns adaptToAccumulatedUnknowns(CelUnknownSet unknowns) {
return AccumulatedUnknowns.create(unknowns.unknownExprIds(), unknowns.attributes());
}

static AccumulatedUnknowns combineUnknownExprValue(Object... objs) {
Set<Long> ids = new LinkedHashSet<>();
for (Object object : objs) {
if (isAccumulatedUnknowns(object)) {
ids.addAll(((AccumulatedUnknowns) object).exprIds());
}
}

return AccumulatedUnknowns.create(ids);
}

/**
* Short circuit unknown or error arguments to logical operators.
*
* <p>Given two arguments, one of which must be throwable (error) or unknown, returns the result
* from the && or || operators for these arguments, assuming that the result cannot be determined
* from any boolean arguments alone. This allows us to consolidate the error/unknown handling for
* both of these operators.
* Enforces strictness on both lhs/rhs arguments from logical operators (i.e: intentionally throws
* an appropriate exception when {@link Throwable} is encountered as part of evaluated result.
*/
public static Object shortcircuitUnknownOrThrowable(Object left, Object right)
throws CelEvaluationException {
// unknown <op> unknown ==> unknown combined
if (InterpreterUtil.isAccumulatedUnknowns(left)
&& InterpreterUtil.isAccumulatedUnknowns(right)) {
return InterpreterUtil.combineUnknownExprValue(left, right);
}
// unknown <op> <error> ==> unknown
// unknown <op> t|f ==> unknown
if (InterpreterUtil.isAccumulatedUnknowns(left)) {
return left;
}
// <error> <op> unknown ==> unknown
// t|f <op> unknown ==> unknown
if (InterpreterUtil.isAccumulatedUnknowns(right)) {
return right;
}
public static Object enforceStrictness(Object left, Object right) throws CelEvaluationException {
// Throw left or right side exception for now, should combine them into ErrorSet.
// <error> <op> <error> ==> <error>
if (left instanceof Throwable) {
Expand Down