From cb5923e03b02f99a1e99278c6f204565821b3360 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 3 Apr 2018 21:06:54 +0200 Subject: [PATCH 1/3] ensure images are never larger than device supports In order to save disk space and memory, at a cost of some CPU time, this makes sure that all downloaded images are not bigger than the device can support. A nice side effect of this process is that EXIF information is stripped from JPEG files since they are read into a Bitmap, then written out as a PNG. This should complete the JPEG EXIF stripping started in 2a3aaacf2347679f30e2c8feffb92f25bb882c8b with considerExifParams(false) !653 --- .../java/org/fdroid/fdroid/FDroidApp.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/app/src/main/java/org/fdroid/fdroid/FDroidApp.java b/app/src/main/java/org/fdroid/fdroid/FDroidApp.java index 0d3a05068..aa9ae58fb 100644 --- a/app/src/main/java/org/fdroid/fdroid/FDroidApp.java +++ b/app/src/main/java/org/fdroid/fdroid/FDroidApp.java @@ -32,15 +32,18 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; +import android.graphics.Bitmap; import android.os.Build; import android.os.Environment; import android.os.StrictMode; import android.text.TextUtils; import android.util.Log; +import android.view.Display; import android.view.WindowManager; import android.widget.Toast; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; +import com.nostra13.universalimageloader.core.process.BitmapProcessor; import info.guardianproject.netcipher.NetCipher; import info.guardianproject.netcipher.proxy.OrbotHelper; import org.acra.ACRA; @@ -61,6 +64,7 @@ import org.fdroid.fdroid.net.ImageLoaderForUIL; import org.fdroid.fdroid.net.WifiStateChangeService; import org.fdroid.fdroid.views.hiding.HidingManager; +import javax.microedition.khronos.opengles.GL10; import java.io.IOException; import java.security.Security; import java.util.List; @@ -380,9 +384,31 @@ public class FDroidApp extends Application { UpdateService.schedule(getApplicationContext()); bluetoothAdapter = getBluetoothAdapter(); + // There are a couple things to pay attention to with this config: memory usage, + // especially on small devices; and, image processing vulns, since images are + // submitted via app's git repos, so anyone with commit privs there could submit + // exploits hidden in images. Luckily, F-Droid doesn't need EXIF at all, and + // that is where the JPEG/PNG vulns have been. So it can be entirely stripped. + Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay(); + int maxSize = GL10.GL_MAX_TEXTURE_SIZE; // see ImageScaleType.NONE_SAFE javadoc + int width = display.getWidth(); + if (width > maxSize) { + maxSize = width; + } + int height = display.getHeight(); + if (height > maxSize) { + maxSize = height; + } ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext()) .imageDownloader(new ImageLoaderForUIL(getApplicationContext())) .defaultDisplayImageOptions(Utils.getDefaultDisplayImageOptionsBuilder().build()) + .diskCacheExtraOptions(maxSize, maxSize, new BitmapProcessor() { + @Override + public Bitmap process(Bitmap bitmap) { + // converting JPEGs to Bitmaps, then saving them removes EXIF metadata + return bitmap; + } + }) .threadPoolSize(getThreadPoolSize()) .build(); ImageLoader.getInstance().init(config); From fa9a4ce608e7d9e4444645a45e269ab0121cb91c Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 3 Apr 2018 23:22:11 +0200 Subject: [PATCH 2/3] scale all images to the exact required size to save memory/disk !661 https://gitlab.com/fdroid/fdroidclient/merge_requests/653#note_65065867 --- app/src/main/java/org/fdroid/fdroid/Utils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/fdroid/fdroid/Utils.java b/app/src/main/java/org/fdroid/fdroid/Utils.java index a0480f461..c9a5258c8 100644 --- a/app/src/main/java/org/fdroid/fdroid/Utils.java +++ b/app/src/main/java/org/fdroid/fdroid/Utils.java @@ -379,7 +379,7 @@ public final class Utils { .cacheOnDisk(true) .considerExifParams(false) .bitmapConfig(Bitmap.Config.RGB_565) - .imageScaleType(ImageScaleType.NONE); + .imageScaleType(ImageScaleType.EXACTLY); } return defaultDisplayImageOptionsBuilder; } From 48e438d5109d80fee269c69071bfe3c5e4f387d1 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 3 Apr 2018 23:59:50 +0200 Subject: [PATCH 3/3] declare some key vars final to help the compiler optimize those Apparently, the Java compiler can in some cases reuse a final value instead of executing a method again. This is from @hotlittlewhitedog !653 --- app/src/main/java/org/fdroid/fdroid/data/App.java | 7 ++++--- .../java/org/fdroid/fdroid/views/apps/AppListAdapter.java | 3 ++- .../org/fdroid/fdroid/views/whatsnew/WhatsNewAdapter.java | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/data/App.java b/app/src/main/java/org/fdroid/fdroid/data/App.java index 120021760..aff0a6e78 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/App.java +++ b/app/src/main/java/org/fdroid/fdroid/data/App.java @@ -219,12 +219,13 @@ public class App extends ValueObject implements Comparable, Parcelable { public App() { } - public App(Cursor cursor) { + public App(final Cursor cursor) { checkCursorPosition(cursor); - for (int i = 0; i < cursor.getColumnCount(); i++) { - String n = cursor.getColumnName(i); + final int cursorColumnCount = cursor.getColumnCount(); + for (int i = 0; i < cursorColumnCount; i++) { + final String n = cursor.getColumnName(i); switch (n) { case Cols.ROW_ID: id = cursor.getLong(i); diff --git a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListAdapter.java index 4d1590cce..32fc0561d 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/apps/AppListAdapter.java +++ b/app/src/main/java/org/fdroid/fdroid/views/apps/AppListAdapter.java @@ -34,7 +34,8 @@ class AppListAdapter extends RecyclerView.Adapter @Override public void onBindViewHolder(StandardAppListItemController holder, int position) { cursor.moveToPosition(position); - holder.bindModel(new App(cursor)); + final App app = new App(cursor); + holder.bindModel(app); } @Override diff --git a/app/src/main/java/org/fdroid/fdroid/views/whatsnew/WhatsNewAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/whatsnew/WhatsNewAdapter.java index 7500f16d6..671ec8b27 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/whatsnew/WhatsNewAdapter.java +++ b/app/src/main/java/org/fdroid/fdroid/views/whatsnew/WhatsNewAdapter.java @@ -80,7 +80,8 @@ public class WhatsNewAdapter extends RecyclerView.Adapter { @Override public void onBindViewHolder(AppCardController holder, int position) { cursor.moveToPosition(position); - holder.bindApp(new App(cursor)); + final App app = new App(cursor); + holder.bindApp(app); } @Override