diff --git a/src/main/java/com/alibaba/fastjson/JSONArray.java b/src/main/java/com/alibaba/fastjson/JSONArray.java index b3693f2600..922cef80ec 100755 --- a/src/main/java/com/alibaba/fastjson/JSONArray.java +++ b/src/main/java/com/alibaba/fastjson/JSONArray.java @@ -30,6 +30,7 @@ import static com.alibaba.fastjson.util.TypeUtils.castToTimestamp; import java.io.IOException; +import java.io.ObjectInputStream; import java.io.Serializable; import java.lang.reflect.Type; import java.math.BigDecimal; @@ -453,8 +454,15 @@ public int hashCode() { return this.list.hashCode(); } - private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { - s.defaultReadObject(); + private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + 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) { if (item != null) { ParserConfig.global.checkAutoType(item.getClass().getName(), null); diff --git a/src/main/java/com/alibaba/fastjson/JSONObject.java b/src/main/java/com/alibaba/fastjson/JSONObject.java index 350d66a117..4ab7ed4050 100755 --- a/src/main/java/com/alibaba/fastjson/JSONObject.java +++ b/src/main/java/com/alibaba/fastjson/JSONObject.java @@ -479,71 +479,19 @@ public Map getInnerMap() { 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 { - ensureFields(); - if (fields != null && !fields_error) { - ObjectInputStream secIn = new ObjectInputStream(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; - } - } - }; + SecureObjectInputStream.ensureFields(); + if (SecureObjectInputStream.fields != null && !SecureObjectInputStream.fields_error) { + ObjectInputStream secIn = new SecureObjectInputStream(in); secIn.defaultReadObject(); return; } in.defaultReadObject(); - for (Entry entry : map.entrySet()) { - final String key = entry.getKey(); + for (Entry entry : map.entrySet()) { + final Object key = entry.getKey(); if (key != null) { ParserConfig.global.checkAutoType(key.getClass().getName(), null); } @@ -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 { + + } + } } diff --git a/src/test/java/com/alibaba/json/bvt/JSONObjectTest_readObject.java b/src/test/java/com/alibaba/json/bvt/JSONObjectTest_readObject.java index 7d538a40de..d2bbbbfb3b 100644 --- a/src/test/java/com/alibaba/json/bvt/JSONObjectTest_readObject.java +++ b/src/test/java/com/alibaba/json/bvt/JSONObjectTest_readObject.java @@ -1,5 +1,6 @@ package com.alibaba.json.bvt; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import junit.framework.TestCase; @@ -28,4 +29,42 @@ public void test_0() throws Exception { assertEquals(JSONObject.class, obj.getClass()); 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); + } }