Check macOS Launcher's zip size before unzipping

The Launcher can download an error page rather than the full Launcher.
When this happens, the error page file is passed directly to unzip,
which promptly fails with the following message:

  End-of-central-directory signature not found.  Either this file is not
  a zipfile, or it constitutes one disk of a multi-part archive.  In the
  latter case the central directory and zipfile comment will be found on
  the last disk(s) of this archive.
  unzip:  cannot find zipfile directory in one of NewHQLauncher.zip or
          NewHQLauncher.zip.zip, and cannot find NewHQLauncher.zip.ZIP, period.

This change improves the error message by checking the size of the
Launcher download and failing if the Launcher is smaller than the
smallest Launcher we've released. The smallest Launcher we've had is
308KB, so I picked 250KB as the limit because it's a nice rounder number
below that.
This commit is contained in:
Matt Hardcastle 2019-09-05 09:49:38 -07:00
parent 96f6793a87
commit 43237e1409

View file

@ -1,6 +1,10 @@
#import "DownloadLauncher.h"
#import "Launcher.h"
#include <sys/stat.h>
static const __int32_t kMinLauncherSize = 250000; // 308kb is our smallest launcher
static const NSString *kIOError = @"IOError";
@implementation DownloadLauncher
@ -22,8 +26,38 @@
}
-(void)validateHQLauncherZipAt:(NSURL *)location {
// Does the file look like a valid HQLauncher ZIP?
struct stat lStat;
const char *cStrLocation = location.fileSystemRepresentation;
if (stat(cStrLocation, &lStat) != 0) {
NSLog(@"couldn't stat download file: %s", cStrLocation);
@throw [NSException exceptionWithName:(NSString *)kIOError
reason:@"couldn't stat download file"
userInfo:nil];
}
if (lStat.st_size <= kMinLauncherSize) {
NSLog(@"download is too small: %s is %lld bytes, should be at least %d bytes",
cStrLocation, lStat.st_size, kMinLauncherSize);
@throw [NSException exceptionWithName:(NSString *)kIOError
reason:@"download is too small"
userInfo:nil];
}
}
-(void)URLSession:(NSURLSession*)session downloadTask:(NSURLSessionDownloadTask*)downloadTask didFinishDownloadingToURL:(NSURL*)location {
NSLog(@"Did finish downloading to url");
@try {
[self validateHQLauncherZipAt:location];
}
@catch (NSException *exc) {
if ([exc.name isEqualToString:(NSString *)kIOError]) {
[[Launcher sharedLauncher] displayErrorPage];
return;
}
@throw;
}
NSError* error = nil;
NSFileManager* fileManager = [NSFileManager defaultManager];
NSString* destinationFileName = downloadTask.originalRequest.URL.lastPathComponent;