diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c index 134febb4aa..ea2aa927f6 100644 --- a/lib/dns/rdataslab.c +++ b/lib/dns/rdataslab.c @@ -176,7 +176,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, static unsigned char removed; struct xrdata *x = NULL; unsigned char *rawbuf = NULL; - unsigned int buflen; + uint32_t buflen; isc_result_t result; unsigned int nitems; unsigned int nalloc; @@ -291,6 +291,10 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, if (rdataset->type == dns_rdatatype_rrsig) { buflen++; } + if (buflen - reservelen - 2 > DNS_RDATA_MAXLENGTH) { + result = ISC_R_NOSPACE; + goto free_rdatas; + } } } @@ -308,6 +312,10 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, if (rdataset->type == dns_rdatatype_rrsig) { buflen++; } + if (buflen - reservelen - 2 > DNS_RDATA_MAXLENGTH) { + result = ISC_R_NOSPACE; + goto free_rdatas; + } /* * Ensure that singleton types are actually singletons. @@ -523,7 +531,8 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab, unsigned char **tslabp) { unsigned char *ocurrent = NULL, *ostart = NULL, *ncurrent = NULL; unsigned char *tstart = NULL, *tcurrent = NULL, *data = NULL; - unsigned int ocount, ncount, count, olength, tlength, tcount, length; + unsigned int ocount, ncount, count, olength, tcount, length; + uint32_t tlength; dns_rdata_t ordata = DNS_RDATA_INIT; dns_rdata_t nrdata = DNS_RDATA_INIT; bool added_something = false; @@ -611,6 +620,9 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab, if (type == dns_rdatatype_rrsig) { tlength++; } + if (tlength - reservelen - 2 > DNS_RDATA_MAXLENGTH) { + return ISC_R_NOSPACE; + } tcount++; nncount++; added_something = true; @@ -787,7 +799,8 @@ dns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab, unsigned int flags, unsigned char **tslabp) { unsigned char *mcurrent = NULL, *sstart = NULL, *scurrent = NULL; unsigned char *tstart = NULL, *tcurrent = NULL; - unsigned int mcount, scount, rcount, count, tlength, tcount, i; + unsigned int mcount, scount, rcount, count, tcount, i; + uint32_t tlength; dns_rdata_t srdata = DNS_RDATA_INIT; dns_rdata_t mrdata = DNS_RDATA_INIT; #if DNS_RDATASET_FIXED @@ -842,7 +855,10 @@ dns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab, * This rdata isn't in the sslab, and thus isn't * being subtracted. */ - tlength += (unsigned int)(mcurrent - mrdatabegin); + tlength += (uint32_t)(mcurrent - mrdatabegin); + if (tlength - reservelen - 2 > DNS_RDATA_MAXLENGTH) { + return ISC_R_NOSPACE; + } tcount++; } else { rcount++; diff --git a/tests/dns/qpdb_test.c b/tests/dns/qpdb_test.c index 29b2fad804..c1888101d1 100644 --- a/tests/dns/qpdb_test.c +++ b/tests/dns/qpdb_test.c @@ -146,7 +146,8 @@ ISC_LOOP_TEST_IMPL(overmempurge_bigrdata) { * cache size doesn't reach the "max". */ while (i-- > 0) { - overmempurge_addrdataset(db, now, i, 50054, 65535, false); + overmempurge_addrdataset(db, now, i, 50054, + DNS_RDATA_MAXLENGTH - 8, false); if (verbose) { print_message("# inuse: %zd max: %zd\n", isc_mem_inuse(mctx2), maxcache);