Commit c366717e authored by Simon Kelley's avatar Simon Kelley

Tidy up add_resource_record() buffer size checks.

Mainly code-size and readability fixes.

Also return NULL from do_rfc1035_name() when limit exceeded, so
that truncated bit gets set in answer.
parent 22dee512
...@@ -1074,18 +1074,15 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int ...@@ -1074,18 +1074,15 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
unsigned short usval; unsigned short usval;
long lval; long lval;
char *sval; char *sval;
#define CHECK_LIMIT(size) \ #define CHECK_LIMIT(size) \
if (limit && p + (size) > (unsigned char*)limit) \ if (limit && p + (size) > (unsigned char*)limit) goto truncated;
{ \
va_end(ap); \
goto truncated; \
}
if (truncp && *truncp)
return 0;
va_start(ap, format); /* make ap point to 1st unamed argument */ va_start(ap, format); /* make ap point to 1st unamed argument */
if (truncp && *truncp)
goto truncated;
if (nameoffset > 0) if (nameoffset > 0)
{ {
CHECK_LIMIT(2); CHECK_LIMIT(2);
...@@ -1095,10 +1092,7 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int ...@@ -1095,10 +1092,7 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
{ {
char *name = va_arg(ap, char *); char *name = va_arg(ap, char *);
if (name && !(p = do_rfc1035_name(p, name, limit))) if (name && !(p = do_rfc1035_name(p, name, limit)))
{ goto truncated;
va_end(ap);
goto truncated;
}
if (nameoffset < 0) if (nameoffset < 0)
{ {
...@@ -1163,13 +1157,9 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int ...@@ -1163,13 +1157,9 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
/* get domain-name answer arg and store it in RDATA field */ /* get domain-name answer arg and store it in RDATA field */
if (offset) if (offset)
*offset = p - (unsigned char *)header; *offset = p - (unsigned char *)header;
p = do_rfc1035_name(p, va_arg(ap, char *), limit); if (!(p = do_rfc1035_name(p, va_arg(ap, char *), limit)))
if (!p) goto truncated;
{ CHECK_LIMIT(1);
va_end(ap);
goto truncated;
}
CHECK_LIMIT(1);
*p++ = 0; *p++ = 0;
break; break;
...@@ -1194,24 +1184,22 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int ...@@ -1194,24 +1184,22 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
break; break;
} }
#undef CHECK_LIMIT
va_end(ap); /* clean up variable argument pointer */ va_end(ap); /* clean up variable argument pointer */
/* Now, store real RDLength. sav already checked against limit. */
j = p - sav - 2; j = p - sav - 2;
/* this has already been checked against limit before */ PUTSHORT(j, sav);
PUTSHORT(j, sav); /* Now, store real RDLength */
/* check for overflow of buffer */
if (limit && ((unsigned char *)limit - p) < 0)
{
truncated:
if (truncp)
*truncp = 1;
return 0;
}
*pp = p; *pp = p;
return 1; return 1;
truncated:
va_end(ap);
if (truncp)
*truncp = 1;
return 0;
#undef CHECK_LIMIT
} }
static unsigned long crec_ttl(struct crec *crecp, time_t now) static unsigned long crec_ttl(struct crec *crecp, time_t now)
......
...@@ -246,14 +246,16 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit) ...@@ -246,14 +246,16 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
while (sval && *sval) while (sval && *sval)
{ {
if (limit && p + 1 > (unsigned char*)limit)
return p;
unsigned char *cp = p++; unsigned char *cp = p++;
if (limit && p > (unsigned char*)limit)
return NULL;
for (j = 0; *sval && (*sval != '.'); sval++, j++) for (j = 0; *sval && (*sval != '.'); sval++, j++)
{ {
if (limit && p + 1 > (unsigned char*)limit) if (limit && p + 1 > (unsigned char*)limit)
return p; return NULL;
#ifdef HAVE_DNSSEC #ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE) if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
*p++ = (*(++sval))-1; *p++ = (*(++sval))-1;
...@@ -261,10 +263,12 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit) ...@@ -261,10 +263,12 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
#endif #endif
*p++ = *sval; *p++ = *sval;
} }
*cp = j; *cp = j;
if (*sval) if (*sval)
sval++; sval++;
} }
return p; return p;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment