Skip to content

Commit e779faa

Browse files
ahornaceVladimir Kotal
authored andcommitted
Add serial filtering when deserializing classes
1 parent d08444b commit e779faa

File tree

9 files changed

+220
-39
lines changed

9 files changed

+220
-39
lines changed

opengrok-indexer/src/main/java/org/opengrok/indexer/analysis/Definitions.java

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,17 @@
1818
*/
1919

2020
/*
21-
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
21+
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
2222
* Portions Copyright (c) 2018, Chris Fraire <[email protected]>.
2323
*/
2424
package org.opengrok.indexer.analysis;
2525

26+
import org.opengrok.indexer.util.WhitelistObjectInputFilter;
27+
2628
import java.io.ByteArrayInputStream;
2729
import java.io.ByteArrayOutputStream;
2830
import java.io.IOException;
31+
import java.io.ObjectInputFilter;
2932
import java.io.ObjectInputStream;
3033
import java.io.ObjectOutputStream;
3134
import java.io.Serializable;
@@ -40,6 +43,19 @@ public class Definitions implements Serializable {
4043

4144
private static final long serialVersionUID = 1191703801007779489L;
4245

46+
private static final ObjectInputFilter serialFilter = new WhitelistObjectInputFilter(
47+
Definitions.class,
48+
HashMap.class,
49+
Map.Entry[].class,
50+
Integer.class,
51+
Number.class,
52+
LineTagMap.class,
53+
HashSet.class,
54+
Tag.class,
55+
ArrayList.class,
56+
Object[].class
57+
);
58+
4359
// Per line sym -> tags mapping
4460
public static class LineTagMap implements Serializable {
4561

@@ -284,9 +300,10 @@ public void addTag(int line, String symbol, String type, String text,
284300
* @throws IOException if an error happens when writing to the array
285301
*/
286302
public byte[] serialize() throws IOException {
287-
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
288-
new ObjectOutputStream(bytes).writeObject(this);
289-
return bytes.toByteArray();
303+
try (ByteArrayOutputStream bytes = new ByteArrayOutputStream(); var oos = new ObjectOutputStream(bytes)) {
304+
oos.writeObject(this);
305+
return bytes.toByteArray();
306+
}
290307
}
291308

292309
/**
@@ -300,10 +317,10 @@ public byte[] serialize() throws IOException {
300317
* @throws ClassCastException if the array contains an object of another
301318
* type than {@code Definitions}
302319
*/
303-
public static Definitions deserialize(byte[] bytes)
304-
throws IOException, ClassNotFoundException {
305-
ObjectInputStream in
306-
= new ObjectInputStream(new ByteArrayInputStream(bytes));
307-
return (Definitions) in.readObject();
320+
public static Definitions deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
321+
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
322+
in.setObjectInputFilter(serialFilter);
323+
return (Definitions) in.readObject();
324+
}
308325
}
309326
}

opengrok-indexer/src/main/java/org/opengrok/indexer/analysis/Scopes.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@
2222
*/
2323
package org.opengrok.indexer.analysis;
2424

25+
import org.opengrok.indexer.util.WhitelistObjectInputFilter;
26+
2527
import java.io.ByteArrayInputStream;
2628
import java.io.ByteArrayOutputStream;
2729
import java.io.IOException;
30+
import java.io.ObjectInputFilter;
2831
import java.io.ObjectInputStream;
2932
import java.io.ObjectOutputStream;
3033
import java.io.Serializable;
@@ -38,6 +41,12 @@ public class Scopes implements Serializable {
3841

3942
private static final long serialVersionUID = 1191703801007779489L;
4043

44+
private static final ObjectInputFilter serialFilter = new WhitelistObjectInputFilter(
45+
Scopes.class,
46+
TreeSet.class,
47+
Scope.class
48+
);
49+
4150
/**
4251
* Note: this class has a natural ordering that is inconsistent with equals.
4352
*/
@@ -164,10 +173,10 @@ public byte[] serialize() throws IOException {
164173
* @throws ClassCastException if the array contains an object of another
165174
* type than {@code Definitions}
166175
*/
167-
public static Scopes deserialize(byte[] bytes)
168-
throws IOException, ClassNotFoundException {
169-
ObjectInputStream in
170-
= new ObjectInputStream(new ByteArrayInputStream(bytes));
171-
return (Scopes) in.readObject();
176+
public static Scopes deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
177+
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
178+
in.setObjectInputFilter(serialFilter);
179+
return (Scopes) in.readObject();
180+
}
172181
}
173182
}

opengrok-indexer/src/main/java/org/opengrok/indexer/index/IndexAnalysisSettings.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@
2222
*/
2323
package org.opengrok.indexer.index;
2424

25+
import org.opengrok.indexer.util.WhitelistObjectInputFilter;
26+
2527
import java.io.ByteArrayInputStream;
2628
import java.io.ByteArrayOutputStream;
2729
import java.io.IOException;
30+
import java.io.ObjectInputFilter;
2831
import java.io.ObjectInputStream;
2932
import java.io.ObjectOutputStream;
3033
import java.io.Serializable;
@@ -42,6 +45,8 @@ public final class IndexAnalysisSettings implements Serializable {
4245

4346
private static final long serialVersionUID = 1172403004716059609L;
4447

48+
private static final ObjectInputFilter serialFilter = new WhitelistObjectInputFilter(IndexAnalysisSettings.class);
49+
4550
private String projectName;
4651

4752
/**
@@ -136,9 +141,10 @@ public void setAnalyzersVersions(Map<String, Long> values) {
136141
* OutputStream.
137142
*/
138143
public byte[] serialize() throws IOException {
139-
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
140-
new ObjectOutputStream(bytes).writeObject(this);
141-
return bytes.toByteArray();
144+
try (ByteArrayOutputStream bytes = new ByteArrayOutputStream(); var oos = new ObjectOutputStream(bytes)) {
145+
oos.writeObject(this);
146+
return bytes.toByteArray();
147+
}
142148
}
143149

144150
/**
@@ -152,11 +158,11 @@ public byte[] serialize() throws IOException {
152158
* @throws ClassCastException if the array contains an object of another
153159
* type than {@code IndexAnalysisSettings}
154160
*/
155-
public static IndexAnalysisSettings deserialize(byte[] bytes)
156-
throws IOException, ClassNotFoundException {
157-
ObjectInputStream in = new ObjectInputStream(
158-
new ByteArrayInputStream(bytes));
159-
return (IndexAnalysisSettings) in.readObject();
161+
public static IndexAnalysisSettings deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
162+
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
163+
in.setObjectInputFilter(serialFilter);
164+
return (IndexAnalysisSettings) in.readObject();
165+
}
160166
}
161167

162168
private void readObject(ObjectInputStream in) throws ClassNotFoundException,

opengrok-indexer/src/main/java/org/opengrok/indexer/index/IndexAnalysisSettings3.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@
2222
*/
2323
package org.opengrok.indexer.index;
2424

25+
import org.opengrok.indexer.util.WhitelistObjectInputFilter;
26+
2527
import java.io.ByteArrayInputStream;
2628
import java.io.ByteArrayOutputStream;
2729
import java.io.IOException;
30+
import java.io.ObjectInputFilter;
2831
import java.io.ObjectInputStream;
2932
import java.io.ObjectOutputStream;
3033
import java.io.Serializable;
@@ -42,6 +45,8 @@ public final class IndexAnalysisSettings3 implements Serializable {
4245

4346
private static final long serialVersionUID = -4700122690707062276L;
4447

48+
private static final ObjectInputFilter serialFilter = new WhitelistObjectInputFilter(IndexAnalysisSettings3.class);
49+
4550
private String projectName;
4651

4752
/**
@@ -162,9 +167,10 @@ public void setIndexedSymlinks(Map<String, IndexedSymlink> values) {
162167
* OutputStream.
163168
*/
164169
public byte[] serialize() throws IOException {
165-
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
166-
new ObjectOutputStream(bytes).writeObject(this);
167-
return bytes.toByteArray();
170+
try (ByteArrayOutputStream bytes = new ByteArrayOutputStream(); var oos = new ObjectOutputStream(bytes)) {
171+
oos.writeObject(this);
172+
return bytes.toByteArray();
173+
}
168174
}
169175

170176
/**
@@ -178,11 +184,11 @@ public byte[] serialize() throws IOException {
178184
* @throws ClassCastException if the array contains an object of another
179185
* type than {@code IndexAnalysisSettings}
180186
*/
181-
public static IndexAnalysisSettings3 deserialize(byte[] bytes)
182-
throws IOException, ClassNotFoundException {
183-
ObjectInputStream in = new ObjectInputStream(
184-
new ByteArrayInputStream(bytes));
185-
return (IndexAnalysisSettings3) in.readObject();
187+
public static IndexAnalysisSettings3 deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
188+
try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
189+
in.setObjectInputFilter(serialFilter);
190+
return (IndexAnalysisSettings3) in.readObject();
191+
}
186192
}
187193

188194
@SuppressWarnings("Duplicates")
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* CDDL HEADER START
3+
*
4+
* The contents of this file are subject to the terms of the
5+
* Common Development and Distribution License (the "License").
6+
* You may not use this file except in compliance with the License.
7+
*
8+
* See LICENSE.txt included in this distribution for the specific
9+
* language governing permissions and limitations under the License.
10+
*
11+
* When distributing Covered Code, include this CDDL HEADER in each
12+
* file and include the License file at LICENSE.txt.
13+
* If applicable, add the following below this CDDL HEADER, with the
14+
* fields enclosed by brackets "[]" replaced with your own identifying
15+
* information: Portions Copyright [yyyy] [name of copyright owner]
16+
*
17+
* CDDL HEADER END
18+
*/
19+
20+
/*
21+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
22+
*/
23+
package org.opengrok.indexer.util;
24+
25+
import org.jetbrains.annotations.NotNull;
26+
27+
import java.io.ObjectInputFilter;
28+
import java.util.Set;
29+
30+
public class WhitelistObjectInputFilter implements ObjectInputFilter {
31+
32+
private final Set<Class<?>> whitelist;
33+
34+
public WhitelistObjectInputFilter(@NotNull final Class<?>... whitelist) {
35+
this.whitelist = Set.of(whitelist);
36+
}
37+
38+
@Override
39+
public Status checkInput(final FilterInfo filterInfo) {
40+
if (filterInfo.serialClass() == null || whitelist.contains(filterInfo.serialClass())) {
41+
return Status.ALLOWED;
42+
}
43+
return Status.REJECTED;
44+
}
45+
}

opengrok-indexer/src/test/java/org/opengrok/indexer/analysis/ScopesTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import org.junit.jupiter.api.Test;
2626
import org.opengrok.indexer.analysis.Scopes.Scope;
2727

28+
import java.io.IOException;
29+
2830
import static org.junit.jupiter.api.Assertions.assertEquals;
2931

3032
/**
@@ -63,4 +65,14 @@ public void testGetScope() {
6365
assertEquals(instance.getScope(101), globalScope);
6466
assertEquals(instance.getScope(500), globalScope);
6567
}
68+
69+
@Test
70+
void testSerialize() throws IOException, ClassNotFoundException {
71+
Scopes scopes = new Scopes();
72+
scopes.addScope(new Scope(1, 100, "name", "namespace", "signature"));
73+
byte[] bytes = scopes.serialize();
74+
Scopes deserialized = Scopes.deserialize(bytes);
75+
assertEquals(1, deserialized.size());
76+
}
77+
6678
}

opengrok-indexer/src/test/java/org/opengrok/indexer/index/IndexAnalysisSettingsUpgraderTest.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
package org.opengrok.indexer.index;
2424

2525
import java.io.IOException;
26+
import java.io.InvalidClassException;
2627
import java.util.HashMap;
2728
import java.util.Map;
2829

@@ -32,7 +33,7 @@
3233
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
3334
import static org.junit.jupiter.api.Assertions.assertEquals;
3435
import static org.junit.jupiter.api.Assertions.assertNotNull;
35-
import static org.junit.jupiter.api.Assertions.assertNull;
36+
import static org.junit.jupiter.api.Assertions.assertThrows;
3637
import static org.junit.jupiter.api.Assertions.assertTrue;
3738

3839
/**
@@ -123,13 +124,8 @@ public void shouldThrowIfVersionIsMisrepresented() throws IOException, ClassNotF
123124
byte[] bin = obj.serialize();
124125

125126
IndexAnalysisSettingsUpgrader upgrader = new IndexAnalysisSettingsUpgrader();
126-
IndexAnalysisSettings3 res = null;
127-
try {
128-
res = upgrader.upgrade(bin, 3); // wrong version
129-
} catch (ClassCastException e) {
130-
// expected
131-
}
132-
assertNull(res, "should not have produced an instance");
127+
assertThrows(InvalidClassException.class, () -> upgrader.upgrade(bin, 3),
128+
"should not have produced an instance");
133129
}
134130

135131
@Test

0 commit comments

Comments
 (0)