Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 367ace2f authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Update is_valid_package_name() to match framework.

The framework has a new format for /data/app directory names in OC
to protect user privacy.  This change updates the validation logic
in installd to support the new format.

For consistency the logic now mirrors the package name validation
logic used by PackageParser.

Test: /data/nativetest64/installd_utils_test/installd_utils_test
Bug: 33705143
Change-Id: I41d270942479c52e063c29a2cb9552d7b238b86e
parent 198cf8e5
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -321,6 +321,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))
@@ -512,5 +513,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
+31 −35
Original line number Diff line number Diff line
@@ -354,47 +354,43 @@ 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;
    // 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;
        }

    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;
        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);
        }
        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);
    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;
    }
            x++;
        }
    }

    return true;
}