Bug 1261983 - infer: close file input stream in case of GZIP failure draft
authorAndrzej Hunt <ahunt@mozilla.com>
Fri, 14 Apr 2017 12:10:25 -0700
changeset 563014 659e85b6e2dc54a35b4213583638a86aeb4c89df
parent 561690 aca6b2a5a2ab3338436c9e819dc2244a022b6425
child 563016 a6199ee49e22d9d0ce307a306fd80f4e38fa15d9
push id54188
push userahunt@mozilla.com
push dateFri, 14 Apr 2017 21:37:48 +0000
bugs1261983
milestone55.0a1
Bug 1261983 - infer: close file input stream in case of GZIP failure This commit also cleans up extraneous stream closes: these streams are closed in finally, so we don't need to also clean them up in the main try block body. MozReview-Commit-ID: EXxlmmtqvyq
mobile/android/base/java/org/mozilla/gecko/dlc/DownloadAction.java
--- a/mobile/android/base/java/org/mozilla/gecko/dlc/DownloadAction.java
+++ b/mobile/android/base/java/org/mozilla/gecko/dlc/DownloadAction.java
@@ -210,45 +210,49 @@ public class DownloadAction extends Base
 
     protected OutputStream openFile(File file, boolean append) throws FileNotFoundException {
         return new BufferedOutputStream(new FileOutputStream(file, append));
     }
 
     protected void extract(File sourceFile, File destinationFile, String checksum)
             throws UnrecoverableDownloadContentException, RecoverableDownloadContentException {
         InputStream inputStream = null;
+        InputStream gzInputStream = null;
         OutputStream outputStream = null;
         File temporaryFile = null;
 
         try {
             File destinationDirectory = destinationFile.getParentFile();
             if (!destinationDirectory.exists() && !destinationDirectory.mkdirs()) {
                 throw new IOException("Destination directory does not exist and cannot be created");
             }
 
             temporaryFile = new File(destinationDirectory, destinationFile.getName() + ".tmp");
 
-            inputStream = new GZIPInputStream(new BufferedInputStream(new FileInputStream(sourceFile)));
+            // We have to have keep a handle to the BufferedInputStream: the GZIPInputStream
+            // constructor can fail e.g. if the stream isn't a GZIP stream. If we didn't keep
+            // a reference to that stream we wouldn't be able to close it if GZInputStream throws.
+            // (The BufferedInputStream constructor doesn't throw, so we don't need to care about it.)
+            inputStream = new BufferedInputStream(new FileInputStream(sourceFile));
+            gzInputStream = new GZIPInputStream(inputStream);
             outputStream = new BufferedOutputStream(new FileOutputStream(temporaryFile));
 
-            IOUtils.copy(inputStream, outputStream);
-
-            inputStream.close();
-            outputStream.close();
+            IOUtils.copy(gzInputStream, outputStream);
 
             if (!verify(temporaryFile, checksum)) {
                 Log.w(LOGTAG, "Checksum of extracted file does not match.");
                 return;
             }
 
             move(temporaryFile, destinationFile);
         } catch (IOException e) {
             // We could not extract to the destination: Keep temporary file and try again next time we run.
             throw new RecoverableDownloadContentException(RecoverableDownloadContentException.DISK_IO, e);
         } finally {
+            IOUtils.safeStreamClose(gzInputStream);
             IOUtils.safeStreamClose(inputStream);
             IOUtils.safeStreamClose(outputStream);
 
             if (temporaryFile != null && temporaryFile.exists()) {
                 temporaryFile.delete();
             }
         }
     }