[558633] Validate classes on deserialization
Change-Id: I7c9ac823f543aeba14ce181b47f24984549bfd24
diff --git a/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/SnapshotImpl.java b/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/SnapshotImpl.java
index 3622d0f..1a178a5 100644
--- a/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/SnapshotImpl.java
+++ b/plugins/org.eclipse.mat.parser/src/org/eclipse/mat/parser/internal/SnapshotImpl.java
@@ -17,8 +17,10 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -102,7 +104,75 @@
File indexFile = new File(prefix + "index"); //$NON-NLS-1$
fis = new FileInputStream(indexFile);
listener.worked(1);
- ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(fis));
+ /**
+ * Classes deserialized:
+ * org.eclipse.mat.parser.model.XSnapshotInfo
+ * org.eclipse.mat.parser.model.AbstractObjectImpl
+ * org.eclipse.mat.parser.model.XGCRootInfo
+ * org.eclipse.mat.parser.model.ClassImpl
+ * [Lorg.eclipse.mat.parser.model.XGCRootInfo
+ * org.eclipse.mat.parser.model.XGCRootInfo
+ *
+ * org.eclipse.mat.snapshot.SnapshotInfo
+ * org.eclipse.mat.snapshot.UnreachableObjectsHistogram
+ *
+ * org.eclipse.mat.snapshot.model.GCRootInfo
+ * org.eclipse.mat.snapshot.model.FieldDescriptor
+ * org.eclipse.mat.snapshot.model.Field
+ * [Lorg.eclipse.mat.snapshot.model.FieldDescriptor
+ * [Lorg.eclipse.mat.snapshot.model.Field
+ * org.eclipse.mat.snapshot.model.ObjectReference
+ *
+ * org.eclipse.mat.collect.HashMapIntObject
+ * org.eclipse.mat.collect.BitField
+ *
+ * java.util.ArrayList:
+ * java.util.Date
+ * java.util.HashMap
+ *
+ * java.lang.Boolean
+ * java.lang.Long
+ * java.lang.Number
+ * java.lang.Byte
+ * java.lang.Short
+ * java.lang.Character
+ * java.lang.Double
+ * java.lang.Float
+ * [I
+ *
+ */
+ ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(fis)) {
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+ // similar to system property jdk.serialFilter
+ String match="java.lang.*;java.util.*;org.eclipse.mat.parser.model.*;org.eclipse.mat.snapshot.*;org.eclipse.mat.snapshot.model.*;org.eclipse.mat.collect.*;!*"; //$NON-NLS-1$
+ String nm = desc.getName();
+ if (!nm.startsWith("[")) //$NON-NLS-1$
+ {
+ for (String pt : match.split(";")) //$NON-NLS-1$
+ {
+ boolean not = pt.startsWith("!"); //$NON-NLS-1$
+ if (not)
+ pt = pt.substring(1);
+ boolean m;
+ if (pt.endsWith(".**")) //$NON-NLS-1$
+ m = nm.startsWith(pt.substring(0, pt.length() - 2));
+ else if (pt.endsWith(".*")) //$NON-NLS-1$
+ m = nm.startsWith(pt.substring(0, pt.length() - 1))
+ && !nm.substring(pt.length() - 1).contains("."); //$NON-NLS-1$
+ else if (pt.endsWith("*")) //$NON-NLS-1$
+ m = nm.startsWith(pt.substring(0, pt.length() - 1));
+ else
+ m = nm.equals(pt);
+ if (not && m)
+ throw new InvalidClassException(nm, match);
+ if (m)
+ break;
+ }
+ }
+ return super.resolveClass(desc);
+ }
+ };
String version = in.readUTF();
if (!VERSION.equals(version))
@@ -155,12 +225,26 @@
}
IndexManager indexManager = new IndexManager();
- indexManager.init(prefix);
+ boolean done = false;
+ try
+ {
+ indexManager.init(prefix);
- SnapshotImpl ret = new SnapshotImpl(snapshotInfo, heapObjectReader, classCache, roots, rootsPerThread, loaderLabels,
- arrayObjects, indexManager);
- listener.worked(3);
- return ret;
+ SnapshotImpl ret = new SnapshotImpl(snapshotInfo, heapObjectReader, classCache, roots, rootsPerThread, loaderLabels,
+ arrayObjects, indexManager);
+ listener.worked(3);
+ done = true;
+
+ return ret;
+ }
+ finally
+ {
+ if (!done)
+ {
+ // Close files on error to allow delete
+ indexManager.close();
+ }
+ }
}
catch (ClassNotFoundException e)
{
diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/SnapshotHistoryService.java b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/SnapshotHistoryService.java
index f753ae1..0d138bd 100644
--- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/SnapshotHistoryService.java
+++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/SnapshotHistoryService.java
@@ -14,8 +14,10 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
@@ -197,7 +199,47 @@
list = new LinkedList<Entry>();
- ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file));
+ /*
+ * org.eclipse.mat.ui.SnapshotHistoryService$Entry
+ * java.lang.Long
+ * java.lang.Number
+ * org.eclipse.mat.snapshot.SnapshotInfo
+ * java.util.Date
+ * java.util.HashMap
+ * java.lang.Boolean
+ */
+ ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file)) {
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+ // similar to system property jdk.serialFilter
+ String match="java.lang.*;java.util.*;org.eclipse.mat.snapshot.SnapshotInfo;org.eclipse.mat.ui.SnapshotHistoryService$Entry;!*"; //$NON-NLS-1$
+ String nm = desc.getName();
+ if (!nm.startsWith("[")) //$NON-NLS-1$
+ {
+ for (String pt : match.split(";")) //$NON-NLS-1$
+ {
+ boolean not = pt.startsWith("!"); //$NON-NLS-1$
+ if (not)
+ pt = pt.substring(1);
+ boolean m;
+ if (pt.endsWith(".**")) //$NON-NLS-1$
+ m = nm.startsWith(pt.substring(0, pt.length() - 2));
+ else if (pt.endsWith(".*")) //$NON-NLS-1$
+ m = nm.startsWith(pt.substring(0, pt.length() - 1))
+ && !nm.substring(pt.length() - 1).contains("."); //$NON-NLS-1$
+ else if (pt.endsWith("*")) //$NON-NLS-1$
+ m = nm.startsWith(pt.substring(0, pt.length() - 1));
+ else
+ m = nm.equals(pt);
+ if (not && m)
+ throw new InvalidClassException(nm, match);
+ if (m)
+ break;
+ }
+ }
+ return super.resolveClass(desc);
+ }
+ };
try
{
int size = oin.readInt();
diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/browser/QueryHistory.java b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/browser/QueryHistory.java
index 4864eb0..1d99640 100644
--- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/browser/QueryHistory.java
+++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/internal/browser/QueryHistory.java
@@ -14,8 +14,10 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
@@ -72,7 +74,47 @@
{
try
{
- ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file));
+ /**
+ * org.eclipse.mat.ui.SnapshotHistoryService$Entry
+ * java.lang.Long
+ * java.lang.Number
+ * org.eclipse.mat.snapshot.SnapshotInfo
+ * java.util.Date
+ * java.util.HashMap
+ * java.lang.Boolean
+ */
+ ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file)) {
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+ // similar to system property jdk.serialFilter
+ String match="java.lang.*;java.util.*;org.eclipse.mat.snapshot.*;org.eclipse.mat.ui.SnapshotHistoryService$Entry;!*"; //$NON-NLS-1$
+ String nm = desc.getName();
+ if (!nm.startsWith("[")) //$NON-NLS-1$
+ {
+ for (String pt : match.split(";")) //$NON-NLS-1$
+ {
+ boolean not = pt.startsWith("!"); //$NON-NLS-1$
+ if (not)
+ pt = pt.substring(1);
+ boolean m;
+ if (pt.endsWith(".**")) //$NON-NLS-1$
+ m = nm.startsWith(pt.substring(0, pt.length() - 2));
+ else if (pt.endsWith(".*")) //$NON-NLS-1$
+ m = nm.startsWith(pt.substring(0, pt.length() - 1))
+ && !nm.substring(pt.length() - 1).contains("."); //$NON-NLS-1$
+ else if (pt.endsWith("*")) //$NON-NLS-1$
+ m = nm.startsWith(pt.substring(0, pt.length() - 1));
+ else
+ m = nm.equals(pt);
+ if (not && m)
+ throw new InvalidClassException(nm, match);
+ if (m)
+ break;
+ }
+ }
+ return super.resolveClass(desc);
+ }
+ };
try
{
history = (LinkedList<String>) oin.readObject();