From: Willem Toorop Date: Tue, 12 Jul 2022 14:53:56 +0000 (+0200) Subject: Fix #166 Grow buffer when converting to presentation format X-Git-Tag: 1.8.2-rc.1~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dcf0440accf5ac3d3aafae481a7cf911bcf5891e;p=thirdparty%2Fldns.git Fix #166 Grow buffer when converting to presentation format --- diff --git a/Changelog b/Changelog index 2a9b79e6..601a2ecf 100644 --- a/Changelog +++ b/Changelog @@ -8,6 +8,9 @@ * Enable compile of SVCB and HTTPS support by default. * bugfix #179: Free line memory even if zone file parsing fails Thanks Claudius Zingerli + * bugfix #166: Grow buffer when writing chars and fixed size + strings when converting to presentation format, preventing + potential assersion errors. 1.8.1 2021-12-03 * bugfix #146: ldns-1.7.1 had soname 3.0, so ldns-1.8.x soname diff --git a/host2str.c b/host2str.c index 45b3f42d..b0c76e93 100644 --- a/host2str.c +++ b/host2str.c @@ -1286,7 +1286,7 @@ ldns_rdf2buffer_str_hip(ldns_buffer *output, const ldns_rdf *rdf) ldns_buffer_printf(output, "%02x", (int) *data); } - ldns_buffer_write_u8(output, (uint8_t) ' '); + ldns_buffer_write_char(output, (uint8_t) ' '); if (ldns_buffer_reserve(output, ldns_b64_ntop_calculate_size(pk_size))) { @@ -1402,7 +1402,7 @@ svcparam_mandatory2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data) svcparam_key2buffer_str(output, ldns_read_uint16(data)); for (data += 2, sz -= 2; sz; data += 2, sz -= 2) { - ldns_buffer_write_u8(output, ','); + ldns_buffer_write_char(output, ','); svcparam_key2buffer_str(output, ldns_read_uint16(data)); } return ldns_buffer_status(output); @@ -1425,7 +1425,7 @@ svcparam_alpn2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data) quote = i < *dp; } if (quote) - ldns_buffer_write_u8(output, '"'); + ldns_buffer_write_char(output, '"'); while (data < eod) { uint8_t *eot = data + 1 + *data; @@ -1433,22 +1433,22 @@ svcparam_alpn2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data) return LDNS_STATUS_INVALID_SVCPARAM_VALUE; if (eod - data < (int)sz) - ldns_buffer_write_u8(output, ','); + ldns_buffer_write_char(output, ','); for (data += 1; data < eot; data += 1) { uint8_t ch = *data; if (isprint(ch) || ch == '\t') { if (ch == '"' || ch == ',' || ch == '\\') - ldns_buffer_write_u8(output, '\\'); - ldns_buffer_write_u8(output, ch); + ldns_buffer_write_char(output, '\\'); + ldns_buffer_write_char(output, ch); } else ldns_buffer_printf(output, "\\%03u" , (unsigned)ch); } } if (quote) - ldns_buffer_write_u8(output, '"'); + ldns_buffer_write_char(output, '"'); return ldns_buffer_status(output); } @@ -1469,14 +1469,14 @@ svcparam_ipv4hint2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data) if (sz % 4 || !inet_ntop(AF_INET, data, str, INET_ADDRSTRLEN)) return LDNS_STATUS_INVALID_SVCPARAM_VALUE; - ldns_buffer_write_string(output, str); + ldns_buffer_write_chars(output, str); for (data += 4, sz -= 4; sz ; data += 4, sz -= 4 ) { - ldns_buffer_write_u8(output, ','); + ldns_buffer_write_char(output, ','); if (!inet_ntop(AF_INET, data, str, INET_ADDRSTRLEN)) return LDNS_STATUS_INVALID_SVCPARAM_VALUE; - ldns_buffer_write_string(output, str); + ldns_buffer_write_chars(output, str); } return ldns_buffer_status(output); } @@ -1508,14 +1508,14 @@ svcparam_ipv6hint2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data) if (sz % 16 || !inet_ntop(AF_INET6, data, str, INET6_ADDRSTRLEN)) return LDNS_STATUS_INVALID_SVCPARAM_VALUE; - ldns_buffer_write_string(output, str); + ldns_buffer_write_chars(output, str); for (data += 16, sz -= 16; sz ; data += 16, sz -= 16) { - ldns_buffer_write_u8(output, ','); + ldns_buffer_write_char(output, ','); if (!inet_ntop(AF_INET6, data, str, INET6_ADDRSTRLEN)) return LDNS_STATUS_INVALID_SVCPARAM_VALUE; - ldns_buffer_write_string(output, str); + ldns_buffer_write_chars(output, str); } return ldns_buffer_status(output); } @@ -1530,20 +1530,20 @@ svcparam_value2buffer_str(ldns_buffer *output, size_t sz, uint8_t *data) ; /* pass */ if ((quote = dp < eod)) - ldns_buffer_write_u8(output, '"'); + ldns_buffer_write_char(output, '"'); for (dp = data; dp < eod; dp++) { uint8_t ch = *dp; if (isprint(ch) || ch == '\t') { if (ch == '"' || ch == '\\') - ldns_buffer_write_u8(output, '\\'); - ldns_buffer_write_u8(output, ch); + ldns_buffer_write_char(output, '\\'); + ldns_buffer_write_char(output, ch); } else ldns_buffer_printf(output, "\\%03u", (unsigned)ch); } if (quote) - ldns_buffer_write_u8(output, '"'); + ldns_buffer_write_char(output, '"'); return ldns_buffer_status(output); } @@ -1569,7 +1569,7 @@ ldns_rdf2buffer_str_svcparams(ldns_buffer *output, const ldns_rdf *rdf) return LDNS_STATUS_RDATA_OVERFLOW; if (dp > data) - ldns_buffer_write_u8(output, ' '); + ldns_buffer_write_char(output, ' '); if ((st = svcparam_key2buffer_str(output, key))) return st; @@ -1577,7 +1577,7 @@ ldns_rdf2buffer_str_svcparams(ldns_buffer *output, const ldns_rdf *rdf) if (val_sz == 0) continue; dp += 4; - ldns_buffer_write_u8(output, '='); + ldns_buffer_write_char(output, '='); switch (key) { case LDNS_SVCPARAM_KEY_MANDATORY: st = svcparam_mandatory2buffer_str(output, val_sz, dp); @@ -2653,7 +2653,7 @@ ldns_buffer2str(ldns_buffer *buffer) if (!ldns_buffer_reserve(buffer, 1)) { return NULL; } - ldns_buffer_write_u8(buffer, (uint8_t) '\0'); + ldns_buffer_write_char(buffer, (uint8_t) '\0'); if (!ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer))) { return NULL; } @@ -2676,7 +2676,7 @@ ldns_buffer_export2str(ldns_buffer *buffer) if (! ldns_buffer_reserve(buffer, 1)) { return NULL; } - ldns_buffer_write_u8(buffer, 0); + ldns_buffer_write_char(buffer, 0); /* reallocate memory to the size of the string and export */ ldns_buffer_set_capacity(buffer, ldns_buffer_position(buffer)); diff --git a/ldns/buffer.h b/ldns/buffer.h index f49a550b..79ae0f5c 100644 --- a/ldns/buffer.h +++ b/ldns/buffer.h @@ -399,6 +399,22 @@ ldns_buffer_write_string(ldns_buffer *buffer, const char *str) ldns_buffer_write(buffer, str, strlen(str)); } +/** + * copies the given (null-delimited) string to the current position at the buffer + * increasing the capacity if necessary + * \param[in] buffer the buffer + * \param[in] str the string to write + */ +INLINE void +ldns_buffer_write_chars(ldns_buffer *buffer, const char *str) +{ + if (!ldns_buffer_reserve(buffer, strlen(str))) + buffer->_status = LDNS_STATUS_MEM_ERR; + else + ldns_buffer_write_string(buffer, str); +} + + /** * writes the given byte of data at the given position in the buffer * \param[in] buffer the buffer @@ -424,6 +440,21 @@ ldns_buffer_write_u8(ldns_buffer *buffer, uint8_t data) buffer->_position += sizeof(data); } +/** + * writes the given byte of data at the current position in the buffer + * increasing the capacity if necessary + * \param[in] buffer the buffer + * \param[in] data the 8 bits to write + */ +INLINE void +ldns_buffer_write_char(ldns_buffer *buffer, uint8_t data) +{ + if (!ldns_buffer_reserve(buffer, sizeof(data))) + buffer->_status = LDNS_STATUS_MEM_ERR; + else + ldns_buffer_write_u8(buffer, data); +} + /** * writes the given 2 byte integer at the given position in the buffer * \param[in] buffer the buffer