Skip to content

Commit aa44ed3

Browse files
committed
java-[key-]class allowed packages must be packages (apache#3453)
1 parent 231133d commit aa44ed3

1 file changed

Lines changed: 27 additions & 7 deletions

File tree

lang/java/avro/src/main/java/org/apache/avro/specific/SpecificDatumReader.java

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.List;
3131
import java.util.HashSet;
3232
import java.util.Set;
33+
import java.util.stream.Stream;
3334

3435
/**
3536
* {@link org.apache.avro.io.DatumReader DatumReader} for generated Java
@@ -38,7 +39,7 @@
3839
public class SpecificDatumReader<T> extends GenericDatumReader<T> {
3940

4041
/**
41-
* @deprecated prefer to use SERIALIZABLE_CLASSES instead.
42+
* @deprecated prefer to use {@link #SERIALIZABLE_CLASSES} instead.
4243
*/
4344
@Deprecated
4445
public static final String[] SERIALIZABLE_PACKAGES;
@@ -47,12 +48,29 @@ public class SpecificDatumReader<T> extends GenericDatumReader<T> {
4748

4849
static {
4950
// no serializable classes by default
50-
String serializableClassesProp = System.getProperty("org.apache.avro.SERIALIZABLE_CLASSES");
51-
SERIALIZABLE_CLASSES = (serializableClassesProp == null) ? new String[0] : serializableClassesProp.split(",");
51+
SERIALIZABLE_CLASSES = streamPropertyEntries(System.getProperty("org.apache.avro.SERIALIZABLE_CLASSES"))
52+
.toArray(String[]::new);
5253

5354
// no serializable packages by default
54-
String serializablePackagesProp = System.getProperty("org.apache.avro.SERIALIZABLE_PACKAGES");
55-
SERIALIZABLE_PACKAGES = (serializablePackagesProp == null) ? new String[0] : serializablePackagesProp.split(",");
55+
SERIALIZABLE_PACKAGES = streamPropertyEntries(System.getProperty("org.apache.avro.SERIALIZABLE_PACKAGES"))
56+
// Add a '.' suffix to ensure we'll be matching package names instead of
57+
// arbitrary prefixes, except for the wildcard "*", which allows all
58+
// packages (this is only safe in fully controlled environments!).
59+
.map(entry -> "*".equals(entry) ? entry : entry + ".").toArray(String[]::new);
60+
}
61+
62+
/**
63+
* Parse a comma separated list into non-empty entries. Leading and trailing
64+
* whitespace is stripped.
65+
*
66+
* @param commaSeparatedEntries the comma separated list of entries
67+
* @return a stream of the entries
68+
*/
69+
private static Stream<String> streamPropertyEntries(String commaSeparatedEntries) {
70+
if (commaSeparatedEntries == null) {
71+
return Stream.empty();
72+
}
73+
return Stream.of(commaSeparatedEntries.split(",")).map(String::strip).filter(s -> !s.isEmpty());
5674
}
5775

5876
// The primitive "class names" based on Class.isPrimitive()
@@ -167,8 +185,10 @@ private void checkSecurity(String className) throws ClassNotFoundException {
167185
}
168186
}
169187

170-
throw new SecurityException("Forbidden " + className
171-
+ "! 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.");
188+
throw new SecurityException("Forbidden " + className + "! This class is not trusted to be included in Avro "
189+
+ "schemas using java-class. Please set the system property org.apache.avro.SERIALIZABLE_CLASSES to the comma "
190+
+ "separated list of classes you trust. You can also set the system property "
191+
+ "org.apache.avro.SERIALIZABLE_PACKAGES to the comma separated list of the packages you trust.");
172192
}
173193

174194
/**

0 commit comments

Comments
 (0)