diff --git a/simdzone/src/fallback/name.h b/simdzone/src/fallback/name.h index 2e67855..9ea9a96 100644 --- a/simdzone/src/fallback/name.h +++ b/simdzone/src/fallback/name.h @@ -9,15 +9,17 @@ #ifndef NAME_H #define NAME_H -nonnull_all +nonnull((1,3,5)) static really_inline int32_t scan_name( const char *data, size_t length, uint8_t octets[255 + ZONE_BLOCK_SIZE], + const uint8_t *limit, size_t *lengthp) { uint8_t *l = octets, *w = octets + 1; - const uint8_t *we = octets + 255; + const uint8_t *we = limit && limit < octets + 255 + ? limit : octets + 255; const char *t = data, *te = t + length; l[0] = 0; diff --git a/simdzone/src/generic/format.h b/simdzone/src/generic/format.h index 76542c2..d167a27 100644 --- a/simdzone/src/generic/format.h +++ b/simdzone/src/generic/format.h @@ -52,8 +52,11 @@ static really_inline int32_t parse_name( // a freestanding "@" denotes the current origin if (unlikely(token->length == 1 && token->data[0] == '@')) goto relative; - switch (scan_name(token->data, token->length, rdata->octets, &length)) { + switch (scan_name(token->data, token->length, rdata->octets, rdata->limit, &length)) { case 0: + if (rdata->octets + length > rdata->limit) + SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); + rdata->octets += length; return 0; case 1: @@ -63,7 +66,8 @@ static really_inline int32_t parse_name( SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); relative: - if (length > 255 - parser->file->origin.length) + if (length > 255 - parser->file->origin.length + || rdata->octets + length + parser->file->origin.length > rdata->limit) SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(field), NAME(type)); memcpy(rdata->octets + length, parser->file->origin.octets, parser->file->origin.length); rdata->octets += length + parser->file->origin.length; @@ -85,7 +89,7 @@ static really_inline int32_t parse_owner( // a freestanding "@" denotes the origin if (unlikely(token->length == 1 && token->data[0] == '@')) goto relative; - switch (scan_name(token->data, token->length, octets, &length)) { + switch (scan_name(token->data, token->length, octets, NULL, &length)) { case 0: parser->file->owner.length = length; parser->owner = &parser->file->owner; @@ -263,7 +267,7 @@ static really_inline int32_t parse_dollar_include( // $INCLUDE directive MAY specify an origin take(parser, token); if (is_contiguous(token)) { - if (scan_name(token->data, token->length, name.octets, &name.length) != 0) { + if (scan_name(token->data, token->length, name.octets, NULL, &name.length) != 0) { zone_close_file(parser, file); SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[1]), NAME(&include)); } @@ -329,7 +333,7 @@ static inline int32_t parse_dollar_origin( if ((code = take_contiguous_or_quoted(parser, &origin, &fields[0], token)) < 0) return code; - if (scan_name(token->data, token->length, parser->file->origin.octets, &parser->file->origin.length) != 0) + if (scan_name(token->data, token->length, parser->file->origin.octets, NULL, &parser->file->origin.length) != 0) SYNTAX_ERROR(parser, "Invalid %s in %s", NAME(&fields[0]), NAME(&origin)); if ((code = take_delimiter(parser, &origin, token)) < 0) return code; diff --git a/simdzone/src/generic/name.h b/simdzone/src/generic/name.h index d16c943..75486a6 100644 --- a/simdzone/src/generic/name.h +++ b/simdzone/src/generic/name.h @@ -26,18 +26,23 @@ static really_inline void copy_name_block( block->dots = simd_find_8x32(&input, '.'); } -nonnull_all +nonnull((1,3,5)) static really_inline int32_t scan_name( const char *data, size_t tlength, uint8_t octets[255 + ZONE_BLOCK_SIZE], + const uint8_t *limit, size_t *lengthp) { uint64_t label = 0; const char *text = data; uint8_t *wire = octets + 1; name_block_t block; + size_t max_length = limit && ((uintptr_t)limit - (uintptr_t)octets) < 255 + ? ((uintptr_t)limit - (uintptr_t)octets) : 255; + if(max_length == 0) + return -1; octets[0] = 0; // real world domain names quickly exceed 16 octets (www.example.com is @@ -146,9 +151,9 @@ escaped: } octets[label] = (uint8_t)(length - label); - } while (left && length < 255); + } while (left && length < max_length); - if (length >= 255) + if (length >= max_length) return -1; *lengthp = length + 1; -- 2.43.0