diff options
author | Guy Harris <guy@alum.mit.edu> | 2016-08-07 17:48:27 -0700 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2016-08-07 17:48:27 -0700 |
commit | 9e9347f3dce4a82a4b75230a39d3f382c6f15f2a (patch) | |
tree | f8a850b7b2a626d4ca2916830630c783c65bbbe0 /addrtostr.c | |
parent | 3ac642ee4cb3ba2f54052fdb7754525bd4a40709 (diff) | |
download | tcpdump-9e9347f3dce4a82a4b75230a39d3f382c6f15f2a.tar.gz |
Do the addrtostr6() bounds checking while we're generating the string.
That obviates the need for a temporary buffer, and eliminates complaints
about using sprintf().
Diffstat (limited to 'addrtostr.c')
-rw-r--r-- | addrtostr.c | 49 |
1 files changed, 32 insertions, 17 deletions
diff --git a/addrtostr.c b/addrtostr.c index caea1775..92875622 100644 --- a/addrtostr.c +++ b/addrtostr.c @@ -106,8 +106,9 @@ addrtostr6 (const void *src, char *dst, size_t size) * to use pointer overlays. All the world's not a VAX. */ const u_char *srcaddr = (const u_char *)src; - char tmp [INET6_ADDRSTRLEN+1]; - char *tp; + char *dp; + size_t space_left, added_space; + int snprintfed; struct { long base; long len; @@ -149,7 +150,17 @@ addrtostr6 (const void *src, char *dst, size_t size) /* Format the result. */ - tp = tmp; + dp = dst; + space_left = size; +#define APPEND_CHAR(c) \ + { \ + if (space_left == 0) { \ + errno = ENOSPC; \ + return (NULL); \ + } \ + *dp++ = c; \ + space_left--; \ + } for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { /* Are we inside the best run of 0x00's? @@ -157,43 +168,47 @@ addrtostr6 (const void *src, char *dst, size_t size) if (best.base != -1 && i >= best.base && i < (best.base + best.len)) { if (i == best.base) - *tp++ = ':'; + APPEND_CHAR(':'); continue; } /* Are we following an initial run of 0x00s or any real hex? */ if (i != 0) - *tp++ = ':'; + APPEND_CHAR(':'); /* Is this address an encapsulated IPv4? */ if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { - if (!addrtostr(srcaddr+12, tp, sizeof(tmp) - (tp - tmp))) + if (!addrtostr(srcaddr+12, dp, space_left)) { errno = ENOSPC; return (NULL); } - tp += strlen(tp); + added_space = strlen(dp); + dp += added_space; + space_left -= added_space; break; } - tp += sprintf (tp, "%lx", words[i]); + snprintfed = snprintf (dp, space_left, "%lx", words[i]); + if (snprintfed < 0) + return (NULL); + if ((size_t) snprintfed >= space_left) + { + errno = ENOSPC; + return (NULL); + } + dp += snprintfed; + space_left -= snprintfed; } /* Was it a trailing run of 0x00's? */ if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) - *tp++ = ':'; - *tp++ = '\0'; + APPEND_CHAR(':'); + APPEND_CHAR('\0'); - /* Copy and check for overflow. - */ - if (strlcpy (dst, tmp, size) >= size) - { - errno = ENOSPC; - return (NULL); - } return (dst); } |