blob: d09c5255c6fb4cca81a750cb7a8d25fa1d527ecc [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package android.appsecurity.cts;
import static com.google.common.truth.Truth.assertThat;
import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.util.FileUtil;
import org.junit.After;
import org.junit.Before;
import java.io.File;
/**
* Set of tests that verify that corrupt APKs are properly rejected by PackageManager and
* do not cause the system to crash.
*/
@AppModeFull // TODO: Needs porting to instant
public class CorruptApkTests extends DeviceTestCase implements IBuildReceiver {
private final String B71360999_PKG = "com.android.appsecurity.b71360999";
private final String B71361168_PKG = "com.android.appsecurity.b71361168";
private final String B79488511_PKG = "com.android.appsecurity.b79488511";
private IBuildInfo mBuildInfo;
@Override
public void setBuild(IBuildInfo buildInfo) {
mBuildInfo = buildInfo;
}
@Before
@Override
public void setUp() throws Exception {
super.setUp();
uninstall(B71360999_PKG);
uninstall(B71361168_PKG);
uninstall(B79488511_PKG);
}
@After
@Override
public void tearDown() throws Exception {
super.tearDown();
uninstall(B71360999_PKG);
uninstall(B71361168_PKG);
uninstall(B79488511_PKG);
}
/** Uninstall the apk if the test failed previously. */
public void uninstall(String pkg) throws Exception {
ITestDevice device = getDevice();
if (device.getInstalledPackageNames().contains(pkg)) {
device.uninstallPackage(pkg);
}
}
/**
* Tests that apks described in b/71360999 do not install successfully.
*/
public void testFailToInstallCorruptStringPoolHeader_b71360999() throws Exception {
final String APK_PATH = "CtsCorruptApkTests_b71360999.apk";
assertInstallNoFatalError(APK_PATH, B71360999_PKG);
}
/**
* Tests that apks described in b/71361168 do not install successfully.
*/
public void testFailToInstallCorruptStringPoolHeader_b71361168() throws Exception {
final String APK_PATH = "CtsCorruptApkTests_b71361168.apk";
assertInstallNoFatalError(APK_PATH, B71361168_PKG);
}
/**
* Tests that apks described in b/79488511 do not install successfully.
*/
public void testFailToInstallCorruptStringPoolHeader_b79488511() throws Exception {
final String APK_PATH = "CtsCorruptApkTests_b79488511.apk";
assertInstallNoFatalError(APK_PATH, B79488511_PKG);
}
/**
* Assert that installing the app does not cause a native error caused by a buffer overflow
* or an out-of-bounds read.
**/
private void assertInstallNoFatalError(String filename, String pkg) throws Exception {
ITestDevice device = getDevice();
device.clearLogcat();
final String result = device.installPackage(
new CompatibilityBuildHelper(mBuildInfo).getTestFile(filename),
true /*reinstall*/);
// Starting from P, corrupt apks should always fail to install
if (device.getApiLevel() >= 28) {
assertThat(result).isNotNull();
assertThat(result).isNotEmpty();
assertThat(device.getInstalledPackageNames()).doesNotContain(pkg);
}
// This catches if the device fails to install the app because a segmentation fault
// or out of bounds read created by the bug occurs
File tmpTxtFile = null;
InputStreamSource source = device.getLogcat(200 * 1024);
try {
assertNotNull(source);
tmpTxtFile = FileUtil.createTempFile("logcat", ".txt");
FileUtil.writeToFile(source.createInputStream(), tmpTxtFile);
String s = FileUtil.readStringFromFile(tmpTxtFile);
assertFalse(s.contains("SIGSEGV"));
assertFalse(s.contains("==ERROR"));
} finally {
source.close();
if (tmpTxtFile != null) {
FileUtil.deleteFile(tmpTxtFile);
}
}
}
}