More fixed-length buffer removal.

Bug: http://b/20666660
Change-Id: I0c738e9fed2defed48a9cf2d0a4f7b99c08dcf3d
(cherry picked from commit 6452a89aa8)
This commit is contained in:
Elliott Hughes 2015-04-29 12:28:13 -07:00
parent 0156589846
commit f1a58f8f33
6 changed files with 152 additions and 271 deletions

View file

@ -243,8 +243,6 @@ void install_local_socket(asocket *s);
void remove_socket(asocket *s);
void close_all_sockets(atransport *t);
#define LOCAL_CLIENT_PREFIX "emulator-"
asocket *create_local_socket(int fd);
asocket *create_local_service_socket(const char *destination);

View file

@ -32,6 +32,7 @@
#include <vector>
#include <base/stringprintf.h>
#include <base/strings.h>
#include "adb_io.h"
@ -41,6 +42,29 @@ static const char* __adb_serial = NULL;
static int __adb_server_port = DEFAULT_ADB_PORT;
static const char* __adb_server_name = NULL;
static std::string perror_str(const char* msg) {
return android::base::StringPrintf("%s: %s", msg, strerror(errno));
}
static bool ReadProtocolString(int fd, std::string* s, std::string* error) {
char buf[5];
if (!ReadFdExactly(fd, buf, 4)) {
*error = perror_str("protocol fault (couldn't read status length)");
return false;
}
buf[4] = 0;
unsigned long len = strtoul(buf, 0, 16);
s->resize(len + 1, '\0'); // Ensure NUL-termination.
if (!ReadFdExactly(fd, &(*s)[0], len)) {
*error = perror_str("protocol fault (couldn't read status message)");
return false;
}
return true;
}
void adb_set_transport(transport_type type, const char* serial)
{
__adb_transport = type;
@ -57,58 +81,36 @@ void adb_set_tcp_name(const char* hostname)
__adb_server_name = hostname;
}
int adb_get_emulator_console_port(void)
{
const char* serial = __adb_serial;
int port;
int adb_get_emulator_console_port() {
if (__adb_serial) {
// The user specified a serial number; is it an emulator?
int port;
return (sscanf(__adb_serial, "emulator-%d", &port) == 1) ? port : -1;
}
if (serial == NULL) {
/* if no specific device was specified, we need to look at */
/* the list of connected devices, and extract an emulator */
/* name from it. two emulators is an error */
std::string error;
char* tmp = adb_query("host:devices", &error);
char* p = tmp;
if (!tmp) {
printf("no emulator connected: %s\n", error.c_str());
return -1;
}
while (*p) {
char* q = strchr(p, '\n');
if (q != NULL)
*q++ = 0;
else
q = p + strlen(p);
// No specific device was given, so get the list of connected
// devices and search for emulators. If there's one, we'll
// take it. If there are more than one, that's an error.
std::string devices;
std::string error;
if (!adb_query("host:devices", &devices, &error)) {
printf("no emulator connected: %s\n", error.c_str());
return -1;
}
if (!memcmp(p, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1)) {
if (serial != NULL) { /* more than one emulator listed */
free(tmp);
return -2;
}
serial = p;
int port;
size_t emulator_count = 0;
for (auto& device : android::base::Split(devices, "\n")) {
if (sscanf(device.c_str(), "emulator-%d", &port) == 1) {
if (++emulator_count > 1) {
return -2;
}
p = q;
}
free(tmp);
if (serial == NULL)
return -1; /* no emulator found */
}
else {
if (memcmp(serial, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1) != 0)
return -1; /* not an emulator */
}
serial += sizeof(LOCAL_CLIENT_PREFIX)-1;
port = strtol(serial, NULL, 10);
if (emulator_count == 0) return -1;
return port;
}
std::string perror_str(const char* msg) {
return android::base::StringPrintf("%s: %s", msg, strerror(errno));
}
static int switch_socket_transport(int fd, std::string* error) {
std::string service;
if (__adb_serial) {
@ -170,47 +172,36 @@ bool adb_status(int fd, std::string* error) {
return false;
}
if (!ReadFdExactly(fd, buf, 4)) {
*error = perror_str("protocol fault (couldn't read status length)");
return false;
}
buf[4] = 0;
unsigned long len = strtoul(buf, 0, 16);
error->resize(len + 1, '\0'); // Ensure NUL-termination.
if (!ReadFdExactly(fd, &(*error)[0], len)) {
*error = perror_str("protocol fault (couldn't read status message)");
}
ReadProtocolString(fd, error, error);
return false;
}
int _adb_connect(const char *service, std::string* error) {
char tmp[5];
int fd;
D("_adb_connect: %s\n", service);
size_t len = strlen(service);
if ((len < 1) || (len > 1024)) {
*error = android::base::StringPrintf("service name too long (%d)", static_cast<int>(len));
int _adb_connect(const std::string& service, std::string* error) {
D("_adb_connect: %s\n", service.c_str());
if (service.empty() || service.size() > 1024) {
*error = android::base::StringPrintf("bad service name length (%d)",
static_cast<int>(service.size()));
return -1;
}
snprintf(tmp, sizeof tmp, "%04zx", len);
if (__adb_server_name)
int fd;
if (__adb_server_name) {
fd = socket_network_client(__adb_server_name, __adb_server_port, SOCK_STREAM);
else
} else {
fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
if(fd < 0) {
}
if (fd < 0) {
*error = perror_str("cannot connect to daemon");
return -2;
}
if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd, error)) {
if (memcmp(&service[0],"host",4) != 0 && switch_socket_transport(fd, error)) {
return -1;
}
if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service, len)) {
char tmp[5];
snprintf(tmp, sizeof(tmp), "%04zx", service.size());
if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, &service[0], service.size())) {
*error = perror_str("write failure during connection");
adb_close(fd);
return -1;
@ -225,11 +216,11 @@ int _adb_connect(const char *service, std::string* error) {
return fd;
}
int adb_connect(const char* service, std::string* error) {
int adb_connect(const std::string& service, std::string* error) {
// first query the adb server's version
int fd = _adb_connect("host:version", error);
D("adb_connect: service %s\n", service);
D("adb_connect: service %s\n", service.c_str());
if (fd == -2 && __adb_server_name) {
fprintf(stderr,"** Cannot start server on remote host\n");
return fd;
@ -248,21 +239,20 @@ int adb_connect(const char* service, std::string* error) {
// fall through to _adb_connect
} else {
// if server was running, check its version to make sure it is not out of date
char buf[100];
size_t n;
int version = ADB_SERVER_VERSION - 1;
// if we have a file descriptor, then parse version result
if (fd >= 0) {
if(!ReadFdExactly(fd, buf, 4)) goto error;
std::string version_string;
if (!ReadProtocolString(fd, &version_string, error)) {
goto error;
}
buf[4] = 0;
n = strtoul(buf, 0, 16);
if(n > sizeof(buf)) goto error;
if(!ReadFdExactly(fd, buf, n)) goto error;
adb_close(fd);
if (sscanf(buf, "%04x", &version) != 1) goto error;
if (sscanf(&version_string[0], "%04x", &version) != 1) {
goto error;
}
} else {
// if fd is -1, then check for "unknown host service",
// which would indicate a version of adb that does not support the version command
@ -271,7 +261,7 @@ int adb_connect(const char* service, std::string* error) {
}
}
if(version != ADB_SERVER_VERSION) {
if (version != ADB_SERVER_VERSION) {
printf("adb server is out of date. killing...\n");
fd = _adb_connect("host:kill", error);
adb_close(fd);
@ -283,7 +273,7 @@ int adb_connect(const char* service, std::string* error) {
}
// if the command is start-server, we are done.
if (!strcmp(service, "host:start-server")) {
if (service == "host:start-server") {
return 0;
}
@ -302,7 +292,7 @@ error:
}
int adb_command(const char* service, std::string* error) {
int adb_command(const std::string& service, std::string* error) {
int fd = adb_connect(service, error);
if (fd < 0) {
fprintf(stderr, "error: %s\n", error->c_str());
@ -317,39 +307,18 @@ int adb_command(const char* service, std::string* error) {
return 0;
}
char* adb_query(const char* service, std::string* error) {
char buf[5];
unsigned long n;
char* tmp;
D("adb_query: %s\n", service);
bool adb_query(const std::string& service, std::string* result, std::string* error) {
D("adb_query: %s\n", service.c_str());
int fd = adb_connect(service, error);
if (fd < 0) {
fprintf(stderr,"error: %s\n", error->c_str());
return 0;
}
if (!ReadFdExactly(fd, buf, 4)) goto oops;
buf[4] = 0;
n = strtoul(buf, 0, 16);
// TODO: given that we just read a 4-byte hex length 0x????, why the test?
if (n >= 0xffff) {
*error = "reply is too long (>= 64KiB)";
goto oops;
}
tmp = reinterpret_cast<char*>(malloc(n + 1));
if(tmp == 0) goto oops;
if(!ReadFdExactly(fd, tmp, n) == 0) {
tmp[n] = 0;
result->clear();
if (!ReadProtocolString(fd, result, error)) {
adb_close(fd);
return tmp;
return false;
}
free(tmp);
oops:
adb_close(fd);
return 0;
return true;
}

View file

@ -9,19 +9,17 @@
** a valid fd for interacting with that service upon success
** or a negative number on failure
*/
int adb_connect(const char* service, std::string* error);
int _adb_connect(const char* service, std::string* error);
int adb_connect(const std::string& service, std::string* error);
int _adb_connect(const std::string& service, std::string* error);
/* connect to adb, connect to the named service, return 0 if
** the connection succeeded AND the service returned OKAY
*/
int adb_command(const char* service, std::string* error);
int adb_command(const std::string& service, std::string* error);
/* connect to adb, connect to the named service, return
** a malloc'd string of its response upon success or NULL
** on failure.
*/
char* adb_query(const char* service, std::string* error);
// Connects to the named adb service and fills 'result' with the response.
// Returns true on success; returns false and fills 'error' on failure.
bool adb_query(const std::string& service, std::string* result, std::string* error);
/* Set the preferred transport to connect to.
*/

View file

@ -201,7 +201,6 @@ static void help() {
" adb get-state - prints: offline | bootloader | device\n"
" adb get-serialno - prints: <serial-number>\n"
" adb get-devpath - prints: <device-path>\n"
" adb status-window - continuously print device status for a specified device\n"
" adb remount - remounts the /system, /vendor (if present) and /oem (if present) partitions on the device read-write\n"
" adb reboot [bootloader|recovery]\n"
" - reboots the device, optionally into the bootloader or recovery program.\n"
@ -437,31 +436,25 @@ static int interactive_shell() {
}
static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
{
static std::string format_host_command(const char* command, transport_type type, const char* serial) {
if (serial) {
snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
} else {
const char* prefix = "host";
if (ttype == kTransportUsb)
prefix = "host-usb";
else if (ttype == kTransportLocal)
prefix = "host-local";
snprintf(buffer, buflen, "%s:%s", prefix, command);
return android::base::StringPrintf("host-serial:%s:%s", serial, command);
}
const char* prefix = "host";
if (type == kTransportUsb) {
prefix = "host-usb";
} else if (type == kTransportLocal) {
prefix = "host-local";
}
return android::base::StringPrintf("%s:%s", prefix, command);
}
static 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, unsigned sz,
bool show_progress)
{
char buf[4096];
unsigned total;
sprintf(buf,"%s:%d", service, sz);
std::string error;
int fd = adb_connect(buf, &error);
int fd = adb_connect(android::base::StringPrintf("%s:%d", service, sz), &error);
if (fd < 0) {
fprintf(stderr,"error: %s\n", error.c_str());
return -1;
@ -470,7 +463,7 @@ static int adb_download_buffer(const char *service, const char *fn, const void*
int opt = CHUNK_SIZE;
opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
total = sz;
unsigned total = sz;
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
if (show_progress) {
@ -478,7 +471,7 @@ static int adb_download_buffer(const char *service, const char *fn, const void*
if(x) service = x + 1;
}
while(sz > 0) {
while (sz > 0) {
unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
if (!WriteFdExactly(fd, ptr, xfer)) {
std::string error;
@ -497,6 +490,8 @@ static int adb_download_buffer(const char *service, const char *fn, const void*
printf("\n");
}
// TODO: should this be adb_status?
char buf[5];
if(!ReadFdExactly(fd, buf, 4)){
fprintf(stderr,"* error reading response *\n");
adb_close(fd);
@ -550,10 +545,10 @@ static int adb_sideload_host(const char* fn) {
return -1;
}
char buf[100];
sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
std::string service =
android::base::StringPrintf("sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
std::string error;
int fd = adb_connect(buf, &error);
int fd = adb_connect(service, &error);
if (fd < 0) {
// Try falling back to the older sideload method. Maybe this
// is an older device that doesn't support sideload-host.
@ -565,18 +560,19 @@ static int adb_sideload_host(const char* fn) {
opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
while (true) {
char buf[9];
if (!ReadFdExactly(fd, buf, 8)) {
fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
status = -1;
goto done;
}
buf[8] = '\0';
if (strncmp("DONEDONE", buf, 8) == 0) {
if (strcmp("DONEDONE", buf) == 0) {
status = 0;
break;
}
buf[8] = '\0';
int block = strtol(buf, NULL, 10);
size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
@ -622,51 +618,6 @@ static int adb_sideload_host(const char* fn) {
return status;
}
static void status_window(transport_type ttype, const char* serial)
{
char command[4096];
char *state = 0;
char *laststate = 0;
/* silence stderr */
#ifdef _WIN32
/* XXX: TODO */
#else
int fd;
fd = unix_open("/dev/null", O_WRONLY);
dup2(fd, 2);
adb_close(fd);
#endif
format_host_command(command, sizeof command, "get-state", ttype, serial);
while (true) {
adb_sleep_ms(250);
if (state) {
free(state);
state = 0;
}
std::string error;
state = adb_query(command, &error);
if (state) {
if (laststate && !strcmp(state,laststate)){
continue;
} else {
if (laststate) free(laststate);
laststate = strdup(state);
}
}
printf("%c[2J%c[2H", 27, 27);
printf("Android Debug Bridge\n");
printf("State: %s\n", state ? state : "offline");
fflush(stdout);
}
}
/**
* Run ppp in "notty" mode against a resource listed as the first parameter
* eg:
@ -741,7 +692,7 @@ static int send_shell_command(transport_type transport, const char* serial,
int fd;
while (true) {
std::string error;
fd = adb_connect(command.c_str(), &error);
fd = adb_connect(command, &error);
if (fd >= 0) {
break;
}
@ -835,7 +786,7 @@ static int backup(int argc, const char** argv) {
D("backup. filename=%s cmd=%s\n", filename, cmd.c_str());
std::string error;
int fd = adb_connect(cmd.c_str(), &error);
int fd = adb_connect(cmd, &error);
if (fd < 0) {
fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
adb_close(outFd);
@ -964,7 +915,7 @@ static void parse_push_pull_args(const char **arg, int narg, char const **path1,
}
}
static int adb_connect_command(const char* command) {
static int adb_connect_command(const std::string& command) {
std::string error;
int fd = adb_connect(command, &error);
if (fd != -1) {
@ -976,6 +927,17 @@ static int adb_connect_command(const char* command) {
return 1;
}
static int adb_query_command(const std::string& command) {
std::string result;
std::string error;
if (!adb_query(command, &result, &error)) {
fprintf(stderr, "error: %s\n", error.c_str());
return 1;
}
printf("%s\n", result.c_str());
return 0;
}
int adb_commandline(int argc, const char **argv)
{
char buf[4096];
@ -1129,10 +1091,9 @@ int adb_commandline(int argc, const char **argv)
}
}
format_host_command(buf, sizeof buf, service, ttype, serial);
std::string cmd = format_host_command(service, ttype, serial);
std::string error;
if (adb_command(buf, &error)) {
if (adb_command(cmd, &error)) {
D("failure: %s *\n", error.c_str());
fprintf(stderr,"error: %s\n", error.c_str());
return 1;
@ -1152,62 +1113,38 @@ int adb_commandline(int argc, const char **argv)
/* adb_connect() commands */
if (!strcmp(argv[0], "devices")) {
char *tmp;
const char *listopt;
if (argc < 2)
if (argc < 2) {
listopt = "";
else if (argc == 2 && !strcmp(argv[1], "-l"))
} else if (argc == 2 && !strcmp(argv[1], "-l")) {
listopt = argv[1];
else {
} else {
fprintf(stderr, "Usage: adb devices [-l]\n");
return 1;
}
snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
std::string error;
tmp = adb_query(buf, &error);
if (tmp) {
printf("List of devices attached \n");
printf("%s\n", tmp);
return 0;
} else {
return 1;
}
std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
printf("List of devices attached\n");
return adb_query_command(query);
}
else if (!strcmp(argv[0], "connect")) {
char *tmp;
if (argc != 2) {
fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
return 1;
}
snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
std::string error;
tmp = adb_query(buf, &error);
if (tmp) {
printf("%s\n", tmp);
return 0;
} else {
return 1;
}
std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
return adb_query_command(query);
}
else if (!strcmp(argv[0], "disconnect")) {
char *tmp;
if (argc > 2) {
fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
return 1;
}
if (argc == 2) {
snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
} else {
snprintf(buf, sizeof buf, "host:disconnect:");
}
std::string error;
tmp = adb_query(buf, &error);
if (tmp) {
printf("%s\n", tmp);
return 0;
} else {
return 1;
}
std::string query = android::base::StringPrintf("host:disconnect:%s",
(argc == 2) ? argv[1] : "");
return adb_query_command(query);
}
else if (!strcmp(argv[0], "emu")) {
return adb_send_emulator_command(argc, argv);
@ -1241,7 +1178,7 @@ int adb_commandline(int argc, const char **argv)
while (true) {
D("interactive shell loop. cmd=%s\n", cmd.c_str());
std::string error;
int fd = adb_connect(cmd.c_str(), &error);
int fd = adb_connect(cmd, &error);
int r;
if (fd >= 0) {
D("about to read_and_dump(fd=%d)\n", fd);
@ -1280,7 +1217,7 @@ int adb_commandline(int argc, const char **argv)
}
std::string error;
int fd = adb_connect(cmd.c_str(), &error);
int fd = adb_connect(cmd, &error);
if (fd < 0) {
fprintf(stderr, "error: %s\n", error.c_str());
return -1;
@ -1385,18 +1322,12 @@ int adb_commandline(int argc, const char **argv)
// Implement forward --list
if (list) {
if (argc != 1)
if (argc != 1) {
return usage();
snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
std::string error;
char* forwards = adb_query(buf, &error);
if (forwards == NULL) {
fprintf(stderr, "error: %s\n", error.c_str());
return 1;
}
printf("%s", forwards);
free(forwards);
return 0;
std::string query = android::base::StringPrintf("%s:list-forward", host_prefix);
return adb_query_command(query);
}
// Implement forward --remove-all
@ -1523,21 +1454,9 @@ int adb_commandline(int argc, const char **argv)
!strcmp(argv[0],"get-serialno") ||
!strcmp(argv[0],"get-devpath"))
{
format_host_command(buf, sizeof buf, argv[0], ttype, serial);
std::string error;
char* tmp = adb_query(buf, &error);
if (tmp) {
printf("%s\n", tmp);
return 0;
} else {
return 1;
}
return adb_query_command(format_host_command(argv[0], ttype, serial));
}
/* other commands */
else if (!strcmp(argv[0],"status-window")) {
status_window(ttype, serial);
return 0;
}
else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
return logcat(ttype, serial, argc, argv);
}
@ -1755,7 +1674,7 @@ static int install_multiple_app(transport_type transport, const char* serial, in
// Create install session
std::string error;
int fd = adb_connect(cmd.c_str(), &error);
int fd = adb_connect(cmd, &error);
if (fd < 0) {
fprintf(stderr, "Connect error for create: %s\n", error.c_str());
return -1;
@ -1807,7 +1726,7 @@ static int install_multiple_app(transport_type transport, const char* serial, in
}
std::string error;
int remoteFd = adb_connect(cmd.c_str(), &error);
int remoteFd = adb_connect(cmd, &error);
if (remoteFd < 0) {
fprintf(stderr, "Connect error for write: %s\n", error.c_str());
adb_close(localFd);
@ -1831,13 +1750,10 @@ static int install_multiple_app(transport_type transport, const char* serial, in
finalize_session:
// Commit session if we streamed everything okay; otherwise abandon
if (success) {
snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
} else {
snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
}
fd = adb_connect(buf, &error);
std::string service =
android::base::StringPrintf("exec:pm install-%s %d",
success ? "commit" : "abandon", session_id);
fd = adb_connect(service, &error);
if (fd < 0) {
fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
return -1;

View file

@ -847,7 +847,7 @@ retry:
result = t;
} else if (ttype == kTransportAny) {
if (result) {
if (error_out) *error_out = "more than one device and emulator";
if (error_out) *error_out = "more than one device/emulator";
ambiguous = 1;
result = NULL;
break;

View file

@ -105,7 +105,7 @@ int local_connect_arbitrary_ports(int console_port, int adb_port)
D("client: connected on remote on fd %d\n", fd);
close_on_exec(fd);
disable_tcp_nagle(fd);
snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, console_port);
snprintf(buf, sizeof buf, "emulator-%d", console_port);
register_socket_transport(fd, buf, adb_port, 1);
return 0;
}