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

Commit 61a004c0 authored by Elliott Hughes's avatar Elliott Hughes Committed by Gerrit Code Review
Browse files

Merge "Fix more buffer overruns."

parents adc4a8b8 5830577b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ LIBADB_SRC_FILES := \
    adb_auth.cpp \
    adb_io.cpp \
    adb_listeners.cpp \
    adb_utils.cpp \
    sockets.cpp \
    transport.cpp \
    transport_local.cpp \
@@ -82,6 +83,7 @@ include $(BUILD_HOST_STATIC_LIBRARY)

LIBADB_TEST_SRCS := \
    adb_io_test.cpp \
    adb_utils_test.cpp \
    transport_test.cpp \

include $(CLEAR_VARS)

adb/adb_utils.cpp

0 → 100644
+43 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.
 */

#include "adb_utils.h"

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

bool directory_exists(const std::string& path) {
  struct stat sb;
  return lstat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode);
}

static bool should_escape(const char c) {
  return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
}

std::string escape_arg(const std::string& s) {
  // Preserve empty arguments.
  if (s.empty()) return "\"\"";

  std::string result(s);
  for (auto it = result.begin(); it != result.end(); ++it) {
      if (should_escape(*it)) {
          it = result.insert(it, '\\') + 1;
      }
  }
  return result;
}

adb/adb_utils.h

0 → 100644
+26 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.
 */

#ifndef _ADB_UTILS_H_
#define _ADB_UTILS_H_

#include <string>

bool directory_exists(const std::string& path);

std::string escape_arg(const std::string& s);

#endif

adb/adb_utils_test.cpp

0 → 100644
+52 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.
 */

#include "adb_utils.h"

#include <gtest/gtest.h>

TEST(adb_utils, directory_exists) {
  ASSERT_TRUE(directory_exists("/proc"));
  ASSERT_FALSE(directory_exists("/proc/self")); // Symbolic link.
  ASSERT_FALSE(directory_exists("/proc/does-not-exist"));
}

TEST(adb_utils, escape_arg) {
  ASSERT_EQ(R"("")", escape_arg(""));

  ASSERT_EQ(R"(abc)", escape_arg("abc"));

  ASSERT_EQ(R"(\ abc)", escape_arg(" abc"));
  ASSERT_EQ(R"(\'abc)", escape_arg("'abc"));
  ASSERT_EQ(R"(\"abc)", escape_arg("\"abc"));
  ASSERT_EQ(R"(\\abc)", escape_arg("\\abc"));
  ASSERT_EQ(R"(\(abc)", escape_arg("(abc"));
  ASSERT_EQ(R"(\)abc)", escape_arg(")abc"));

  ASSERT_EQ(R"(abc\ abc)", escape_arg("abc abc"));
  ASSERT_EQ(R"(abc\'abc)", escape_arg("abc'abc"));
  ASSERT_EQ(R"(abc\"abc)", escape_arg("abc\"abc"));
  ASSERT_EQ(R"(abc\\abc)", escape_arg("abc\\abc"));
  ASSERT_EQ(R"(abc\(abc)", escape_arg("abc(abc"));
  ASSERT_EQ(R"(abc\)abc)", escape_arg("abc)abc"));

  ASSERT_EQ(R"(abc\ )", escape_arg("abc "));
  ASSERT_EQ(R"(abc\')", escape_arg("abc'"));
  ASSERT_EQ(R"(abc\")", escape_arg("abc\""));
  ASSERT_EQ(R"(abc\\)", escape_arg("abc\\"));
  ASSERT_EQ(R"(abc\()", escape_arg("abc("));
  ASSERT_EQ(R"(abc\))", escape_arg("abc)"));
}
+107 −217
Original line number Diff line number Diff line
@@ -44,49 +44,38 @@
#include "adb_auth.h"
#include "adb_client.h"
#include "adb_io.h"
#include "adb_utils.h"
#include "file_sync_service.h"

static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...);

int find_sync_dirs(const char *srcarg,
        char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
        char **oem_srcdir_out);
