diff options
Diffstat (limited to 'freebsd/contrib/tcpdump/smbutil.c')
-rw-r--r-- | freebsd/contrib/tcpdump/smbutil.c | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/freebsd/contrib/tcpdump/smbutil.c b/freebsd/contrib/tcpdump/smbutil.c index 5ed188b6..31ee99c4 100644 --- a/freebsd/contrib/tcpdump/smbutil.c +++ b/freebsd/contrib/tcpdump/smbutil.c @@ -484,12 +484,13 @@ smb_fdata1(netdissect_options *ndo, case 'P': { - int l = atoi(fmt + 1); + int l = atoi(fmt + 1); + if(l <= 0) goto trunc; /* actually error in fmt string */ ND_TCHECK2(buf[0], l); buf += l; fmt++; while (isdigit((unsigned char)*fmt)) - fmt++; + fmt++; break; } case 'r': @@ -803,17 +804,33 @@ smb_fdata(netdissect_options *ndo, int unicodestr) { static int depth = 0; + const u_char *buf_start = buf; char s[128]; char *p; while (*fmt) { switch (*fmt) { case '*': + /* + * List of multiple instances of something described by the + * remainder of the string (which may itself include a list + * of multiple instances of something, so we recurse). + */ fmt++; while (buf < maxbuf) { const u_char *buf2; depth++; - buf2 = smb_fdata(ndo, buf, fmt, maxbuf, unicodestr); + /* + * In order to avoid stack exhaustion recurse at most 10 + * levels; that "should not happen", as no SMB structure + * should be nested *that* deeply, and we thus shouldn't + * have format strings with that level of nesting. + */ + if (depth == 10) { + ND_PRINT((ndo, "(too many nested levels, not recursing)")); + buf2 = buf; + } else + buf2 = smb_fdata(ndo, buf, fmt, maxbuf, unicodestr); depth--; if (buf2 == NULL) return(NULL); @@ -824,22 +841,35 @@ smb_fdata(netdissect_options *ndo, return(buf); case '|': + /* + * Just do a bounds check. + */ fmt++; if (buf >= maxbuf) return(buf); break; case '%': + /* + * XXX - unused? + */ fmt++; buf = maxbuf; break; case '#': + /* + * Done? + */ fmt++; return(buf); break; case '[': + /* + * Format of an item, enclosed in square brackets; dissect + * the item with smb_fdata1(). + */ fmt++; if (buf >= maxbuf) return(buf); @@ -853,11 +883,15 @@ smb_fdata(netdissect_options *ndo, s[p - fmt] = '\0'; fmt = p + 1; buf = smb_fdata1(ndo, buf, s, maxbuf, unicodestr); - if (buf == NULL) + if(buf < buf_start || buf == NULL) { return(NULL); + } break; default: + /* + * Not a formatting character, so just print it. + */ ND_PRINT((ndo, "%c", *fmt)); fmt++; break; |