From 73d55aaab23256f85941730444e82cbc41a63f8b Mon Sep 17 00:00:00 2001 From: David Pursell Date: Wed, 21 Sep 2016 12:08:37 -0700 Subject: [PATCH] adb: fix host-side serial number parsing for IPv6. When the adb client sends a command to the adb server targeting a particular device serial, it looks something like this: host-serial:: But if happens to be an IPv6 address (e.g. when `adb connect` targets IPv6), the current parsing code doesn't handle the additional colons properly. This CL fixes the host-serial parsing to handle this case. This only affects commands that explicitly name a device serial, e.g.: adb -s shell adb -s forward Implicitly using a single attached device was unaffected by this bug. Bug: http://b/30891386 Test: `adb -s [fe80::ba27:ebff:feb1:934%eth2]:5555 shell` works now, and new unittests pass. Change-Id: Iffe784e61432ae94eb96ed3c8477900a3e807329 --- adb/socket_test.cpp | 11 +++++++++++ adb/sockets.cpp | 21 ++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp index 2bb01a382..5e79b5e2e 100644 --- a/adb/socket_test.cpp +++ b/adb/socket_test.cpp @@ -307,6 +307,17 @@ TEST(socket_test, test_skip_host_serial) { // Don't register a port unless it's all numbers and ends with ':'. VerifySkipHostSerial(protocol + "foo:123", ":123"); VerifySkipHostSerial(protocol + "foo:123bar:baz", ":123bar:baz"); + + VerifySkipHostSerial(protocol + "100.100.100.100:5555:foo", ":foo"); + VerifySkipHostSerial(protocol + "[0123:4567:89ab:CDEF:0:9:a:f]:5555:foo", ":foo"); + VerifySkipHostSerial(protocol + "[::1]:5555:foo", ":foo"); + + // If we can't find both [] then treat it as a normal serial with [ in it. + VerifySkipHostSerial(protocol + "[0123:foo", ":foo"); + + // Don't be fooled by random IPv6 addresses in the command string. + VerifySkipHostSerial(protocol + "foo:ping [0123:4567:89ab:CDEF:0:9:a:f]:5555", + ":ping [0123:4567:89ab:CDEF:0:9:a:f]:5555"); } } diff --git a/adb/sockets.cpp b/adb/sockets.cpp index abba7452b..41372e5cc 100644 --- a/adb/sockets.cpp +++ b/adb/sockets.cpp @@ -622,21 +622,32 @@ char* skip_host_serial(char* service) { service += 4; } - char* first_colon = strchr(service, ':'); - if (!first_colon) { + // Check for an IPv6 address. `adb connect` creates the serial number from the canonical + // network address so it will always have the [] delimiters. + if (service[0] == '[') { + char* ipv6_end = strchr(service, ']'); + if (ipv6_end != nullptr) { + service = ipv6_end; + } + } + + // The next colon we find must either begin the port field or the command field. + char* colon_ptr = strchr(service, ':'); + if (!colon_ptr) { // No colon in service string. return nullptr; } - char* serial_end = first_colon; + // If the next field is only decimal digits and ends with another colon, it's a port. + char* serial_end = colon_ptr; if (isdigit(serial_end[1])) { serial_end++; while (*serial_end && isdigit(*serial_end)) { serial_end++; } if (*serial_end != ':') { - // Something other than numbers was found, reset the end. - serial_end = first_colon; + // Something other than ":" was found, this must be the command field instead. + serial_end = colon_ptr; } } return serial_end;