X-Git-Url: http://gitweb.fperrin.net/?a=blobdiff_plain;f=src%2Fcom%2Fhughes%2Fandroid%2Futil%2FPersistentObjectCache.java;h=938142c341591d7551dfa16dc5ebe55be7e859b5;hb=83d9dc7cd871082a82c2dd0dbb7a0ceabd7c83a0;hp=388eb7acce1deee0a085c02a3d23742c2f3f9247;hpb=3d72bc11d5ef9d58e62b5beb4e33a437da28d4b8;p=Dictionary.git diff --git a/src/com/hughes/android/util/PersistentObjectCache.java b/src/com/hughes/android/util/PersistentObjectCache.java index 388eb7a..938142c 100644 --- a/src/com/hughes/android/util/PersistentObjectCache.java +++ b/src/com/hughes/android/util/PersistentObjectCache.java @@ -18,22 +18,56 @@ import android.content.Context; import android.os.Environment; import android.util.Log; +import com.hughes.android.dictionary.DictionaryApplication; +import com.hughes.android.dictionary.DictionaryInfo; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InvalidClassException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; public class PersistentObjectCache { private final File dir; - private final Map objects = new LinkedHashMap(); + private final Map objects = new HashMap<>(); + + class ConstrainedOIS extends ObjectInputStream { + ConstrainedOIS(InputStream in) throws IOException { + super(in); + } + + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { + String name = desc.getName(); + // Note: try to avoid adding more classes. + // LinkedHashMap is already more than enough for a DoS + if (name.equals(String.class.getName()) || + name.equals(DictionaryInfo.IndexInfo.class.getName()) || + name.equals(ArrayList.class.getName()) || + name.equals(HashMap.class.getName()) || + name.equals(DictionaryInfo.class.getName()) || + name.equals(DictionaryApplication.DictionaryConfig.class.getName()) || + name.equals(LinkedHashMap.class.getName())) { + return super.resolveClass(desc); + } + throw new InvalidClassException("Not allowed to deserialize class", name); + } + } - public synchronized T read(final String filename, final Class resultClass) { + public synchronized T read(final String filename, final Class resultClass) { try { - Object object = (objects.get(filename)); + Object object = objects.get(filename); if (object != null) { return resultClass.cast(object); } @@ -43,12 +77,16 @@ public class PersistentObjectCache { Log.d(getClass().getSimpleName(), "File empty: " + src); return null; } + ObjectInputStream in = null; try { - final ObjectInputStream in = new ObjectInputStream(new FileInputStream(src)); + in = new ConstrainedOIS(new BufferedInputStream(new FileInputStream(src))); object = in.readObject(); in.close(); } catch (Exception e) { Log.e(getClass().getSimpleName(), "Deserialization failed: " + src, e); + try { + if (in != null) in.close(); + } catch (IOException e2) {} return null; } objects.put(filename, object); @@ -58,16 +96,19 @@ public class PersistentObjectCache { } } - public synchronized void write(final String filename, final Object object) { + public synchronized void write(final String filename, final Serializable object) { objects.put(filename, object); final File dest = new File(dir, filename); + ObjectOutputStream out = null; try { - final ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(dest)); + out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(dest))); out.writeObject(object); - out.close(); } catch (Exception e) { Log.e(getClass().getSimpleName(), "Serialization failed: " + dest, e); } + try { + if (out != null) out.close(); + } catch (IOException e) {} } private PersistentObjectCache(final Context context) { @@ -75,8 +116,8 @@ public class PersistentObjectCache { dir = filesDir != null ? filesDir : Environment.getExternalStorageDirectory(); if (dir == null) { throw new RuntimeException("context.getFilesDir() == " + context.getFilesDir() - + ", Environment.getExternalStorageDirectory()=" - + Environment.getExternalStorageDirectory()); + + ", Environment.getExternalStorageDirectory()=" + + Environment.getExternalStorageDirectory()); } } @@ -93,7 +134,7 @@ public class PersistentObjectCache { } else { if (!instance.dir.equals(context.getFilesDir())) { throw new RuntimeException("File dir changed. old=" + instance.dir + ", new=" - + context.getFilesDir()); + + context.getFilesDir()); } } return instance;