Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d91b5aa authored by Wu Ahan's avatar Wu Ahan
Browse files

DO NOT MERGE: Decode the input of both setStream and setResource calls first

The size of the input of both setStream and setResource may very big
that system server got oom while handling it, so we try to decode it
first before copying it to the wallpaper path, if the decoding fails, we
treat the input as an invalid input.

Bug: 204087139
Test: Manually set wallpaper, no PDoS observed.
Change-Id: I014cf461954992782b3dfa0dde67c98a572cc770
parent d7097b81
Loading
Loading
Loading
Loading
+29 −11
Original line number Original line Diff line number Diff line
@@ -1180,18 +1180,27 @@ public class WallpaperManager {
                    mContext.getUserId());
                    mContext.getUserId());
            if (fd != null) {
            if (fd != null) {
                FileOutputStream fos = null;
                FileOutputStream fos = null;
                boolean ok = false;
                final Bitmap tmp = BitmapFactory.decodeStream(resources.openRawResource(resid));
                try {
                try {
                    // If the stream can't be decoded, treat it as an invalid input.
                    if (tmp != null) {
                        fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
                        fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
                    copyStreamToWallpaperFile(resources.openRawResource(resid), fos);
                        tmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
                        // The 'close()' is the trigger for any server-side image manipulation,
                        // The 'close()' is the trigger for any server-side image manipulation,
                        // so we must do that before waiting for completion.
                        // so we must do that before waiting for completion.
                        fos.close();
                        fos.close();
                        completion.waitForCompletion();
                        completion.waitForCompletion();
                    } else {
                        throw new IllegalArgumentException(
                                "Resource 0x" + Integer.toHexString(resid) + " is invalid");
                    }
                } finally {
                } finally {
                    // Might be redundant but completion shouldn't wait unless the write
                    // Might be redundant but completion shouldn't wait unless the write
                    // succeeded; this is a fallback if it threw past the close+wait.
                    // succeeded; this is a fallback if it threw past the close+wait.
                    IoUtils.closeQuietly(fos);
                    IoUtils.closeQuietly(fos);
                    if (tmp != null) {
                        tmp.recycle();
                    }
                }
                }
            }
            }
        } catch (RemoteException e) {
        } catch (RemoteException e) {
@@ -1433,13 +1442,22 @@ public class WallpaperManager {
                    result, which, completion, mContext.getUserId());
                    result, which, completion, mContext.getUserId());
            if (fd != null) {
            if (fd != null) {
                FileOutputStream fos = null;
                FileOutputStream fos = null;
                final Bitmap tmp = BitmapFactory.decodeStream(bitmapData);
                try {
                try {
                    // If the stream can't be decoded, treat it as an invalid input.
                    if (tmp != null) {
                        fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
                        fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
                    copyStreamToWallpaperFile(bitmapData, fos);
                        tmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
                        fos.close();
                        fos.close();
                        completion.waitForCompletion();
                        completion.waitForCompletion();
                    } else {
                        throw new IllegalArgumentException("InputStream is invalid");
                    }
                } finally {
                } finally {
                    IoUtils.closeQuietly(fos);
                    IoUtils.closeQuietly(fos);
                    if (tmp != null) {
                        tmp.recycle();
                    }
                }
                }
            }
            }
        } catch (RemoteException e) {
        } catch (RemoteException e) {