Loading core/java/com/android/internal/content/NativeLibraryHelper.java +4 −6 Original line number Diff line number Diff line Loading @@ -172,8 +172,7 @@ public class NativeLibraryHelper { private static native long nativeOpenApkFd(FileDescriptor fd, String debugPath); private static native void nativeClose(long handle); private static native long nativeSumNativeBinaries(long handle, String cpuAbi, boolean debuggable); private static native long nativeSumNativeBinaries(long handle, String cpuAbi); private native static int nativeCopyNativeBinaries(long handle, String sharedLibraryPath, String abiToCopy, boolean extractNativeLibs, boolean debuggable); Loading @@ -188,7 +187,7 @@ public class NativeLibraryHelper { private static long sumNativeBinaries(Handle handle, String abi) { long sum = 0; for (long apkHandle : handle.apkHandles) { sum += nativeSumNativeBinaries(apkHandle, abi, handle.debuggable); sum += nativeSumNativeBinaries(apkHandle, abi); } return sum; } Loading Loading @@ -222,7 +221,7 @@ public class NativeLibraryHelper { public static int findSupportedAbi(Handle handle, String[] supportedAbis) { int finalRes = NO_NATIVE_LIBRARIES; for (long apkHandle : handle.apkHandles) { final int res = nativeFindSupportedAbi(apkHandle, supportedAbis, handle.debuggable); final int res = nativeFindSupportedAbi(apkHandle, supportedAbis); if (res == NO_NATIVE_LIBRARIES) { // No native code, keep looking through all APKs. } else if (res == INSTALL_FAILED_NO_MATCHING_ABIS) { Loading @@ -244,8 +243,7 @@ public class NativeLibraryHelper { return finalRes; } private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis, boolean debuggable); private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis); // Convenience method to call removeNativeBinariesFromDirLI(File) public static void removeNativeBinariesLI(String nativeLibraryPath) { Loading core/jni/com_android_internal_content_NativeLibraryHelper.cpp +17 −21 Original line number Diff line number Diff line Loading @@ -349,21 +349,19 @@ static install_status_t copyFileIfChanged(JNIEnv* env, void* arg, ZipFileRO* zip * satisfied : * * - The entry is under the lib/ directory. * - The entry name ends with ".so" and the entry name starts with "lib", * an exception is made for debuggable apps. * - The entry filename is "safe" (as determined by isFilenameSafe). * */ class NativeLibrariesIterator { private: NativeLibrariesIterator(ZipFileRO* zipFile, bool debuggable, void* cookie) : mZipFile(zipFile), mDebuggable(debuggable), mCookie(cookie), mLastSlash(nullptr) { NativeLibrariesIterator(ZipFileRO* zipFile, void* cookie) : mZipFile(zipFile), mCookie(cookie), mLastSlash(nullptr) { fileName[0] = '\0'; } public: static base::expected<std::unique_ptr<NativeLibrariesIterator>, int32_t> create( ZipFileRO* zipFile, bool debuggable) { ZipFileRO* zipFile) { // Do not specify a suffix to find both .so files and gdbserver. auto result = zipFile->startIterationOrError(APK_LIB.data(), nullptr /* suffix */); if (!result.ok()) { Loading @@ -371,7 +369,7 @@ public: } return std::unique_ptr<NativeLibrariesIterator>( new NativeLibrariesIterator(zipFile, debuggable, result.value())); new NativeLibrariesIterator(zipFile, result.value())); } base::expected<ZipEntryRO, int32_t> next() { Loading @@ -390,7 +388,7 @@ public: continue; } const char* lastSlash = util::ValidLibraryPathLastSlash(fileName, false, mDebuggable); const char* lastSlash = util::ValidLibraryPathLastSlash(fileName, false); if (lastSlash) { mLastSlash = lastSlash; break; Loading @@ -415,20 +413,19 @@ private: char fileName[PATH_MAX]; ZipFileRO* const mZipFile; const bool mDebuggable; void* mCookie; const char* mLastSlash; }; static install_status_t iterateOverNativeFiles(JNIEnv *env, jlong apkHandle, jstring javaCpuAbi, jboolean debuggable, iterFunc callFunc, void* callArg) { iterFunc callFunc, void* callArg) { ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle); if (zipFile == nullptr) { return INSTALL_FAILED_INVALID_APK; } auto result = NativeLibrariesIterator::create(zipFile, debuggable); auto result = NativeLibrariesIterator::create(zipFile); if (!result.ok()) { return INSTALL_FAILED_INVALID_APK; } Loading Loading @@ -470,14 +467,13 @@ iterateOverNativeFiles(JNIEnv *env, jlong apkHandle, jstring javaCpuAbi, return INSTALL_SUCCEEDED; } static int findSupportedAbi(JNIEnv* env, jlong apkHandle, jobjectArray supportedAbisArray, jboolean debuggable) { static int findSupportedAbi(JNIEnv* env, jlong apkHandle, jobjectArray supportedAbisArray) { ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle); if (zipFile == nullptr) { return INSTALL_FAILED_INVALID_APK; } auto result = NativeLibrariesIterator::create(zipFile, debuggable); auto result = NativeLibrariesIterator::create(zipFile); if (!result.ok()) { return INSTALL_FAILED_INVALID_APK; } Loading Loading @@ -548,26 +544,26 @@ com_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, { jboolean app_compat_16kb = app_compat_16kb_enabled(); void* args[] = { &javaNativeLibPath, &extractNativeLibs, &debuggable, &app_compat_16kb }; return (jint) iterateOverNativeFiles(env, apkHandle, javaCpuAbi, debuggable, return (jint) iterateOverNativeFiles(env, apkHandle, javaCpuAbi, copyFileIfChanged, reinterpret_cast<void*>(args)); } static jlong com_android_internal_content_NativeLibraryHelper_sumNativeBinaries(JNIEnv *env, jclass clazz, jlong apkHandle, jstring javaCpuAbi, jboolean debuggable) jlong apkHandle, jstring javaCpuAbi) { size_t totalSize = 0; iterateOverNativeFiles(env, apkHandle, javaCpuAbi, debuggable, sumFiles, &totalSize); iterateOverNativeFiles(env, apkHandle, javaCpuAbi, sumFiles, &totalSize); return totalSize; } static jint com_android_internal_content_NativeLibraryHelper_findSupportedAbi(JNIEnv *env, jclass clazz, jlong apkHandle, jobjectArray javaCpuAbisToSearch, jboolean debuggable) jlong apkHandle, jobjectArray javaCpuAbisToSearch) { return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch, debuggable); return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch); } enum bitcode_scan_result_t { Loading Loading @@ -748,7 +744,7 @@ static jint com_android_internal_content_NativeLibraryHelper_checkApkAlignment( return PAGE_SIZE_APP_COMPAT_FLAG_ERROR; } auto result = NativeLibrariesIterator::create(zipFile, debuggable); auto result = NativeLibrariesIterator::create(zipFile); if (!result.ok()) { ALOGE("Can't iterate over native libs for file:%s", zipFile->getZipFileName()); return PAGE_SIZE_APP_COMPAT_FLAG_ERROR; Loading Loading @@ -810,9 +806,9 @@ static const JNINativeMethod gMethods[] = { {"nativeClose", "(J)V", (void*)com_android_internal_content_NativeLibraryHelper_close}, {"nativeCopyNativeBinaries", "(JLjava/lang/String;Ljava/lang/String;ZZ)I", (void*)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries}, {"nativeSumNativeBinaries", "(JLjava/lang/String;Z)J", {"nativeSumNativeBinaries", "(JLjava/lang/String;)J", (void*)com_android_internal_content_NativeLibraryHelper_sumNativeBinaries}, {"nativeFindSupportedAbi", "(J[Ljava/lang/String;Z)I", {"nativeFindSupportedAbi", "(J[Ljava/lang/String;)I", (void*)com_android_internal_content_NativeLibraryHelper_findSupportedAbi}, {"hasRenderscriptBitcode", "(J)I", (void*)com_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode}, Loading libs/androidfw/ApkParsing.cpp +1 −9 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ const size_t LIB_SUFFIX_LEN = LIB_SUFFIX.size(); static const std::array<std::string_view, 2> abis = {"arm64-v8a", "x86_64"}; namespace android::util { const char* ValidLibraryPathLastSlash(const char* fileName, bool suppress64Bit, bool debuggable) { const char* ValidLibraryPathLastSlash(const char* fileName, bool suppress64Bit) { // Make sure the filename is at least to the minimum library name size. const size_t fileNameLen = strlen(fileName); static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN; Loading Loading @@ -66,14 +66,6 @@ const char* ValidLibraryPathLastSlash(const char* fileName, bool suppress64Bit, return nullptr; } if (!debuggable) { // Make sure the filename starts with lib and ends with ".so". if (strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX.data(), LIB_SUFFIX_LEN) != 0 || strncmp(lastSlash, LIB_PREFIX.data(), LIB_PREFIX_LEN) != 0) { return nullptr; } } // Don't include 64 bit versions if they are suppressed if (suppress64Bit && std::find(abis.begin(), abis.end(), std::string_view( fileName + APK_LIB_LEN, lastSlash - fileName - APK_LIB_LEN)) != abis.end()) { Loading libs/androidfw/include/androidfw/ApkParsing.h +1 −1 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ extern const size_t APK_LIB_LEN; namespace android::util { // Checks if filename is a valid library path and returns a pointer to the last slash in the path // if it is, nullptr otherwise const char* ValidLibraryPathLastSlash(const char* filename, bool suppress64Bit, bool debuggable); const char* ValidLibraryPathLastSlash(const char* filename, bool suppress64Bit); // Equivalent to android.os.FileUtils.isFilenameSafe bool isFilenameSafe(const char* filename); Loading libs/androidfw/tests/ApkParsing_test.cpp +7 −19 Original line number Diff line number Diff line Loading @@ -27,57 +27,45 @@ using ::testing::NotNull; namespace android { TEST(ApkParsingTest, ValidArm64Path) { const char* path = "lib/arm64-v8a/library.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); auto lastSlash = util::ValidLibraryPathLastSlash(path, false); ASSERT_THAT(lastSlash, NotNull()); ASSERT_THAT(lastSlash, Eq(path + 13)); } TEST(ApkParsingTest, ValidArm64PathButSuppressed) { const char* path = "lib/arm64-v8a/library.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, true, false); auto lastSlash = util::ValidLibraryPathLastSlash(path, true); ASSERT_THAT(lastSlash, IsNull()); } TEST(ApkParsingTest, ValidArm32Path) { const char* path = "lib/armeabi-v7a/library.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); auto lastSlash = util::ValidLibraryPathLastSlash(path, false); ASSERT_THAT(lastSlash, NotNull()); ASSERT_THAT(lastSlash, Eq(path + 15)); } TEST(ApkParsingTest, InvalidMustStartWithLib) { const char* path = "lib/arm64-v8a/random.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); ASSERT_THAT(lastSlash, IsNull()); } TEST(ApkParsingTest, InvalidMustEndInSo) { const char* path = "lib/arm64-v8a/library.txt"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); ASSERT_THAT(lastSlash, IsNull()); } TEST(ApkParsingTest, InvalidCharacter) { const char* path = "lib/arm64-v8a/lib#.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); auto lastSlash = util::ValidLibraryPathLastSlash(path, false); ASSERT_THAT(lastSlash, IsNull()); } TEST(ApkParsingTest, InvalidSubdirectories) { const char* path = "lib/arm64-v8a/anything/library.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); auto lastSlash = util::ValidLibraryPathLastSlash(path, false); ASSERT_THAT(lastSlash, IsNull()); } TEST(ApkParsingTest, InvalidFileAtRoot) { const char* path = "lib/library.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); auto lastSlash = util::ValidLibraryPathLastSlash(path, false); ASSERT_THAT(lastSlash, IsNull()); } TEST(ApkParsingTest, InvalidPrefix) { const char* path = "assets/libhello.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); auto lastSlash = util::ValidLibraryPathLastSlash(path, false); ASSERT_THAT(lastSlash, IsNull()); } } No newline at end of file Loading
core/java/com/android/internal/content/NativeLibraryHelper.java +4 −6 Original line number Diff line number Diff line Loading @@ -172,8 +172,7 @@ public class NativeLibraryHelper { private static native long nativeOpenApkFd(FileDescriptor fd, String debugPath); private static native void nativeClose(long handle); private static native long nativeSumNativeBinaries(long handle, String cpuAbi, boolean debuggable); private static native long nativeSumNativeBinaries(long handle, String cpuAbi); private native static int nativeCopyNativeBinaries(long handle, String sharedLibraryPath, String abiToCopy, boolean extractNativeLibs, boolean debuggable); Loading @@ -188,7 +187,7 @@ public class NativeLibraryHelper { private static long sumNativeBinaries(Handle handle, String abi) { long sum = 0; for (long apkHandle : handle.apkHandles) { sum += nativeSumNativeBinaries(apkHandle, abi, handle.debuggable); sum += nativeSumNativeBinaries(apkHandle, abi); } return sum; } Loading Loading @@ -222,7 +221,7 @@ public class NativeLibraryHelper { public static int findSupportedAbi(Handle handle, String[] supportedAbis) { int finalRes = NO_NATIVE_LIBRARIES; for (long apkHandle : handle.apkHandles) { final int res = nativeFindSupportedAbi(apkHandle, supportedAbis, handle.debuggable); final int res = nativeFindSupportedAbi(apkHandle, supportedAbis); if (res == NO_NATIVE_LIBRARIES) { // No native code, keep looking through all APKs. } else if (res == INSTALL_FAILED_NO_MATCHING_ABIS) { Loading @@ -244,8 +243,7 @@ public class NativeLibraryHelper { return finalRes; } private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis, boolean debuggable); private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis); // Convenience method to call removeNativeBinariesFromDirLI(File) public static void removeNativeBinariesLI(String nativeLibraryPath) { Loading
core/jni/com_android_internal_content_NativeLibraryHelper.cpp +17 −21 Original line number Diff line number Diff line Loading @@ -349,21 +349,19 @@ static install_status_t copyFileIfChanged(JNIEnv* env, void* arg, ZipFileRO* zip * satisfied : * * - The entry is under the lib/ directory. * - The entry name ends with ".so" and the entry name starts with "lib", * an exception is made for debuggable apps. * - The entry filename is "safe" (as determined by isFilenameSafe). * */ class NativeLibrariesIterator { private: NativeLibrariesIterator(ZipFileRO* zipFile, bool debuggable, void* cookie) : mZipFile(zipFile), mDebuggable(debuggable), mCookie(cookie), mLastSlash(nullptr) { NativeLibrariesIterator(ZipFileRO* zipFile, void* cookie) : mZipFile(zipFile), mCookie(cookie), mLastSlash(nullptr) { fileName[0] = '\0'; } public: static base::expected<std::unique_ptr<NativeLibrariesIterator>, int32_t> create( ZipFileRO* zipFile, bool debuggable) { ZipFileRO* zipFile) { // Do not specify a suffix to find both .so files and gdbserver. auto result = zipFile->startIterationOrError(APK_LIB.data(), nullptr /* suffix */); if (!result.ok()) { Loading @@ -371,7 +369,7 @@ public: } return std::unique_ptr<NativeLibrariesIterator>( new NativeLibrariesIterator(zipFile, debuggable, result.value())); new NativeLibrariesIterator(zipFile, result.value())); } base::expected<ZipEntryRO, int32_t> next() { Loading @@ -390,7 +388,7 @@ public: continue; } const char* lastSlash = util::ValidLibraryPathLastSlash(fileName, false, mDebuggable); const char* lastSlash = util::ValidLibraryPathLastSlash(fileName, false); if (lastSlash) { mLastSlash = lastSlash; break; Loading @@ -415,20 +413,19 @@ private: char fileName[PATH_MAX]; ZipFileRO* const mZipFile; const bool mDebuggable; void* mCookie; const char* mLastSlash; }; static install_status_t iterateOverNativeFiles(JNIEnv *env, jlong apkHandle, jstring javaCpuAbi, jboolean debuggable, iterFunc callFunc, void* callArg) { iterFunc callFunc, void* callArg) { ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle); if (zipFile == nullptr) { return INSTALL_FAILED_INVALID_APK; } auto result = NativeLibrariesIterator::create(zipFile, debuggable); auto result = NativeLibrariesIterator::create(zipFile); if (!result.ok()) { return INSTALL_FAILED_INVALID_APK; } Loading Loading @@ -470,14 +467,13 @@ iterateOverNativeFiles(JNIEnv *env, jlong apkHandle, jstring javaCpuAbi, return INSTALL_SUCCEEDED; } static int findSupportedAbi(JNIEnv* env, jlong apkHandle, jobjectArray supportedAbisArray, jboolean debuggable) { static int findSupportedAbi(JNIEnv* env, jlong apkHandle, jobjectArray supportedAbisArray) { ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle); if (zipFile == nullptr) { return INSTALL_FAILED_INVALID_APK; } auto result = NativeLibrariesIterator::create(zipFile, debuggable); auto result = NativeLibrariesIterator::create(zipFile); if (!result.ok()) { return INSTALL_FAILED_INVALID_APK; } Loading Loading @@ -548,26 +544,26 @@ com_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, { jboolean app_compat_16kb = app_compat_16kb_enabled(); void* args[] = { &javaNativeLibPath, &extractNativeLibs, &debuggable, &app_compat_16kb }; return (jint) iterateOverNativeFiles(env, apkHandle, javaCpuAbi, debuggable, return (jint) iterateOverNativeFiles(env, apkHandle, javaCpuAbi, copyFileIfChanged, reinterpret_cast<void*>(args)); } static jlong com_android_internal_content_NativeLibraryHelper_sumNativeBinaries(JNIEnv *env, jclass clazz, jlong apkHandle, jstring javaCpuAbi, jboolean debuggable) jlong apkHandle, jstring javaCpuAbi) { size_t totalSize = 0; iterateOverNativeFiles(env, apkHandle, javaCpuAbi, debuggable, sumFiles, &totalSize); iterateOverNativeFiles(env, apkHandle, javaCpuAbi, sumFiles, &totalSize); return totalSize; } static jint com_android_internal_content_NativeLibraryHelper_findSupportedAbi(JNIEnv *env, jclass clazz, jlong apkHandle, jobjectArray javaCpuAbisToSearch, jboolean debuggable) jlong apkHandle, jobjectArray javaCpuAbisToSearch) { return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch, debuggable); return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch); } enum bitcode_scan_result_t { Loading Loading @@ -748,7 +744,7 @@ static jint com_android_internal_content_NativeLibraryHelper_checkApkAlignment( return PAGE_SIZE_APP_COMPAT_FLAG_ERROR; } auto result = NativeLibrariesIterator::create(zipFile, debuggable); auto result = NativeLibrariesIterator::create(zipFile); if (!result.ok()) { ALOGE("Can't iterate over native libs for file:%s", zipFile->getZipFileName()); return PAGE_SIZE_APP_COMPAT_FLAG_ERROR; Loading Loading @@ -810,9 +806,9 @@ static const JNINativeMethod gMethods[] = { {"nativeClose", "(J)V", (void*)com_android_internal_content_NativeLibraryHelper_close}, {"nativeCopyNativeBinaries", "(JLjava/lang/String;Ljava/lang/String;ZZ)I", (void*)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries}, {"nativeSumNativeBinaries", "(JLjava/lang/String;Z)J", {"nativeSumNativeBinaries", "(JLjava/lang/String;)J", (void*)com_android_internal_content_NativeLibraryHelper_sumNativeBinaries}, {"nativeFindSupportedAbi", "(J[Ljava/lang/String;Z)I", {"nativeFindSupportedAbi", "(J[Ljava/lang/String;)I", (void*)com_android_internal_content_NativeLibraryHelper_findSupportedAbi}, {"hasRenderscriptBitcode", "(J)I", (void*)com_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode}, Loading
libs/androidfw/ApkParsing.cpp +1 −9 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ const size_t LIB_SUFFIX_LEN = LIB_SUFFIX.size(); static const std::array<std::string_view, 2> abis = {"arm64-v8a", "x86_64"}; namespace android::util { const char* ValidLibraryPathLastSlash(const char* fileName, bool suppress64Bit, bool debuggable) { const char* ValidLibraryPathLastSlash(const char* fileName, bool suppress64Bit) { // Make sure the filename is at least to the minimum library name size. const size_t fileNameLen = strlen(fileName); static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN; Loading Loading @@ -66,14 +66,6 @@ const char* ValidLibraryPathLastSlash(const char* fileName, bool suppress64Bit, return nullptr; } if (!debuggable) { // Make sure the filename starts with lib and ends with ".so". if (strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX.data(), LIB_SUFFIX_LEN) != 0 || strncmp(lastSlash, LIB_PREFIX.data(), LIB_PREFIX_LEN) != 0) { return nullptr; } } // Don't include 64 bit versions if they are suppressed if (suppress64Bit && std::find(abis.begin(), abis.end(), std::string_view( fileName + APK_LIB_LEN, lastSlash - fileName - APK_LIB_LEN)) != abis.end()) { Loading
libs/androidfw/include/androidfw/ApkParsing.h +1 −1 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ extern const size_t APK_LIB_LEN; namespace android::util { // Checks if filename is a valid library path and returns a pointer to the last slash in the path // if it is, nullptr otherwise const char* ValidLibraryPathLastSlash(const char* filename, bool suppress64Bit, bool debuggable); const char* ValidLibraryPathLastSlash(const char* filename, bool suppress64Bit); // Equivalent to android.os.FileUtils.isFilenameSafe bool isFilenameSafe(const char* filename); Loading
libs/androidfw/tests/ApkParsing_test.cpp +7 −19 Original line number Diff line number Diff line Loading @@ -27,57 +27,45 @@ using ::testing::NotNull; namespace android { TEST(ApkParsingTest, ValidArm64Path) { const char* path = "lib/arm64-v8a/library.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); auto lastSlash = util::ValidLibraryPathLastSlash(path, false); ASSERT_THAT(lastSlash, NotNull()); ASSERT_THAT(lastSlash, Eq(path + 13)); } TEST(ApkParsingTest, ValidArm64PathButSuppressed) { const char* path = "lib/arm64-v8a/library.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, true, false); auto lastSlash = util::ValidLibraryPathLastSlash(path, true); ASSERT_THAT(lastSlash, IsNull()); } TEST(ApkParsingTest, ValidArm32Path) { const char* path = "lib/armeabi-v7a/library.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); auto lastSlash = util::ValidLibraryPathLastSlash(path, false); ASSERT_THAT(lastSlash, NotNull()); ASSERT_THAT(lastSlash, Eq(path + 15)); } TEST(ApkParsingTest, InvalidMustStartWithLib) { const char* path = "lib/arm64-v8a/random.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); ASSERT_THAT(lastSlash, IsNull()); } TEST(ApkParsingTest, InvalidMustEndInSo) { const char* path = "lib/arm64-v8a/library.txt"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); ASSERT_THAT(lastSlash, IsNull()); } TEST(ApkParsingTest, InvalidCharacter) { const char* path = "lib/arm64-v8a/lib#.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); auto lastSlash = util::ValidLibraryPathLastSlash(path, false); ASSERT_THAT(lastSlash, IsNull()); } TEST(ApkParsingTest, InvalidSubdirectories) { const char* path = "lib/arm64-v8a/anything/library.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); auto lastSlash = util::ValidLibraryPathLastSlash(path, false); ASSERT_THAT(lastSlash, IsNull()); } TEST(ApkParsingTest, InvalidFileAtRoot) { const char* path = "lib/library.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); auto lastSlash = util::ValidLibraryPathLastSlash(path, false); ASSERT_THAT(lastSlash, IsNull()); } TEST(ApkParsingTest, InvalidPrefix) { const char* path = "assets/libhello.so"; auto lastSlash = util::ValidLibraryPathLastSlash(path, false, false); auto lastSlash = util::ValidLibraryPathLastSlash(path, false); ASSERT_THAT(lastSlash, IsNull()); } } No newline at end of file