From e9bfef8becdd7d2d4bb8c22c71e70afa62c5c828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Thu, 8 May 2025 16:22:24 +0200 Subject: [PATCH] Remove the default serializable packages and deprecated the property to introduce org.apache.avro.SERIALIZABLE_CLASSES instead --- lang/java/avro/pom.xml | 3 + .../avro/specific/SpecificDatumReader.java | 62 ++++++++++++++----- .../org/apache/avro/reflect/TestReflect.java | 1 + lang/java/ipc/pom.xml | 3 + 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/lang/java/avro/pom.xml b/lang/java/avro/pom.xml index e776c665571..b74bef66fa6 100644 --- a/lang/java/avro/pom.xml +++ b/lang/java/avro/pom.xml @@ -90,6 +90,9 @@ maven-surefire-plugin none + + java.math.BigDecimal,java.math.BigInteger,java.net.URI,java.net.URL,java.io.File,java.lang.Integer,org.apache.avro.reflect.TestReflect$R10 + diff --git a/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificDatumReader.java b/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificDatumReader.java index 29c8ac66567..48d4420e750 100644 --- a/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificDatumReader.java +++ b/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificDatumReader.java @@ -23,10 +23,13 @@ import org.apache.avro.generic.GenericDatumReader; import org.apache.avro.io.ResolvingDecoder; import org.apache.avro.util.ClassUtils; + import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.HashSet; +import java.util.Set; /** * {@link org.apache.avro.io.DatumReader DatumReader} for generated Java @@ -34,14 +37,31 @@ */ public class SpecificDatumReader extends GenericDatumReader { + /** + * @deprecated prefer to use SERIALIZABLE_CLASSES instead. + */ + @Deprecated public static final String[] SERIALIZABLE_PACKAGES; + public static final String[] SERIALIZABLE_CLASSES; + static { - SERIALIZABLE_PACKAGES = System.getProperty("org.apache.avro.SERIALIZABLE_PACKAGES", - "java.lang,java.math,java.io,java.net,org.apache.avro.reflect").split(","); + // no serializable classes by default + String serializableClassesProp = System.getProperty("org.apache.avro.SERIALIZABLE_CLASSES"); + SERIALIZABLE_CLASSES = (serializableClassesProp == null) ? new String[0] : serializableClassesProp.split(","); + + // no serializable packages by default + String serializablePackagesProp = System.getProperty("org.apache.avro.SERIALIZABLE_PACKAGES"); + SERIALIZABLE_PACKAGES = (serializablePackagesProp == null) ? new String[0] : serializablePackagesProp.split(","); } + // The primitive "class names" based on Class.isPrimitive() + private static final Set PRIMITIVES = new HashSet<>(Arrays.asList(Boolean.TYPE.getName(), + Character.TYPE.getName(), Byte.TYPE.getName(), Short.TYPE.getName(), Integer.TYPE.getName(), Long.TYPE.getName(), + Float.TYPE.getName(), Double.TYPE.getName(), Void.TYPE.getName())); + private final List trustedPackages = new ArrayList<>(); + private final List trustedClasses = new ArrayList<>(); public SpecificDatumReader() { this(null, null, SpecificData.get()); @@ -69,12 +89,14 @@ public SpecificDatumReader(Schema writer, Schema reader) { public SpecificDatumReader(Schema writer, Schema reader, SpecificData data) { super(writer, reader, data); trustedPackages.addAll(Arrays.asList(SERIALIZABLE_PACKAGES)); + trustedClasses.addAll(Arrays.asList(SERIALIZABLE_CLASSES)); } /** Construct given a {@link SpecificData}. */ public SpecificDatumReader(SpecificData data) { super(data); trustedPackages.addAll(Arrays.asList(SERIALIZABLE_PACKAGES)); + trustedClasses.addAll(Arrays.asList(SERIALIZABLE_CLASSES)); } /** Return the contained {@link SpecificData}. */ @@ -116,8 +138,8 @@ private Class getPropAsClass(Schema schema, String prop) { if (name == null) return null; try { + checkSecurity(name); Class clazz = ClassUtils.forName(getData().getClassLoader(), name); - checkSecurity(clazz); return clazz; } catch (ClassNotFoundException e) { throw new AvroRuntimeException(e); @@ -128,31 +150,39 @@ private boolean trustAllPackages() { return (trustedPackages.size() == 1 && "*".equals(trustedPackages.get(0))); } - private void checkSecurity(Class clazz) throws ClassNotFoundException { - if (trustAllPackages() || clazz.isPrimitive()) { + private void checkSecurity(String className) throws ClassNotFoundException { + if (trustAllPackages() || PRIMITIVES.contains(className)) { return; } - boolean found = false; - Package thePackage = clazz.getPackage(); - if (thePackage != null) { - for (String trustedPackage : getTrustedPackages()) { - if (thePackage.getName().equals(trustedPackage) || thePackage.getName().startsWith(trustedPackage + ".")) { - found = true; - break; - } + for (String trustedClass : getTrustedClasses()) { + if (className.equals(trustedClass)) { + return; } } - if (!found) { - throw new SecurityException("Forbidden " + clazz - + "! This class is not trusted to be included in Avro schema using java-class. Please set org.apache.avro.SERIALIZABLE_PACKAGES system property with the packages you trust."); + + for (String trustedPackage : getTrustedPackages()) { + if (className.startsWith(trustedPackage)) { + return; + } } + + throw new SecurityException("Forbidden " + className + + "! This class is not trusted to be included in Avro schema using java-class. Please set org.apache.avro.SERIALIZABLE_CLASSES system property with the class you trust or org.apache.avro.SERIALIZABLE_PACKAGES system property with the packages you trust."); } + /** + * @deprecated Use getTrustedClasses() instead + */ + @Deprecated public final List getTrustedPackages() { return trustedPackages; } + public final List getTrustedClasses() { + return trustedClasses; + } + @Override protected Object readRecord(Object old, Schema expected, ResolvingDecoder in) throws IOException { SpecificData data = getSpecificData(); diff --git a/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java b/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java index 50121b5a0dd..08e186268cd 100644 --- a/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java +++ b/lang/java/avro/src/test/java/org/apache/avro/reflect/TestReflect.java @@ -615,6 +615,7 @@ void checkReadWrite(Object object) throws Exception { } void checkReadWrite(Object object, Schema s) throws Exception { + ReflectDatumWriter writer = new ReflectDatumWriter<>(s); ByteArrayOutputStream out = new ByteArrayOutputStream(); writer.write(object, factory.directBinaryEncoder(out, null)); diff --git a/lang/java/ipc/pom.xml b/lang/java/ipc/pom.xml index a12798488bd..5d18931d8e0 100644 --- a/lang/java/ipc/pom.xml +++ b/lang/java/ipc/pom.xml @@ -62,6 +62,9 @@ 1 false none + + java.math.BigDecimal,java.math.BigInteger +