mirror of
https://github.com/corda/corda.git
synced 2025-01-21 03:55:00 +00:00
ObjectInputStream: handle TC_REFERENCE
There are serialized objects out in the wild which make heavy use of TC_REFERENCE: for example when an object has a reference to itself. Therefore we need to support that, too. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
parent
b6d3caf458
commit
ff45f452da
@ -36,6 +36,7 @@ import static java.io.ObjectOutputStream.getReadOrWriteMethod;
|
|||||||
|
|
||||||
import avian.VMClass;
|
import avian.VMClass;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@ -43,7 +44,10 @@ import java.lang.reflect.Method;
|
|||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
public class ObjectInputStream extends InputStream implements DataInput {
|
public class ObjectInputStream extends InputStream implements DataInput {
|
||||||
|
private final static int HANDLE_OFFSET = 0x7e0000;
|
||||||
|
|
||||||
private final InputStream in;
|
private final InputStream in;
|
||||||
|
private final ArrayList references;
|
||||||
|
|
||||||
public ObjectInputStream(InputStream in) throws IOException {
|
public ObjectInputStream(InputStream in) throws IOException {
|
||||||
this.in = in;
|
this.in = in;
|
||||||
@ -56,6 +60,7 @@ public class ObjectInputStream extends InputStream implements DataInput {
|
|||||||
if (version != STREAM_VERSION) {
|
if (version != STREAM_VERSION) {
|
||||||
throw new IOException("Unsupported version: " + version);
|
throw new IOException("Unsupported version: " + version);
|
||||||
}
|
}
|
||||||
|
references = new ArrayList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
@ -288,7 +293,13 @@ public class ObjectInputStream extends InputStream implements DataInput {
|
|||||||
int length = rawShort();
|
int length = rawShort();
|
||||||
byte[] bytes = new byte[length];
|
byte[] bytes = new byte[length];
|
||||||
readFully(bytes);
|
readFully(bytes);
|
||||||
return new String(bytes, "UTF-8");
|
String s = new String(bytes, "UTF-8");
|
||||||
|
references.add(s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
if (c == TC_REFERENCE) {
|
||||||
|
int handle = rawInt();
|
||||||
|
return references.get(handle - HANDLE_OFFSET);
|
||||||
}
|
}
|
||||||
if (c != TC_OBJECT) {
|
if (c != TC_OBJECT) {
|
||||||
throw new IOException("Unexpected token: 0x"
|
throw new IOException("Unexpected token: 0x"
|
||||||
@ -296,11 +307,21 @@ public class ObjectInputStream extends InputStream implements DataInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// class desc
|
// class desc
|
||||||
expectToken(TC_CLASSDESC);
|
c = rawByte();
|
||||||
ClassDesc classDesc = classDesc();
|
ClassDesc classDesc;
|
||||||
|
if (c == TC_REFERENCE) {
|
||||||
|
int handle = rawInt() - HANDLE_OFFSET;
|
||||||
|
classDesc = (ClassDesc)references.get(handle);
|
||||||
|
} else if (c == TC_CLASSDESC) {
|
||||||
|
classDesc = classDesc();
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException("Unexpected token: 0x"
|
||||||
|
+ Integer.toHexString(c));
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Object o = makeInstance(classDesc.clazz.vmClass);
|
Object o = makeInstance(classDesc.clazz.vmClass);
|
||||||
|
references.add(o);
|
||||||
|
|
||||||
boolean customized = (classDesc.flags & SC_WRITE_METHOD) != 0;
|
boolean customized = (classDesc.flags & SC_WRITE_METHOD) != 0;
|
||||||
Method readMethod = customized ?
|
Method readMethod = customized ?
|
||||||
@ -350,6 +371,7 @@ public class ObjectInputStream extends InputStream implements DataInput {
|
|||||||
+ Long.toHexString(expected));
|
+ Long.toHexString(expected));
|
||||||
}
|
}
|
||||||
} catch (Exception ignored) { }
|
} catch (Exception ignored) { }
|
||||||
|
references.add(result);
|
||||||
|
|
||||||
result.flags = rawByte();
|
result.flags = rawByte();
|
||||||
if ((result.flags & ~(SC_SERIALIZABLE | SC_WRITE_METHOD)) != 0) {
|
if ((result.flags & ~(SC_SERIALIZABLE | SC_WRITE_METHOD)) != 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user