int install_app(transport_type transport, const char* serial, int argc,
static int install_app(transport_type transport, const char* serial, int argc,
                       const char** argv);
int install_multiple_app(transport_type transport, const char* serial, int argc,
static int install_multiple_app(transport_type transport, const char* serial, int argc,
                                const char** argv);
int uninstall_app(transport_type transport, const char* serial, int argc,
static int uninstall_app(transport_type transport, const char* serial, int argc,
                         const char** argv);

static const char *gProductOutPath = NULL;
static std::string gProductOutPath;
extern int gListenAll;

static char *product_file(const char *extra)
{
    if (gProductOutPath == NULL) {
static std::string product_file(const char *extra) {
    if (gProductOutPath.empty()) {
        fprintf(stderr, "adb: Product directory not specified; "
                "use -p or define ANDROID_PRODUCT_OUT\n");
        exit(1);
    }

    int n = strlen(gProductOutPath) + strlen(extra) + 2;
    char* x = reinterpret_cast<char*>(malloc(n));
    if (x == 0) {
        fprintf(stderr, "adb: Out of memory (product_file())\n");
        exit(1);
    }

    snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
    return x;
    return android::base::StringPrintf("%s%s%s",
                                       gProductOutPath.c_str(), OS_PATH_SEPARATOR_STR, extra);
}

void version(FILE * out) {
static void version(FILE* out) {
    fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
            ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
}

void help()
{
static void help() {
    version(stderr);

    fprintf(stderr,
@@ -246,8 +235,7 @@ void help()
        );
}

int usage()
{
static int usage() {
    help();
    return 1;
}
@@ -419,8 +407,7 @@ static void *stdin_read_thread(void *x)
    return 0;
}

int interactive_shell(void)
{
static int interactive_shell() {
    adb_thread_t thr;
    int fdi, fd;

@@ -458,7 +445,7 @@ static void format_host_command(char* buffer, size_t buflen, const char* comman
    }
}

int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
static int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
                               unsigned progress)
{
    char buf[4096];
@@ -517,23 +504,6 @@ int adb_download_buffer(const char *service, const char *fn, const void* data, i
    return 0;
}


int adb_download(const char *service, const char *fn, unsigned progress)
{
    void *data;
    unsigned sz;

    data = load_file(fn, &sz);
    if(data == 0) {
        fprintf(stderr,"* cannot read '%s' *\n", fn);
        return -1;
    }

    int status = adb_download_buffer(service, fn, data, sz, progress);
    free(data);
    return status;
}

#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)

/*
@@ -555,7 +525,7 @@ int adb_download(const char *service, const char *fn, unsigned progress)
 * - When the other side sends "DONEDONE" instead of a block number,
 *   we hang up.
 */
int adb_sideload_host(const char* fn) {
static int adb_sideload_host(const char* fn) {
    unsigned sz;
    size_t xfer = 0;
    int status;
@@ -686,24 +656,6 @@ static void status_window(transport_type ttype, const char* serial)
    }
}

static int should_escape(const char c)
{
    return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
}

static std::string escape_arg(const std::string& s) {
    // Preserve empty arguments.
    if (s.empty()) return "\"\"";

    std::string result(s);
    for (auto it = result.begin(); it != result.end(); ++it) {
        if (should_escape(*it)) {
            it = result.insert(it, '\\') + 1;
        }
    }
    return result;
}

/**
 * Run ppp in "notty" mode against a resource listed as the first parameter
 * eg:
@@ -711,8 +663,7 @@ static std::string escape_arg(const std::string& s) {
 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
 *
 */
int ppp(int argc, const char **argv)
{
static int ppp(int argc, const char** argv) {
#if defined(_WIN32)
    fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
    return -1;
@@ -1004,62 +955,52 @@ TODO: debug? sooner-debug, sooner:debug?
 * Given <hint>, try to construct an absolute path to the
 * ANDROID_PRODUCT_OUT dir.
 */
static const char *find_product_out_path(const char *hint)
{
    static char path_buf[PATH_MAX];

static std::string find_product_out_path(const char* hint) {
    if (hint == NULL || hint[0] == '\0') {
        return NULL;
        return "";
    }

    /* If it's already absolute, don't bother doing any work.
     */
    // If it's already absolute, don't bother doing any work.
    if (adb_is_absolute_host_path(hint)) {
        strcpy(path_buf, hint);
        return path_buf;
        return hint;
    }

    /* If there are any slashes in it, assume it's a relative path;
     * make it absolute.
     */
    // If there are any slashes in it, assume it's a relative path;
    // make it absolute.
    if (adb_dirstart(hint) != NULL) {
        if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
        char cwd[PATH_MAX];
        if (getcwd(cwd, sizeof(cwd)) == NULL) {
            fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
            return NULL;
            return "";
        }
        if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
            fprintf(stderr, "adb: Couldn't assemble path\n");
            return NULL;
        }
        strcat(path_buf, OS_PATH_SEPARATOR_STR);
        strcat(path_buf, hint);
        return path_buf;
        return android::base::StringPrintf("%s%s%s", cwd, OS_PATH_SEPARATOR_STR, hint);
    }

    /* It's a string without any slashes.  Try to do something with it.
     *
     * Try to find the root of the build tree, and build a PRODUCT_OUT
     * path from there.
     */
    // It's a string without any slashes.  Try to do something with it.
    //
    // Try to find the root of the build tree, and build a PRODUCT_OUT
    // path from there.
    char top_buf[PATH_MAX];
    const char* top = find_top(top_buf);
    if (top == NULL) {
    if (top == nullptr) {
        fprintf(stderr, "adb: Couldn't find top of build tree\n");
        return "";
    }
    std::string path = top_buf;
    path += OS_PATH_SEPARATOR_STR;
    path += "out";
    path += OS_PATH_SEPARATOR_STR;
    path += "target";
    path += OS_PATH_SEPARATOR_STR;
    path += "product";
    path += OS_PATH_SEPARATOR_STR;
    path += hint;
    if (!directory_exists(path)) {
        fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
                        "\"%s\" doesn't exist\n", hint, path.c_str());
        return NULL;
    }
//TODO: if we have a way to indicate debug, look in out/debug/target/...
    snprintf(path_buf, sizeof(path_buf),
            "%s" OS_PATH_SEPARATOR_STR
            "out" OS_PATH_SEPARATOR_STR
            "target" OS_PATH_SEPARATOR_STR
            "product" OS_PATH_SEPARATOR_STR
            "%s", top_buf, hint);
    if (access(path_buf, F_OK) < 0) {
        fprintf(stderr, "adb: Couldn't find a product dir "
                "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
        return NULL;
    }
    return path_buf;
    return path;
}

static void parse_push_pull_args(const char **arg, int narg, char const **path1,
@@ -1114,15 +1055,14 @@ int adb_commandline(int argc, const char **argv)
    const char* serial = NULL;
    const char* server_port_str = NULL;

        /* If defined, this should be an absolute path to
         * the directory containing all of the various system images
         * for a particular product.  If not defined, and the adb
         * command requires this information, then the user must
         * specify the path using "-p".
         */
    gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
    if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
        gProductOutPath = NULL;
    // If defined, this should be an absolute path to
    // the directory containing all of the various system images
    // for a particular product.  If not defined, and the adb
    // command requires this information, then the user must
    // specify the path using "-p".
    char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
    if (ANDROID_PRODUCT_OUT != nullptr) {
        gProductOutPath = ANDROID_PRODUCT_OUT;
    }
    // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint

@@ -1163,9 +1103,8 @@ int adb_commandline(int argc, const char **argv)
                product = argv[0] + 2;
            }
            gProductOutPath = find_product_out_path(product);
            if (gProductOutPath == NULL) {
                fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
                        product);
            if (gProductOutPath.empty()) {
                fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
                return usage();
            }
        } else if (argv[0][0]=='-' && argv[0][1]=='s') {
@@ -1596,46 +1535,55 @@ int adb_commandline(int argc, const char **argv)
        return uninstall_app(ttype, serial, argc, argv);
    }
    else if (!strcmp(argv[0], "sync")) {
        const char* srcarg;
        char *system_srcpath, *data_srcpath, *vendor_srcpath, *oem_srcpath;

        int listonly = 0;

        int ret;
        std::string src_arg;
        bool list_only = false;
        if (argc < 2) {
            /* No local path was specified. */
            srcarg = NULL;
            // No local path was specified.
            src_arg = "";
        } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
            listonly = 1;
            list_only = 1;
            if (argc == 3) {
                srcarg = argv[2];
                src_arg = argv[2];
            } else {
                srcarg = NULL;
                src_arg = "";
            }
        } else if (argc == 2) {
            /* A local path or "android"/"data" arg was specified. */
            srcarg = argv[1];
            // A local path or "android"/"data" arg was specified.
            src_arg = argv[1];
        } else {
            return usage();
        }
        ret = find_sync_dirs(srcarg, &system_srcpath, &data_srcpath, &vendor_srcpath,
                &oem_srcpath);
        if (ret != 0) return usage();

        if (system_srcpath != NULL)
            ret = do_sync_sync(system_srcpath, "/system", listonly);
        if (ret == 0 && vendor_srcpath != NULL)
            ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
        if(ret == 0 && oem_srcpath != NULL)
            ret = do_sync_sync(oem_srcpath, "/oem", listonly);
        if (ret == 0 && data_srcpath != NULL)
            ret = do_sync_sync(data_srcpath, "/data", listonly);

        free(system_srcpath);
        free(vendor_srcpath);
        free(oem_srcpath);
        free(data_srcpath);
        return ret;

        if (src_arg != "" &&
            src_arg != "system" && src_arg != "data" && src_arg != "vendor" && src_arg != "oem") {
            return usage();
        }

        std::string system_src_path = product_file("system");
        std::string data_src_path = product_file("data");
        std::string vendor_src_path = product_file("vendor");
        std::string oem_src_path = product_file("oem");
        if (!directory_exists(vendor_src_path)) {
            vendor_src_path = "";
        }
        if (!directory_exists(oem_src_path)) {
            oem_src_path = "";
        }

        int rc = 0;
        if (rc == 0 && (src_arg.empty() || src_arg == "system")) {
            rc = do_sync_sync(system_src_path.c_str(), "/system", list_only);
        }
        if (rc == 0 && (src_arg.empty() || src_arg == "vendor")) {
            rc = do_sync_sync(vendor_src_path.c_str(), "/vendor", list_only);
        }
        if(rc == 0 && (src_arg.empty() || src_arg == "oem")) {
            rc = do_sync_sync(oem_src_path.c_str(), "/oem", list_only);
        }
        if (rc == 0 && (src_arg.empty() || src_arg == "data")) {
            rc = do_sync_sync(data_src_path.c_str(), "/data", list_only);
        }
        return rc;
    }
    /* passthrough commands */
    else if (!strcmp(argv[0],"get-state") ||
@@ -1730,64 +1678,6 @@ static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...
    return adb_commandline(argc, argv);
}

int find_sync_dirs(const char *srcarg,
        char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
        char **oem_srcdir_out)
{
    char *system_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL, *oem_srcdir = NULL;
    struct stat st;

    if(srcarg == NULL) {
        system_srcdir = product_file("system");
        data_srcdir = product_file("data");
        vendor_srcdir = product_file("vendor");
        oem_srcdir = product_file("oem");
        // Check if vendor partition exists.
        if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
            vendor_srcdir = NULL;
        // Check if oem partition exists.
        if (lstat(oem_srcdir, &st) || !S_ISDIR(st.st_mode))
            oem_srcdir = NULL;
    } else {
        // srcarg may be "data", "system", "vendor", "oem" or NULL.
        // If srcarg is NULL, then all partitions are synced.
        if(strcmp(srcarg, "system") == 0) {
            system_srcdir = product_file("system");
        } else if(strcmp(srcarg, "data") == 0) {
            data_srcdir = product_file("data");
        } else if(strcmp(srcarg, "vendor") == 0) {
            vendor_srcdir = product_file("vendor");
        } else if(strcmp(srcarg, "oem") == 0) {
            oem_srcdir = product_file("oem");
        } else {
            // It's not "system", "data", "vendor", or "oem".
            return 1;
        }
    }

    if(system_srcdir_out != NULL)
        *system_srcdir_out = system_srcdir;
    else
        free(system_srcdir);

    if(vendor_srcdir_out != NULL)
        *vendor_srcdir_out = vendor_srcdir;
    else
        free(vendor_srcdir);

    if(oem_srcdir_out != NULL)
        *oem_srcdir_out = oem_srcdir;
    else
        free(oem_srcdir);

    if(data_srcdir_out != NULL)
        *data_srcdir_out = data_srcdir;
    else
        free(data_srcdir);

    return 0;
}

static int pm_command(transport_type transport, const char* serial,
                      int argc, const char** argv)
{
@@ -1802,7 +1692,7 @@ static int pm_command(transport_type transport, const char* serial,
    return 0;
}

int uninstall_app(transport_type transport, const char* serial, int argc,
static int uninstall_app(transport_type transport, const char* serial, int argc,
                         const char** argv)
{
    /* if the user choose the -k option, we refuse to do it until devices are
@@ -1839,7 +1729,7 @@ static const char* get_basename(const char* filename)
    }
}

int install_app(transport_type transport, const char* serial, int argc,
static int install_app(transport_type transport, const char* serial, int argc,
                       const char** argv)
{
    static const char *const DATA_DEST = "/data/local/tmp/%s";
@@ -1893,7 +1783,7 @@ cleanup_apk:
    return err;
}

int install_multiple_app(transport_type transport, const char* serial, int argc,
static int install_multiple_app(transport_type transport, const char* serial, int argc,
                                const char** argv)
{
    int i;
Loading