Code of Conduct
Search before asking
Describe the bug
DynFields.Builder.build(target) and buildChecked(target) throw NullPointerException instead of returning a field bound to null, when defaultAlwaysNull() is set and no candidate field is found.
DynFields.AlwaysNull is a singleton constructed with a null backing Field (super(null, "AlwaysNull")). It does not override bind(Object), so the call falls through to UnboundField.bind, which exempts the sentinel from the static-field check and then dereferences the null field on the next check:
public BoundField<T> bind(Object target) {
if (isStatic() && this != AlwaysNull.INSTANCE) {
throw new IllegalStateException("Cannot bind static field " + name);
}
if (!field.getDeclaringClass().isAssignableFrom(target.getClass())) { // NPE here
Reproducer:
DynFields.builder()
.impl(SomeClass.class, "noSuchField")
.defaultAlwaysNull()
.build(new Object());
// java.lang.NullPointerException: Cannot invoke "java.lang.reflect.Field.getDeclaringClass()"
// because "this.field" is null
// at org.apache.kyuubi.util.reflect.DynFields$UnboundField.bind(DynFields.java:89)
The sibling class in the same package already avoids this: DynMethods.UnboundMethod.NOOP overrides bind to return new BoundMethod(this, receiver), and UnboundMethod.bind carries no sentinel exemption at all.
Scope, so the severity is not overstated: nothing in Kyuubi calls defaultAlwaysNull() today, so no caller can reach this path and no user can hit it. This is hardening a vendored utility rather than fixing a reported failure. kyuubi-util's DynFields is copied from iceberg-common, which has the same defect; it is tracked upstream as apache/iceberg#17044, unfixed as of iceberg 1.11.0.
Affects Version(s)
master, and every release since 1.6.0-incubating, where DynFields was introduced (#3230)
Are you willing to submit PR?
Code of Conduct
Search before asking
Describe the bug
DynFields.Builder.build(target)andbuildChecked(target)throwNullPointerExceptioninstead of returning a field bound tonull, whendefaultAlwaysNull()is set and no candidate field is found.DynFields.AlwaysNullis a singleton constructed with anullbackingField(super(null, "AlwaysNull")). It does not overridebind(Object), so the call falls through toUnboundField.bind, which exempts the sentinel from the static-field check and then dereferences the null field on the next check:Reproducer:
The sibling class in the same package already avoids this:
DynMethods.UnboundMethod.NOOPoverridesbindto returnnew BoundMethod(this, receiver), andUnboundMethod.bindcarries no sentinel exemption at all.Scope, so the severity is not overstated: nothing in Kyuubi calls
defaultAlwaysNull()today, so no caller can reach this path and no user can hit it. This is hardening a vendored utility rather than fixing a reported failure.kyuubi-util'sDynFieldsis copied fromiceberg-common, which has the same defect; it is tracked upstream as apache/iceberg#17044, unfixed as of iceberg 1.11.0.Affects Version(s)
master, and every release since 1.6.0-incubating, where
DynFieldswas introduced (#3230)Are you willing to submit PR?