mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
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.
This commit is contained in:
@@ -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) \
|
|
||||||
if (limit && p + (size) > (unsigned char*)limit) \
|
|
||||||
{ \
|
|
||||||
va_end(ap); \
|
|
||||||
goto truncated; \
|
|
||||||
}
|
|
||||||
|
|
||||||
if (truncp && *truncp)
|
#define CHECK_LIMIT(size) \
|
||||||
return 0;
|
if (limit && p + (size) > (unsigned char*)limit) goto truncated;
|
||||||
|
|
||||||
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
|
|||||||
{
|
{
|
||||||
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
|
|||||||
/* 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
|
|||||||
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)
|
||||||
|
|||||||
12
src/util.c
12
src/util.c
@@ -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)
|
|||||||
#endif
|
#endif
|
||||||
*p++ = *sval;
|
*p++ = *sval;
|
||||||
}
|
}
|
||||||
|
|
||||||
*cp = j;
|
*cp = j;
|
||||||
if (*sval)
|
if (*sval)
|
||||||
sval++;
|
sval++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user