diff options
| -rw-r--r-- | cmds/installd/tests/installd_utils_test.cpp | 18 | ||||
| -rw-r--r-- | cmds/installd/utils.cpp | 66 |
2 files changed, 49 insertions, 35 deletions
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp index 947cc0db3f..28402125ce 100644 --- a/cmds/installd/tests/installd_utils_test.cpp +++ b/cmds/installd/tests/installd_utils_test.cpp @@ -317,6 +317,7 @@ TEST_F(UtilsTest, CreatePkgPath_LongPkgNameSuccess) { size_t pkgnameSize = PKG_NAME_MAX; char pkgname[pkgnameSize + 1]; memset(pkgname, 'a', pkgnameSize); + pkgname[1] = '.'; pkgname[pkgnameSize] = '\0'; EXPECT_EQ(0, create_pkg_path(path, pkgname, "", 0)) @@ -508,5 +509,22 @@ TEST_F(UtilsTest, CreateDataUserPackagePath) { create_data_user_ce_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example")); } +TEST_F(UtilsTest, IsValidPackageName) { + EXPECT_EQ(true, is_valid_package_name("com.example")); + EXPECT_EQ(true, is_valid_package_name("com.example-1")); + EXPECT_EQ(true, is_valid_package_name("com.example-1024")); + EXPECT_EQ(true, is_valid_package_name("com.example.foo---KiJFj4a_tePVw95pSrjg==")); + EXPECT_EQ(true, is_valid_package_name("really_LONG.a1234.package_name")); + + EXPECT_EQ(false, is_valid_package_name("1234.package")); + EXPECT_EQ(false, is_valid_package_name("com.1234.package")); + EXPECT_EQ(false, is_valid_package_name("package")); + EXPECT_EQ(false, is_valid_package_name("")); + EXPECT_EQ(false, is_valid_package_name(".")); + EXPECT_EQ(false, is_valid_package_name("com.example/../com.evil/")); + EXPECT_EQ(false, is_valid_package_name("com.example-1/../com.evil/")); + EXPECT_EQ(false, is_valid_package_name("/com.evil")); +} + } // namespace installd } // namespace android diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp index 7c40ef75f3..ba40041aee 100644 --- a/cmds/installd/utils.cpp +++ b/cmds/installd/utils.cpp @@ -346,46 +346,42 @@ int create_move_path(char path[PKG_PATH_MAX], * 0 on success. */ bool is_valid_package_name(const std::string& packageName) { - const char* pkgname = packageName.c_str(); - const char *x = pkgname; - int alpha = -1; - - if (strlen(pkgname) > PKG_NAME_MAX) { - return false; - } - - while (*x) { - if (isalnum(*x) || (*x == '_')) { - /* alphanumeric or underscore are fine */ - } else if (*x == '.') { - if ((x == pkgname) || (x[1] == '.') || (x[1] == 0)) { - /* periods must not be first, last, or doubled */ - ALOGE("invalid package name '%s'\n", pkgname); - return false; + // This logic is borrowed from PackageParser.java + bool hasSep = false; + bool front = true; + + auto it = packageName.begin(); + for (; it != packageName.end() && *it != '-'; it++) { + char c = *it; + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + front = false; + continue; + } + if (!front) { + if ((c >= '0' && c <= '9') || c == '_') { + continue; } - } else if (*x == '-') { - /* Suffix -X is fine to let versioning of packages. - But whatever follows should be alphanumeric.*/ - alpha = 1; - } else { - /* anything not A-Z, a-z, 0-9, _, or . is invalid */ - ALOGE("invalid package name '%s'\n", pkgname); - return false; } + if (c == '.') { + hasSep = true; + front = true; + continue; + } + LOG(WARNING) << "Bad package character " << c << " in " << packageName; + return false; + } - x++; + if (!hasSep || front) { + LOG(WARNING) << "Missing separator in " << packageName; + return false; } - if (alpha == 1) { - // Skip current character - x++; - while (*x) { - if (!isalnum(*x)) { - ALOGE("invalid package name '%s' should include only numbers after -\n", pkgname); - return false; - } - x++; - } + for (; it != packageName.end(); it++) { + char c = *it; + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) continue; + if ((c >= '0' && c <= '9') || c == '_' || c == '-' || c == '=') continue; + LOG(WARNING) << "Bad suffix character " << c << " in " << packageName; + return false; } return true; |