diff options
author | Paul Marks <pmarks@google.com> | 2014-03-30 07:50:37 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2014-03-30 23:45:29 +0200 |
commit | 0bc4938eecccefdf8906bf9c488e4cd9c8467e99 (patch) | |
tree | b6a82fdddea4cf18dd21ae49cde331435d855425 /src | |
parent | 4043d7b67b6d4c03e8c529408edbe65bc66e5ae1 (diff) |
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/tool_urlglob.c | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c index ec5014b97..943e0ab88 100644 --- a/src/tool_urlglob.c +++ b/src/tool_urlglob.c @@ -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 * 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; } +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, size_t pos, unsigned long *amount) { @@ -315,8 +345,20 @@ static GlobCode glob_parse(URLGlob *glob, char *pattern, while(*pattern && !res) { char *buf = glob->glob_buffer; - int sublen = 0; - while(*pattern && *pattern != '{' && *pattern != '[') { + size_t sublen = 0; + 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 == ']') return GLOBERROR("unmatched close brace/bracket", pos, GLOB_ERROR); |