From a019f781417ea2351ace55603fc0906051f165c6 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Fri, 16 Jun 2017 15:34:34 -0700 Subject: [PATCH] adb: increase the shell command length limit. Relax the shell command length limits when talking to an adbd with the shell protocol. shell is pretty much the only service that takes an arbitrarily long string, so this is somewhat safe. Bug: http://b/37716055 Test: `adb shell $(python -c 'print "echo " + "f" * (32*1024)') | wc` on L and master Change-Id: I0737fd2244530ef8080f300cd3a3549a1ab93465 --- adb/adb_client.cpp | 2 +- adb/adb_io.cpp | 2 +- adb/commandline.cpp | 7 +++++++ adb/sockets.cpp | 2 +- adb/test_device.py | 7 +++++++ 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp index f5d0f02df..e533a00eb 100644 --- a/adb/adb_client.cpp +++ b/adb/adb_client.cpp @@ -125,7 +125,7 @@ bool adb_status(int fd, std::string* error) { static int _adb_connect(const std::string& service, std::string* error) { D("_adb_connect: %s", service.c_str()); - if (service.empty() || service.size() > MAX_PAYLOAD_V1) { + if (service.empty() || service.size() > MAX_PAYLOAD) { *error = android::base::StringPrintf("bad service name length (%zd)", service.size()); return -1; diff --git a/adb/adb_io.cpp b/adb/adb_io.cpp index ca8729eb1..38e31167e 100644 --- a/adb/adb_io.cpp +++ b/adb/adb_io.cpp @@ -31,7 +31,7 @@ bool SendProtocolString(int fd, const std::string& s) { unsigned int length = s.size(); - if (length > MAX_PAYLOAD_V1 - 4) { + if (length > MAX_PAYLOAD - 4) { errno = EMSGSIZE; return false; } diff --git a/adb/commandline.cpp b/adb/commandline.cpp index 68ae4affe..c9f1ee9cf 100644 --- a/adb/commandline.cpp +++ b/adb/commandline.cpp @@ -599,6 +599,13 @@ static int RemoteShell(bool use_shell_protocol, const std::string& type_arg, std::string service_string = ShellServiceString(use_shell_protocol, type_arg, command); + // Old devices can't handle a service string that's longer than MAX_PAYLOAD_V1. + // Use |use_shell_protocol| to determine whether to allow a command longer than that. + if (service_string.size() > MAX_PAYLOAD_V1 && !use_shell_protocol) { + fprintf(stderr, "error: shell command too long\n"); + return 1; + } + // Make local stdin raw if the device allocates a PTY, which happens if: // 1. We are explicitly asking for a PTY shell, or // 2. We don't specify shell type and are starting an interactive session. diff --git a/adb/sockets.cpp b/adb/sockets.cpp index 14ad1ff97..e0143c611 100644 --- a/adb/sockets.cpp +++ b/adb/sockets.cpp @@ -686,7 +686,7 @@ static int smart_socket_enqueue(asocket* s, apacket* p) { } len = unhex(p->data, 4); - if ((len < 1) || (len > MAX_PAYLOAD_V1)) { + if ((len < 1) || (len > MAX_PAYLOAD)) { D("SS(%d): bad size (%d)", s->id, len); goto fail; } diff --git a/adb/test_device.py b/adb/test_device.py index 737d0c247..9e1a2ec2d 100644 --- a/adb/test_device.py +++ b/adb/test_device.py @@ -342,6 +342,13 @@ class ShellTest(DeviceTest): out = self.device.shell(['echo', 'foo'])[0] self.assertEqual(out, 'foo' + self.device.linesep) + def test_shell_command_length(self): + # Devices that have shell_v2 should be able to handle long commands. + if self.device.has_shell_protocol(): + rc, out, err = self.device.shell_nocheck(['echo', 'x' * 16384]) + self.assertEqual(rc, 0) + self.assertTrue(out == ('x' * 16384 + '\n')) + def test_shell_nocheck_failure(self): rc, out, _ = self.device.shell_nocheck(['false']) self.assertNotEqual(rc, 0)