summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/installd/tests/installd_utils_test.cpp18
-rw-r--r--cmds/installd/utils.cpp66
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;