SharedPreferences は結構簡単に壊れる

ちょっと前に Google+ に書いたけど、こっちにも。
Android開発者が大好きで信頼も厚い SharedPreferences が、意外と簡単に壊れる件。

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
Editor editor = prefs.edit();
editor.putString("name", "\0");  // ←ここが問題の箇所
editor.commit();

このようにすると、次回 SharedPreferences を読み込むときにログに warning が出力され、保存したデータはすべて失われてしまいます。

W/ApplicationContext( 4239): getSharedPreferences
W/ApplicationContext( 4239): org.xmlpull.v1.XmlPullParserException: Error parsing document. (position:line -1, column -1) caused by: org.apache.harmony.xml.ExpatParser$ParseException: At line 3, column 20: not well-formed (invalid token)
W/ApplicationContext( 4239):    at org.apache.harmony.xml.ExpatPullParser$ByteDocument.flush(ExpatPullParser.java:958)
W/ApplicationContext( 4239):    at org.apache.harmony.xml.ExpatPullParser$Document.pump(ExpatPullParser.java:769)
W/ApplicationContext( 4239):    at org.apache.harmony.xml.ExpatPullParser$Document.dequeue(ExpatPullParser.java:813)
W/ApplicationContext( 4239):    at org.apache.harmony.xml.ExpatPullParser.next(ExpatPullParser.java:302)
W/ApplicationContext( 4239):    at com.android.internal.util.XmlUtils.readValueXml(XmlUtils.java:675)
W/ApplicationContext( 4239):    at com.android.internal.util.XmlUtils.readMapXml(XmlUtils.java:470)
W/ApplicationContext( 4239):    at android.app.ContextImpl.getSharedPreferences(ContextImpl.java:379)
W/ApplicationContext( 4239):    at android.content.ContextWrapper.getSharedPreferences(ContextWrapper.java:146)
W/ApplicationContext( 4239):    at android.preference.PreferenceManager.getDefaultSharedPreferences(PreferenceManager.java:348)
W/ApplicationContext( 4239):    at jp.syoboi.test.helloworld.HelloWorldActivity.onCreate(HelloWorldActivity.java:16)
W/ApplicationContext( 4239):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
W/ApplicationContext( 4239):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
W/ApplicationContext( 4239):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
W/ApplicationContext( 4239):    at android.app.ActivityThread.access$1500(ActivityThread.java:117)
W/ApplicationContext( 4239):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
W/ApplicationContext( 4239):    at android.os.Handler.dispatchMessage(Handler.java:99)
W/ApplicationContext( 4239):    at android.os.Looper.loop(Looper.java:130)
W/ApplicationContext( 4239):    at android.app.ActivityThread.main(ActivityThread.java:3683)
W/ApplicationContext( 4239):    at java.lang.reflect.Method.invokeNative(Native Method)
W/ApplicationContext( 4239):    at java.lang.reflect.Method.invoke(Method.java:507)
W/ApplicationContext( 4239):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
W/ApplicationContext( 4239):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
W/ApplicationContext( 4239):    at dalvik.system.NativeStart.main(Native Method)

「設定が初期化される」という問題が報告され「あぁ、また Galaxy S か」と思っていたところ、この問題が見つかりました。
実際には Exception のメッセージをそのまま SharedPreferences に保存していたら、たまたまその中に "\uffff" が含まれていて、SharedPreferences が壊れていたというわけでした。こわいこわい。