package com.fasterxml.jackson.databind.jsontype;

import java.util.HashSet;
import java.util.Set;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.cfg.MapperConfig;

PolymorphicTypeValidator that will only allow polymorphic handling if the base type is NOT one of potential dangerous base types (see isUnsafeBaseType for specific list of such base types). No further validation is performed on subtype.

Note that when using potentially unsafe base type like Object a custom implementation (or subtype with override) is needed. Most commonly subclasses would override both isUnsafeBaseType and isSafeSubType: former to allow all (or just more) base types, and latter to add actual validation of subtype.

Since:2.11
/** * {@link PolymorphicTypeValidator} that will only allow polymorphic handling if * the base type is NOT one of potential dangerous base types (see {@link #isUnsafeBaseType} * for specific list of such base types). No further validation is performed on subtype. *<p> * Note that when using potentially unsafe base type like {@link java.lang.Object} a custom * implementation (or subtype with override) is needed. Most commonly subclasses would * override both {@link #isUnsafeBaseType} and {@link #isSafeSubType}: former to allow * all (or just more) base types, and latter to add actual validation of subtype. * * @since 2.11 */
public class DefaultBaseTypeLimitingValidator extends PolymorphicTypeValidator implements java.io.Serializable { private static final long serialVersionUID = 1L; @Override public Validity validateBaseType(MapperConfig<?> config, JavaType baseType) { // Immediately block potentially unsafe base types if (isUnsafeBaseType(config, baseType)) { return Validity.DENIED; } // otherwise indicate that type may be ok (so further calls are made -- // does not matter with base implementation but allows easier sub-classing) return Validity.INDETERMINATE; } @Override public Validity validateSubClassName(MapperConfig<?> config, JavaType baseType, String subClassName) { // return INDETERMINATE just for easier sub-classing return Validity.INDETERMINATE; } @Override public Validity validateSubType(MapperConfig<?> config, JavaType baseType, JavaType subType) { return isSafeSubType(config, baseType, subType) ? Validity.ALLOWED : Validity.DENIED; }
Helper method called to determine if the given base type is known to be problematic regarding possible "gadget types". Currently includes following types: which are JDK-included super types of at least one gadget type (not necessarily included in JDK)
Params:
  • config – Current mapper configuration
  • baseType – Base type to test
/** * Helper method called to determine if the given base type is known to be * problematic regarding possible "gadget types". * Currently includes following types: *<ul> * <li>{@link java.lang.Object}</li> * <li>{@link java.io.Closeable}</li> * <li>{@link java.io.Serializable}</li> * <li>{@link java.lang.AutoCloseable}</li> * <li>{@link java.lang.Cloneable}</li> * <li>{@link java.util.logging.Handler}</li> * <li>{@link javax.naming.Referenceable}</li> * <li>{@link javax.sql.DataSource}</li> *</ul> * which are JDK-included super types of at least one gadget type (not necessarily * included in JDK) * * @param config Current mapper configuration * @param baseType Base type to test */
protected boolean isUnsafeBaseType(MapperConfig<?> config, JavaType baseType) { return UnsafeBaseTypes.instance.isUnsafeBaseType(baseType.getRawClass()); }
Helper called to determine whether given actual subtype is considered safe to process: this will only be called if subtype was considered acceptable earlier.
Params:
  • config – Current mapper configuration
  • baseType – Base type of sub type (validated earlier)
  • subType – Sub type to test
/** * Helper called to determine whether given actual subtype is considered safe * to process: this will only be called if subtype was considered acceptable * earlier. * * @param config Current mapper configuration * @param baseType Base type of sub type (validated earlier) * @param subType Sub type to test */
protected boolean isSafeSubType(MapperConfig<?> config, JavaType baseType, JavaType subType) { return true; } private final static class UnsafeBaseTypes { public final static UnsafeBaseTypes instance = new UnsafeBaseTypes(); private final Set<String> UNSAFE = new HashSet<>(); { // first add names of types in `java.base` UNSAFE.add(Object.class.getName()); UNSAFE.add(java.io.Closeable.class.getName()); UNSAFE.add(java.io.Serializable.class.getName()); UNSAFE.add(AutoCloseable.class.getName()); UNSAFE.add(Cloneable.class.getName()); // and then couple others typically included in JDK, but that we // prefer not adding direct reference to UNSAFE.add("java.util.logging.Handler"); UNSAFE.add("javax.naming.Referenceable"); UNSAFE.add("javax.sql.DataSource"); } public boolean isUnsafeBaseType(Class<?> rawBaseType) { return UNSAFE.contains(rawBaseType.getName()); } } }