Skip to content

Commit

Permalink
bug fixed for readObject.
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed Jul 12, 2018
1 parent 00f310a commit a0c709c
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 59 deletions.
12 changes: 10 additions & 2 deletions src/main/java/com/alibaba/fastjson/JSONArray.java
Expand Up @@ -30,6 +30,7 @@
import static com.alibaba.fastjson.util.TypeUtils.castToTimestamp; import static com.alibaba.fastjson.util.TypeUtils.castToTimestamp;


import java.io.IOException; import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.math.BigDecimal; import java.math.BigDecimal;
Expand Down Expand Up @@ -453,8 +454,15 @@ public int hashCode() {
return this.list.hashCode(); return this.list.hashCode();
} }


private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
s.defaultReadObject(); JSONObject.SecureObjectInputStream.ensureFields();
if (JSONObject.SecureObjectInputStream.fields != null && !JSONObject.SecureObjectInputStream.fields_error) {
ObjectInputStream secIn = new JSONObject.SecureObjectInputStream(in);
secIn.defaultReadObject();
return;
}

in.defaultReadObject();
for (Object item : list) { for (Object item : list) {
if (item != null) { if (item != null) {
ParserConfig.global.checkAutoType(item.getClass().getName(), null); ParserConfig.global.checkAutoType(item.getClass().getName(), null);
Expand Down
123 changes: 66 additions & 57 deletions src/main/java/com/alibaba/fastjson/JSONObject.java
Expand Up @@ -479,71 +479,19 @@ public Map<String, Object> getInnerMap() {
return this.map; return this.map;
} }


static Field[] fields;
static volatile boolean fields_error;


static void ensureFields() {
if (fields == null && !fields_error) {
try {
final Field[] declaredFields = ObjectInputStream.class.getDeclaredFields();
String[] fieldnames = new String[]{"bin", "passHandle", "handles", "curContext"};
Field[] array = new Field[fieldnames.length];
for (int i = 0; i < fieldnames.length; i++) {
Field field = TypeUtils
.getField(ObjectInputStream.class
, fieldnames[i]
, declaredFields
);
field.setAccessible(true);
array[i] = field;
}
fields = array;
} catch (Throwable error) {
fields_error = true;
}
}
}


private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
ensureFields(); SecureObjectInputStream.ensureFields();
if (fields != null && !fields_error) { if (SecureObjectInputStream.fields != null && !SecureObjectInputStream.fields_error) {
ObjectInputStream secIn = new ObjectInputStream(in) { ObjectInputStream secIn = new SecureObjectInputStream(in);
protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException {
String name = desc.getName();
ParserConfig.global.checkAutoType(name, null);
return super.resolveClass(desc);
}

protected Class<?> resolveProxyClass(String[] interfaces)
throws IOException, ClassNotFoundException {
for (String interfacename : interfaces) {
//检查是否处于黑名单
ParserConfig.global.checkAutoType(interfacename, null);
}
return super.resolveProxyClass(interfaces);
}

//Hack:默认构造方法会调用这个方法,重写此方法使用反射还原部分关键属性
protected void readStreamHeader() throws IOException, StreamCorruptedException {
try {
for (int i = 0; i < fields.length; i++) {
final Field field = fields[i];
final Object value = field.get(in);
field.set(this, value);
}
} catch (IllegalAccessException e) {
fields_error = true;
}
}
};
secIn.defaultReadObject(); secIn.defaultReadObject();
return; return;
} }


in.defaultReadObject(); in.defaultReadObject();
for (Entry<String, Object> entry : map.entrySet()) { for (Entry entry : map.entrySet()) {
final String key = entry.getKey(); final Object key = entry.getKey();
if (key != null) { if (key != null) {
ParserConfig.global.checkAutoType(key.getClass().getName(), null); ParserConfig.global.checkAutoType(key.getClass().getName(), null);
} }
Expand All @@ -554,4 +502,65 @@ protected void readStreamHeader() throws IOException, StreamCorruptedException {
} }
} }
} }

static class SecureObjectInputStream extends ObjectInputStream {
static Field[] fields;
static volatile boolean fields_error;

static void ensureFields() {
if (fields == null && !fields_error) {
try {
final Field[] declaredFields = ObjectInputStream.class.getDeclaredFields();
String[] fieldnames = new String[]{"bin", "passHandle", "handles", "curContext"};
Field[] array = new Field[fieldnames.length];
for (int i = 0; i < fieldnames.length; i++) {
Field field = TypeUtils
.getField(ObjectInputStream.class
, fieldnames[i]
, declaredFields
);
field.setAccessible(true);
array[i] = field;
}
fields = array;
} catch (Throwable error) {
fields_error = true;
}
}
}

public SecureObjectInputStream(ObjectInputStream in) throws IOException {
super(in);
try {
for (int i = 0; i < fields.length; i++) {
final Field field = fields[i];
final Object value = field.get(in);
field.set(this, value);
}
} catch (IllegalAccessException e) {
fields_error = true;
}
}

protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException {
String name = desc.getName();
ParserConfig.global.checkAutoType(name, null);
return super.resolveClass(desc);
}

protected Class<?> resolveProxyClass(String[] interfaces)
throws IOException, ClassNotFoundException {
for (String interfacename : interfaces) {
//检查是否处于黑名单
ParserConfig.global.checkAutoType(interfacename, null);
}
return super.resolveProxyClass(interfaces);
}

//Hack:默认构造方法会调用这个方法,重写此方法使用反射还原部分关键属性
protected void readStreamHeader() throws IOException, StreamCorruptedException {

}
}
} }
39 changes: 39 additions & 0 deletions src/test/java/com/alibaba/json/bvt/JSONObjectTest_readObject.java
@@ -1,5 +1,6 @@
package com.alibaba.json.bvt; package com.alibaba.json.bvt;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import junit.framework.TestCase; import junit.framework.TestCase;


Expand Down Expand Up @@ -28,4 +29,42 @@ public void test_0() throws Exception {
assertEquals(JSONObject.class, obj.getClass()); assertEquals(JSONObject.class, obj.getClass());
assertEquals(jsonObject, obj); assertEquals(jsonObject, obj);
} }

public void test_2() throws Exception {
JSONObject jsonObject = JSON.parseObject("{123:345}");

ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
ObjectOutputStream objOut = new ObjectOutputStream(bytesOut);
objOut.writeObject(jsonObject);
objOut.flush();

byte[] bytes = bytesOut.toByteArray();

ByteArrayInputStream bytesIn = new ByteArrayInputStream(bytes);
ObjectInputStream objIn = new ObjectInputStream(bytesIn);

Object obj = objIn.readObject();

assertEquals(JSONObject.class, obj.getClass());
assertEquals(jsonObject, obj);
}

public void test_3() throws Exception {
JSONObject jsonObject = JSON.parseObject("{123:345,\"items\":[1,2,3,4]}");

ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
ObjectOutputStream objOut = new ObjectOutputStream(bytesOut);
objOut.writeObject(jsonObject);
objOut.flush();

byte[] bytes = bytesOut.toByteArray();

ByteArrayInputStream bytesIn = new ByteArrayInputStream(bytes);
ObjectInputStream objIn = new ObjectInputStream(bytesIn);

Object obj = objIn.readObject();

assertEquals(JSONObject.class, obj.getClass());
assertEquals(jsonObject, obj);
}
} }

0 comments on commit a0c709c

Please sign in to comment.