aboutsummaryrefslogtreecommitdiffstats
path: root/smbutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'smbutil.c')
-rw-r--r--smbutil.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/smbutil.c b/smbutil.c
index fc9b3cc6f227..525635cbc7f7 100644
--- a/smbutil.c
+++ b/smbutil.c
@@ -478,12 +478,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':
@@ -797,17 +798,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);
@@ -818,22 +835,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);
@@ -847,11 +877,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;