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.
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 56ab88b..22d94b4 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1074,18 +1074,15 @@
unsigned short usval;
long lval;
char *sval;
+
#define CHECK_LIMIT(size) \
- if (limit && p + (size) > (unsigned char*)limit) \
- { \
- va_end(ap); \
- goto truncated; \
- }
-
- if (truncp && *truncp)
- return 0;
+ if (limit && p + (size) > (unsigned char*)limit) goto truncated;
va_start(ap, format); /* make ap point to 1st unamed argument */
-
+
+ if (truncp && *truncp)
+ goto truncated;
+
if (nameoffset > 0)
{
CHECK_LIMIT(2);
@@ -1095,10 +1092,7 @@
{
char *name = va_arg(ap, char *);
if (name && !(p = do_rfc1035_name(p, name, limit)))
- {
- va_end(ap);
- goto truncated;
- }
+ goto truncated;
if (nameoffset < 0)
{
@@ -1163,13 +1157,9 @@
/* get domain-name answer arg and store it in RDATA field */
if (offset)
*offset = p - (unsigned char *)header;
- p = do_rfc1035_name(p, va_arg(ap, char *), limit);
- if (!p)
- {
- va_end(ap);
- goto truncated;
- }
- CHECK_LIMIT(1);
+ if (!(p = do_rfc1035_name(p, va_arg(ap, char *), limit)))
+ goto truncated;
+ CHECK_LIMIT(1);
*p++ = 0;
break;
@@ -1194,24 +1184,22 @@
break;
}
-#undef CHECK_LIMIT
va_end(ap); /* clean up variable argument pointer */
+ /* Now, store real RDLength. sav already checked against limit. */
j = p - sav - 2;
- /* this has already been checked against limit before */
- 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;
- }
+ PUTSHORT(j, sav);
*pp = p;
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)
diff --git a/src/util.c b/src/util.c
index 2a1d448..f5d4a78 100644
--- a/src/util.c
+++ b/src/util.c
@@ -246,14 +246,16 @@
while (sval && *sval)
{
- if (limit && p + 1 > (unsigned char*)limit)
- return p;
-
unsigned char *cp = p++;
+
+ if (limit && p > (unsigned char*)limit)
+ return NULL;
+
for (j = 0; *sval && (*sval != '.'); sval++, j++)
{
if (limit && p + 1 > (unsigned char*)limit)
- return p;
+ return NULL;
+
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
*p++ = (*(++sval))-1;
@@ -261,10 +263,12 @@
#endif
*p++ = *sval;
}
+
*cp = j;
if (*sval)
sval++;
}
+
return p;
}