Merge "Switch UniquePtr to std::unique_ptr."
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 532af45..c73d737 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -145,8 +145,8 @@
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()));
+ *error = android::base::StringPrintf("bad service name length (%zd)",
+ service.size());
return -1;
}
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 0ce5ece..604bd57 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -45,11 +45,16 @@
std::string escape_arg(const std::string& s) {
std::string result = s;
- // Insert a \ before any ' in the string.
- for (auto it = result.begin(); it != result.end(); ++it) {
- if (*it == '\'') {
- it = result.insert(it, '\\') + 1;
- }
+ // Escape any ' in the string (before we single-quote the whole thing).
+ // The correct way to do this for the shell is to replace ' with '\'' --- that is,
+ // close the existing single-quoted string, escape a single single-quote, and start
+ // a new single-quoted string. Like the C preprocessor, the shell will concatenate
+ // these pieces into one string.
+ for (size_t i = 0; i < s.size(); ++i) {
+ if (s[i] == '\'') {
+ result.insert(i, "'\\'");
+ i += 2;
+ }
}
// Prefix and suffix the whole string with '.
diff --git a/adb/adb_utils_test.cpp b/adb/adb_utils_test.cpp
index a395079..052aea5 100644
--- a/adb/adb_utils_test.cpp
+++ b/adb/adb_utils_test.cpp
@@ -30,21 +30,21 @@
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')", 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)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("));
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 468909a..f48182d 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -156,6 +156,10 @@
// TODO(danalbert): Why do we use stdout for Windows?
#if defined(_WIN32)
int reply_fd = STDOUT_FILENO;
+ // Change stdout mode to binary so \n => \r\n translation does not
+ // occur. In a moment stdout will be reopened to the daemon log file
+ // anyway.
+ _setmode(reply_fd, _O_BINARY);
#else
int reply_fd = STDERR_FILENO;
#endif
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 6caec6c..d7bee91 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -1593,11 +1593,7 @@
return 1;
}
-#if defined(_WIN32) // Remove when we're using clang for Win32.
- std::string cmd = android::base::StringPrintf("exec:pm install-create -S %u", (unsigned) total_size);
-#else
std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
-#endif
for (i = 1; i < first_apk; i++) {
cmd += " " + escape_arg(argv[i]);
}
@@ -1638,15 +1634,9 @@
goto finalize_session;
}
-#if defined(_WIN32) // Remove when we're using clang for Win32.
- std::string cmd = android::base::StringPrintf(
- "exec:pm install-write -S %u %d %d_%s -",
- (unsigned) sb.st_size, session_id, i, get_basename(file));
-#else
std::string cmd = android::base::StringPrintf(
"exec:pm install-write -S %" PRIu64 " %d %d_%s -",
static_cast<uint64_t>(sb.st_size), session_id, i, get_basename(file));
-#endif
int localFd = adb_open(file, O_RDONLY);
if (localFd < 0) {
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 2efc890..1dc711ae 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -16,6 +16,7 @@
#include <dirent.h>
#include <errno.h>
+#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
@@ -63,13 +64,12 @@
total_bytes, (t / 1000000LL), (t % 1000000LL) / 1000LL);
}
-static const char* transfer_progress_format = "\rTransferring: %llu/%llu (%d%%)";
-
-static void print_transfer_progress(unsigned long long bytes_current,
- unsigned long long bytes_total) {
+static void print_transfer_progress(uint64_t bytes_current,
+ uint64_t bytes_total) {
if (bytes_total == 0) return;
- fprintf(stderr, transfer_progress_format, bytes_current, bytes_total,
+ fprintf(stderr, "\rTransferring: %" PRIu64 "/%" PRIu64 " (%d%%)",
+ bytes_current, bytes_total,
(int) (bytes_current * 100 / bytes_total));
if (bytes_current == bytes_total) {
diff --git a/adb/tests/test_adb.py b/adb/tests/test_adb.py
index 237ef47..0ff87d2 100755
--- a/adb/tests/test_adb.py
+++ b/adb/tests/test_adb.py
@@ -6,6 +6,7 @@
"""
import hashlib
import os
+import pipes
import random
import re
import shlex
@@ -162,6 +163,9 @@
def shell_nocheck(self, cmd):
return call_combined(self.adb_cmd + "shell " + cmd)
+ def install(self, filename):
+ return call_checked(self.adb_cmd + "install {}".format(pipes.quote(filename)))
+
def push(self, local, remote):
return call_checked(self.adb_cmd + "push {} {}".format(local, remote))
@@ -290,6 +294,18 @@
self.assertEqual('t', adb.shell("FOO=a BAR=b echo t").strip())
self.assertEqual('123Linux', adb.shell("echo -n 123\;uname").strip())
+ def test_install_argument_escaping(self):
+ """Make sure that install argument escaping works."""
+ adb = AdbWrapper()
+
+ # http://b/20323053
+ tf = tempfile.NamedTemporaryFile("w", suffix="-text;ls;1.apk")
+ self.assertIn("-text;ls;1.apk", adb.install(tf.name))
+
+ # http://b/3090932
+ tf = tempfile.NamedTemporaryFile("w", suffix="-Live Hold'em.apk")
+ self.assertIn("-Live Hold'em.apk", adb.install(tf.name))
+
class AdbFile(unittest.TestCase):
SCRATCH_DIR = "/data/local/tmp"
diff --git a/base/include/base/stringprintf.h b/base/include/base/stringprintf.h
index 195c1de..d68af87 100644
--- a/base/include/base/stringprintf.h
+++ b/base/include/base/stringprintf.h
@@ -23,16 +23,32 @@
namespace android {
namespace base {
+// These printf-like functions are implemented in terms of vsnprintf, so they
+// use the same attribute for compile-time format string checking. On Windows,
+// if the mingw version of vsnprintf is used, use `gnu_printf' which allows z
+// in %zd and PRIu64 (and related) to be recognized by the compile-time
+// checking.
+#define FORMAT_ARCHETYPE __printf__
+#ifdef __USE_MINGW_ANSI_STDIO
+#if __USE_MINGW_ANSI_STDIO
+#undef FORMAT_ARCHETYPE
+#define FORMAT_ARCHETYPE gnu_printf
+#endif
+#endif
+
// Returns a string corresponding to printf-like formatting of the arguments.
std::string StringPrintf(const char* fmt, ...)
- __attribute__((__format__(__printf__, 1, 2)));
+ __attribute__((__format__(FORMAT_ARCHETYPE, 1, 2)));
// Appends a printf-like formatting of the arguments to 'dst'.
void StringAppendF(std::string* dst, const char* fmt, ...)
- __attribute__((__format__(__printf__, 2, 3)));
+ __attribute__((__format__(FORMAT_ARCHETYPE, 2, 3)));
// Appends a printf-like formatting of the arguments to 'dst'.
-void StringAppendV(std::string* dst, const char* format, va_list ap);
+void StringAppendV(std::string* dst, const char* format, va_list ap)
+ __attribute__((__format__(FORMAT_ARCHETYPE, 2, 0)));
+
+#undef FORMAT_ARCHETYPE
} // namespace base
} // namespace android