Skip to content

Commit 8f89868

Browse files
authored
AVRO-3985: Add trusted packages support in SpecificData (#2980)
1 parent 9c4e4da commit 8f89868

File tree

2 files changed

+46
-11
lines changed

2 files changed

+46
-11
lines changed

lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java

-10
Original file line numberDiff line numberDiff line change
@@ -427,16 +427,6 @@ private FieldAccessor getFieldAccessor(Class<?> c, String fieldName) {
427427
return null;
428428
}
429429

430-
/** @deprecated Replaced by {@link SpecificData#CLASS_PROP} */
431-
@Deprecated
432-
static final String CLASS_PROP = "java-class";
433-
/** @deprecated Replaced by {@link SpecificData#KEY_CLASS_PROP} */
434-
@Deprecated
435-
static final String KEY_CLASS_PROP = "java-key-class";
436-
/** @deprecated Replaced by {@link SpecificData#ELEMENT_PROP} */
437-
@Deprecated
438-
static final String ELEMENT_PROP = "java-element-class";
439-
440430
private static final Map<String, Class> CLASS_CACHE = new ConcurrentHashMap<>();
441431

442432
static Class getClassProp(Schema schema, String prop) {

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

+46-1
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,25 @@
2424
import org.apache.avro.io.ResolvingDecoder;
2525
import org.apache.avro.util.ClassUtils;
2626
import java.io.IOException;
27+
import java.util.ArrayList;
28+
import java.util.Arrays;
29+
import java.util.List;
2730

2831
/**
2932
* {@link org.apache.avro.io.DatumReader DatumReader} for generated Java
3033
* classes.
3134
*/
3235
public class SpecificDatumReader<T> extends GenericDatumReader<T> {
36+
37+
public static final String[] SERIALIZABLE_PACKAGES;
38+
39+
static {
40+
SERIALIZABLE_PACKAGES = System.getProperty("org.apache.avro.SERIALIZABLE_PACKAGES",
41+
"java.lang,java.math,java.io,java.net,org.apache.avro.reflect").split(",");
42+
}
43+
44+
private final List<String> trustedPackages = new ArrayList<>();
45+
3346
public SpecificDatumReader() {
3447
this(null, null, SpecificData.get());
3548
}
@@ -55,6 +68,7 @@ public SpecificDatumReader(Schema writer, Schema reader) {
5568
*/
5669
public SpecificDatumReader(Schema writer, Schema reader, SpecificData data) {
5770
super(writer, reader, data);
71+
trustedPackages.addAll(Arrays.asList(SERIALIZABLE_PACKAGES));
5872
}
5973

6074
/** Construct given a {@link SpecificData}. */
@@ -101,12 +115,43 @@ private Class getPropAsClass(Schema schema, String prop) {
101115
if (name == null)
102116
return null;
103117
try {
104-
return ClassUtils.forName(getData().getClassLoader(), name);
118+
Class clazz = ClassUtils.forName(getData().getClassLoader(), name);
119+
checkSecurity(clazz);
120+
return clazz;
105121
} catch (ClassNotFoundException e) {
106122
throw new AvroRuntimeException(e);
107123
}
108124
}
109125

126+
private boolean trustAllPackages() {
127+
return (trustedPackages.size() == 1 && "*".equals(trustedPackages.get(0)));
128+
}
129+
130+
private void checkSecurity(Class clazz) throws ClassNotFoundException {
131+
if (trustAllPackages() || clazz.isPrimitive()) {
132+
return;
133+
}
134+
135+
boolean found = false;
136+
Package thePackage = clazz.getPackage();
137+
if (thePackage != null) {
138+
for (String trustedPackage : getTrustedPackages()) {
139+
if (thePackage.getName().equals(trustedPackage) || thePackage.getName().startsWith(trustedPackage + ".")) {
140+
found = true;
141+
break;
142+
}
143+
}
144+
if (!found) {
145+
throw new SecurityException("Forbidden " + clazz
146+
+ "! 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.");
147+
}
148+
}
149+
}
150+
151+
public final List<String> getTrustedPackages() {
152+
return trustedPackages;
153+
}
154+
110155
@Override
111156
protected Object readRecord(Object old, Schema expected, ResolvingDecoder in) throws IOException {
112157
SpecificData data = getSpecificData();

0 commit comments

Comments
 (0)