sockets: Change inet_parse() to accept address specification without port From: Bharata B Rao <bhar...@linux.vnet.ibm.com>
inet_parse() expects address:port. Change it to work without explicit port specification. In addition, don't depend solely on the return value of sscanf but also consider the value obtained for %n directive used in sscanf. This ensures that the scanning of malformed inet address isn't flagged as success. Signed-off-by: Bharata B Rao <bhar...@linux.vnet.ibm.com> --- qemu-sockets.c | 32 +++++++++++++++++++++++++------- 1 files changed, 25 insertions(+), 7 deletions(-) diff --git a/qemu-sockets.c b/qemu-sockets.c index c330fc5..627269f 100644 --- a/qemu-sockets.c +++ b/qemu-sockets.c @@ -376,26 +376,35 @@ err: return -1; } -/* compatibility wrapper */ +/* + * sscanf could return positive return value indicating successful + * match and assignment even when it doesn't parse the input as per + * the format specified. Hence we are depending on %n to really determine if + * inputs were successfully scanned. Checking retval for EOF isn't strictly + * necessary, but just being extra careful. + */ int inet_parse(QemuOpts *opts, const char *str) { const char *optstr, *h; char addr[64]; - char port[33]; - int pos; + char port[33] = {'\0'}; /* port is optional */ + int ret, pos, addr_pos = -1, port_pos = -1; /* parse address */ if (str[0] == ':') { /* no host given */ addr[0] = '\0'; - if (1 != sscanf(str,":%32[^,]%n",port,&pos)) { + ret = sscanf(str, ":%32[^,]%n", port, &port_pos); + if (port_pos == -1 || ret == EOF) { fprintf(stderr, "%s: portonly parse error (%s)\n", __FUNCTION__, str); return -1; } } else if (str[0] == '[') { /* IPv6 addr */ - if (2 != sscanf(str,"[%64[^]]]:%32[^,]%n",addr,port,&pos)) { + ret = sscanf(str, "[%64[^]]]%n:%32[^,]%n", addr, &addr_pos, + port, &port_pos); + if (addr_pos == -1 || ret == EOF) { fprintf(stderr, "%s: ipv6 parse error (%s)\n", __FUNCTION__, str); return -1; @@ -403,7 +412,9 @@ int inet_parse(QemuOpts *opts, const char *str) qemu_opt_set(opts, "ipv6", "on"); } else if (qemu_isdigit(str[0])) { /* IPv4 addr */ - if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) { + ret = sscanf(str, "%64[0-9.]%n:%32[^,]%n", addr, &addr_pos, + port, &port_pos); + if (addr_pos == -1 || ret == EOF) { fprintf(stderr, "%s: ipv4 parse error (%s)\n", __FUNCTION__, str); return -1; @@ -411,7 +422,9 @@ int inet_parse(QemuOpts *opts, const char *str) qemu_opt_set(opts, "ipv4", "on"); } else { /* hostname */ - if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) { + ret = sscanf(str, "%64[^:]%n:%32[^,]%n", addr, &addr_pos, + port, &port_pos); + if (addr_pos == -1 || ret == EOF) { fprintf(stderr, "%s: hostname parse error (%s)\n", __FUNCTION__, str); return -1; @@ -421,6 +434,11 @@ int inet_parse(QemuOpts *opts, const char *str) qemu_opt_set(opts, "port", port); /* parse options */ + if (port_pos != -1) { + pos = port_pos; + } else { + pos = addr_pos; + } optstr = str + pos; h = strstr(optstr, ",to="); if (h)