diff --git a/build.mk b/build.mk index e273e251..1b11b85c 100644 --- a/build.mk +++ b/build.mk @@ -87,6 +87,7 @@ TESTS= \ test/test-getsockname.o \ test/test-hrtime.o \ test/test-idle.o \ + test/test-ip6-addr.o \ test/test-ipc.o \ test/test-ipc-send-recv.o \ test/test-loop-handles.o \ diff --git a/checksparse.sh b/checksparse.sh index 01fac07a..a75039fc 100755 --- a/checksparse.sh +++ b/checksparse.sh @@ -107,6 +107,7 @@ test/test-getaddrinfo.c test/test-getsockname.c test/test-hrtime.c test/test-idle.c +test/test-ip6-addr.c test/test-ipc-send-recv.c test/test-ipc.c test/test-loop-handles.c diff --git a/src/inet.c b/src/inet.c index 8f9d89b0..d8848988 100644 --- a/src/inet.c +++ b/src/inet.c @@ -229,7 +229,7 @@ static uv_err_t inet_pton6(const char *src, unsigned char *dst) { curtok = src; seen_xdigits = 0; val = 0; - while ((ch = *src++) != '\0') { + while ((ch = *src++) != '\0' && ch != '%') { const char *pch; if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) @@ -260,7 +260,18 @@ static uv_err_t inet_pton6(const char *src, unsigned char *dst) { continue; } if (ch == '.' && ((tp + sizeof(struct in_addr)) <= endp)) { - uv_err_t err = inet_pton4(curtok, tp); + uv_err_t err; + + /* Scope id present, parse ipv4 addr without it */ + pch = strchr(curtok, '%'); + if (pch != NULL) { + char tmp[sizeof "255.255.255.255"]; + + memcpy(tmp, curtok, pch - curtok); + curtok = tmp; + src = pch; + } + err = inet_pton4(curtok, tp); if (err.code == 0) { tp += sizeof(struct in_addr); seen_xdigits = 0; diff --git a/test/test-ip6-addr.c b/test/test-ip6-addr.c new file mode 100644 index 00000000..3b4cb8fe --- /dev/null +++ b/test/test-ip6-addr.c @@ -0,0 +1,64 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +#define GOOD_ADDR_LIST(X) \ + X("::") \ + X("::1") \ + X("fe80::1") \ + X("fe80::") \ + X("fe80::2acf:daff:fedd:342a") \ + X("fe80:0:0:0:2acf:daff:fedd:342a") \ + X("fe80:0:0:0:2acf:daff:1.2.3.4") \ + +#define BAD_ADDR_LIST(X) \ + X(":::1") \ + X("abcde::1") \ + X("fe80:0:0:0:2acf:daff:fedd:342a:5678") \ + X("fe80:0:0:0:2acf:daff:abcd:1.2.3.4") \ + X("fe80:0:0:2acf:daff:1.2.3.4.5") \ + +#define TEST_GOOD(ADDR) \ + ASSERT(uv_inet_pton(AF_INET6, ADDR, &addr).code == UV_OK); \ + ASSERT(uv_inet_pton(AF_INET6, ADDR "%en1", &addr).code == UV_OK); \ + ASSERT(uv_inet_pton(AF_INET6, ADDR "%%%%", &addr).code == UV_OK); \ + ASSERT(uv_inet_pton(AF_INET6, ADDR "%en1:1.2.3.4", &addr).code == UV_OK); \ + +#define TEST_BAD(ADDR) \ + ASSERT(uv_inet_pton(AF_INET6, ADDR, &addr).code != UV_OK); \ + ASSERT(uv_inet_pton(AF_INET6, ADDR "%en1", &addr).code != UV_OK); \ + ASSERT(uv_inet_pton(AF_INET6, ADDR "%%%%", &addr).code != UV_OK); \ + ASSERT(uv_inet_pton(AF_INET6, ADDR "%en1:1.2.3.4", &addr).code != UV_OK); \ + +TEST_IMPL(ip6_pton) { + struct in6_addr addr; + + GOOD_ADDR_LIST(TEST_GOOD) + BAD_ADDR_LIST(TEST_BAD) + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +#undef GOOD_ADDR_LIST +#undef BAD_ADDR_LIST diff --git a/test/test-list.h b/test/test-list.h index c280ca95..739de09b 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -37,6 +37,7 @@ TEST_DECLARE (semaphore_2) TEST_DECLARE (semaphore_3) TEST_DECLARE (tty) TEST_DECLARE (stdio_over_pipes) +TEST_DECLARE (ip6_pton) TEST_DECLARE (ipc_listen_before_write) TEST_DECLARE (ipc_listen_after_write) #ifndef _WIN32 @@ -265,6 +266,7 @@ TASK_LIST_START TEST_ENTRY (pipe_server_close) TEST_ENTRY (tty) TEST_ENTRY (stdio_over_pipes) + TEST_ENTRY (ip6_pton) TEST_ENTRY (ipc_listen_before_write) TEST_ENTRY (ipc_listen_after_write) #ifndef _WIN32 diff --git a/uv.gyp b/uv.gyp index 4e87dc1a..04c8e2da 100644 --- a/uv.gyp +++ b/uv.gyp @@ -305,6 +305,7 @@ 'test/test-getsockname.c', 'test/test-hrtime.c', 'test/test-idle.c', + 'test/test-ip6-addr.c', 'test/test-ipc.c', 'test/test-ipc-send-recv.c', 'test/test-list.h',