curl: stop interpreting IPv6 literals as glob patterns.

This makes it possible to fetch from an IPv6 literal without specifying
the -g option.  Globbing remains available elsehwere in the URL.

For example:
  curl http://[::1]/file[1-3].txt

This creates no ambiguity, because there is no overlap between the
syntax of valid globs and valid IPv6 literals.  Globs contain hyphens
and at most 1 colon, while IPv6 literals have no hyphens, and at least 2
colons.

The peek_ipv6() parser simply whitelists a set of characters and counts
colons, because the real validation happens later on.  The character set
includes A-Z, in case someone decides to implement support for scopes
like [fe80::1%25eth0] in the future.

Signed-off-by: Paul Marks <pmarks@google.com>
This commit is contained in:
Paul Marks 2014-03-30 07:50:37 +02:00 committed by Daniel Stenberg
parent 4043d7b67b
commit 0bc4938eec
2 changed files with 46 additions and 4 deletions

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -302,6 +302,36 @@ static GlobCode glob_range(URLGlob *glob, char **patternp,
return GLOB_OK; return GLOB_OK;
} }
static bool peek_ipv6(const char *str, size_t *skip)
{
/*
* Scan for a potential IPv6 literal.
* - Valid globs contain a hyphen and <= 1 colon.
* - IPv6 literals contain no hyphens and >= 2 colons.
*/
size_t i = 0;
size_t colons = 0;
if(str[i++] != '[') {
return FALSE;
}
for(;;) {
const char c = str[i++];
if(ISALNUM(c) || c == '.' || c == '%') {
/* ok */
}
else if(c == ':') {
colons++;
}
else if(c == ']') {
*skip = i;
return colons >= 2;
}
else {
return FALSE;
}
}
}
static GlobCode glob_parse(URLGlob *glob, char *pattern, static GlobCode glob_parse(URLGlob *glob, char *pattern,
size_t pos, unsigned long *amount) size_t pos, unsigned long *amount)
{ {
@ -315,8 +345,20 @@ static GlobCode glob_parse(URLGlob *glob, char *pattern,
while(*pattern && !res) { while(*pattern && !res) {
char *buf = glob->glob_buffer; char *buf = glob->glob_buffer;
int sublen = 0; size_t sublen = 0;
while(*pattern && *pattern != '{' && *pattern != '[') { while(*pattern && *pattern != '{') {
if(*pattern == '[') {
/* Skip over potential IPv6 literals. */
size_t skip;
if(peek_ipv6(pattern, &skip)) {
memcpy(buf, pattern, skip);
buf += skip;
pattern += skip;
sublen += skip;
continue;
}
break;
}
if(*pattern == '}' || *pattern == ']') if(*pattern == '}' || *pattern == ']')
return GLOBERROR("unmatched close brace/bracket", pos, GLOB_ERROR); return GLOBERROR("unmatched close brace/bracket", pos, GLOB_ERROR);

View File

@ -56,7 +56,7 @@ HTTP CONNECT to IPv6 numerical address
</name> </name>
# 0x4ce == 1230, the test number # 0x4ce == 1230, the test number
<command> <command>
-g http://[1234:1234:1234::4ce]:%HTTPPORT/wanted/page/1230 -p -x %HOSTIP:%HTTPPORT http://[1234:1234:1234::4ce]:%HTTPPORT/wanted/page/1230 -p -x %HOSTIP:%HTTPPORT
</command> </command>
</client> </client>