您的位置:首页 > 其它

友盟反馈中发现的这样的问题,对下文没有考证,最终对2.3版本通过绕过Parserable 和 serializable方式解决的,留此只做备忘

2015-02-09 20:34 507 查看
OVERVIEW
Sending a private serializable subclass as an Intent extra can crash many receivers.

STEPS TO REPRODUCE
1. Send a private serializable subclass as an Intent extra to a receiver that inspects the extras.  For example, try the following sample code:

public class TestActivity extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);

startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS).putExtra("serializable", new CustomSerializable()));
}

private static final class CustomSerializable implements Serializable
{
private static final long serialVersionUID = 1L;
}
}

RESULTS
Actual behavior: The receiver crashes as soon as it attempts to look at the Intent's extras with a RuntimeException.  This is the trace generated on the Honeycomb emulator

E/AndroidRuntime(  464): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.settings/com.android.settings.Settings$WifiSettingsActivity}: java.lang.RuntimeException: Parcelable encounteredClassNotFoundException reading a Serializable object (name = com.test.TestActivity$CustomSerializable)
E/AndroidRuntime(  464): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1736)
E/AndroidRuntime(  464): 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1752)
E/AndroidRuntime(  464): 	at android.app.ActivityThread.access$1500(ActivityThread.java:123)
E/AndroidRuntime(  464): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:993)
E/AndroidRuntime(  464): 	at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(  464): 	at android.os.Looper.loop(Looper.java:126)
E/AndroidRuntime(  464): 	at android.app.ActivityThread.main(ActivityThread.java:3997)
E/AndroidRuntime(  464): 	at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(  464): 	at java.lang.reflect.Method.invoke(Method.java:491)
E/AndroidRuntime(  464): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
E/AndroidRuntime(  464): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
E/AndroidRuntime(  464): 	at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime(  464): Caused by: java.lang.RuntimeException: Parcelable encounteredClassNotFoundException reading a Serializable object (name = com.fragment.test.FragmentTestActivity$CustomSerializable)
E/AndroidRuntime(  464): 	at android.os.Parcel.readSerializable(Parcel.java:2026)
E/AndroidRuntime(  464): 	at android.os.Parcel.readValue(Parcel.java:1897)
E/AndroidRuntime(  464): 	at android.os.Parcel.readMapInternal(Parcel.java:2083)
E/AndroidRuntime(  464): 	at android.os.Bundle.unparcel(Bundle.java:215)
E/AndroidRuntime(  464): 	at android.os.Bundle.getBoolean(Bundle.java:787)
E/AndroidRuntime(  464): 	at android.content.Intent.getBooleanExtra(Intent.java:3444)
E/AndroidRuntime(  464): 	at android.preference.PreferenceActivity.onIsHidingHeaders(PreferenceActivity.java:665)
E/AndroidRuntime(  464): 	at android.preference.PreferenceActivity.onCreate(PreferenceActivity.java:495)
E/AndroidRuntime(  464): 	at com.android.settings.Settings.onCreate(Settings.java:66)
E/AndroidRuntime(  464): 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1048)
E/AndroidRuntime(  464): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1700)
E/AndroidRuntime(  464): 	... 11 more
E/AndroidRuntime(  464): Caused by: java.lang.ClassNotFoundException: com.fragment.test.FragmentTestActivity$CustomSerializable
E/AndroidRuntime(  464): 	at java.lang.Class.classForName(Native Method)
E/AndroidRuntime(  464): 	at java.lang.Class.forName(Class.java:234)
E/AndroidRuntime(  464): 	at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:2392)
E/AndroidRuntime(  464): 	at java.io.ObjectInputStream.readNewClassDesc(ObjectInputStream.java:1742)
E/AndroidRuntime(  464): 	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:755)
E/AndroidRuntime(  464): 	at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:1888)
E/AndroidRuntime(  464): 	at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:859)
E/AndroidRuntime(  464): 	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2090)
E/AndroidRuntime(  464): 	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2045)
E/AndroidRuntime(  464): 	at android.os.Parcel.readSerializable(Parcel.java:2020)
E/AndroidRuntime(  464): 	... 21 more
E/AndroidRuntime(  464): Caused by: java.lang.NoClassDefFoundError: com.fragment.test.FragmentTestActivity$CustomSerializable
E/AndroidRuntime(  464): 	... 31 more
E/AndroidRuntime(  464): Caused by: java.lang.ClassNotFoundException: com.fragment.test.FragmentTestActivity$CustomSerializable in loader dalvik.system.PathClassLoader[/system/app/Settings.apk]
E/AndroidRuntime(  464): 	at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:251)
E/AndroidRuntime(  464): 	at java.lang.ClassLoader.loadClass(ClassLoader.java:548)
E/AndroidRuntime(  464): 	at java.lang.ClassLoader.loadClass(ClassLoader.java:508)
E/AndroidRuntime(  464): 	... 31 more

Expected behavior: The expected behavior requires additional design discussion.  At a minimum, the exception should be a ClassNotFoundException rather than a runtime exception.  This would allow all receivers to more easily catch this issue.  However requiring all receivers to implement such try-catch boilerplate might be non-obvious, and perhaps consideration should be given to other solutions.  For example, the extra could simply be suppressed (and logged as a error) similar to how accessing a extras as the wrong type is currently handled (e.g. store a string, try to retrieve a boolean, gets treated as if the boolean simply doesn't exist).

WORKAROUND
When reading the extras, the following can be done to prevent the receiver from crashing
/*
* This is a hack to work around a custom serializable classloader attack. This check must come before any of the Intent
* extras are examined.
*/
try
{
final Bundle extras = intent.getExtras();

if (extras != null)
{
// if a custom serializable subclass exists, this will throw an exception
extras.containsKey(null);
}
}
catch (final Exception e)
{
Log.e("Test", "Custom serializable attack detected; do not send private Serializable subclasses to this receiver", e); //$NON-NLS-1$
return;
}

NOTES
This issue reproduces on Droid, Nexus One, Nexus S, etc. running Android 2.2, 2.3.3, and 2.3.2 respectively.  It also reproduces on the Honeycomb emulator.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