From 13395d8a54245380f13a1c588166d3d4c5a04e2c Mon Sep 17 00:00:00 2001 From: "Meredith L. Patterson" <clonearmy@gmail.com> Date: Thu, 24 May 2012 13:22:43 +0200 Subject: [PATCH] counted_array now holds parsed_token_t's. TQ will fix the problem with accumulate_size. Compile-time bounds checks added to int_range. --- examples/dns.c | 35 +++++++++++++++++++++++----------- src/hammer.c | 51 ++++++++++++++++++++++++++++---------------------- src/hammer.h | 4 +++- 3 files changed, 56 insertions(+), 34 deletions(-) diff --git a/examples/dns.c b/examples/dns.c index 26f48549..c2fc59d3 100644 --- a/examples/dns.c +++ b/examples/dns.c @@ -5,7 +5,7 @@ bool is_zero(parse_result_t *p) { if (TT_UINT != p->ast->token_type) - return 0; + return false; return (0 == p->ast->uint); } @@ -14,7 +14,7 @@ bool is_zero(parse_result_t *p) { */ bool validate_label(parse_result_t *p) { if (TT_SEQUENCE != p->ast->token_type) - return 0; + return false; return (64 > p->ast->seq->used); } @@ -25,19 +25,20 @@ bool validate_label(parse_result_t *p) { */ bool validate_dns(parse_result_t *p) { if (TT_SEQUENCE != p->ast->token_type) - return 0; + return false; // The header holds the counts as its last 4 elements. parsed_token_t *header = p->ast->seq->elements[0]; - size_t qd = ((parsed_token_t*)header->seq->elements[8])->uint; - size_t an = ((parsed_token_t*)header->seq->elements[9])->uint; - size_t ns = ((parsed_token_t*)header->seq->elements[10])->uint; - size_t ar = ((parsed_token_t*)header->seq->elements[11])->uint; + size_t qd = header->seq->elements[8]->uint; + size_t an = header->seq->elements[9]->uint; + size_t ns = header->seq->elements[10]->uint; + size_t ar = header->seq->elements[11]->uint; parsed_token_t *questions = p->ast->seq->elements[1]; if (questions->seq->used != qd) - return 0; + return false; parsed_token_t *rrs = p->ast->seq->elements[2]; if (an+ns+ar != rrs->seq->used) - return 0; + return false; + return true; } parser_t* init_parser() { @@ -60,9 +61,21 @@ parser_t* init_parser() { uint16(), // ARCOUNT NULL); + const parser_t *type = int_range(uint16(), 1, 16); + + const parser_t *qtype = choice(type, + int_range(uint16(), 252, 255), + NULL); + + const parser_t *class = int_range(uint16(), 1, 4); + + const parser_t *qclass = choice(class, + int_range(uint16(), 255, 255), + NULL); + const parser_t *dns_question = sequence(length_value(uint8(), uint8()), // QNAME - uint16(), // QTYPE - uint16(), // QCLASS + qtype, // QTYPE + qclass, // QCLASS NULL); const parser_t *letter = choice(ch_range('a', 'z'), diff --git a/src/hammer.c b/src/hammer.c index cad143ab..bb033114 100644 --- a/src/hammer.c +++ b/src/hammer.c @@ -19,10 +19,11 @@ #include "internal.h" #include "allocator.h" #include <assert.h> -#include <string.h> -#include <stdarg.h> #include <ctype.h> #include <error.h> +#include <limits.h> +#include <stdarg.h> +#include <string.h> #define a_new_(arena, typ, count) ((typ*)arena_malloc((arena), sizeof(typ)*(count))) #define a_new(typ, count) a_new_(state->arena, typ, count) @@ -407,10 +408,34 @@ static parse_result_t* parse_int_range(void *env, parse_state_t *state) { const parser_t* int_range(const parser_t *p, const int64_t lower, const int64_t upper) { struct bits_env *b_env = p->env; - // p must be an integer parser, which means it's using parse_bits; - // if it's a uint parser, it can't be uint64 + // p must be an integer parser, which means it's using parse_bits assert_message(p->fn == parse_bits, "int_range requires an integer parser"); + // if it's a uint parser, it can't be uint64 assert_message(!(b_env->signedp) ? (b_env->length < 64) : true, "int_range can't use a uint64 parser"); + // and regardless, the bounds need to fit in the parser in question + switch(b_env->length) { + case 32: + if (b_env->signedp) + assert_message(lower >= INT_MIN && upper <= INT_MAX, "bounds for 32-bit signed integer exceeded"); + else + assert_message(lower >= 0 && upper <= UINT_MAX, "bounds for 32-bit unsigned integer exceeded"); + break; + case 16: + if (b_env->signedp) + assert_message(lower >= SHRT_MIN && upper <= SHRT_MAX, "bounds for 16-bit signed integer exceeded"); + else + assert_message(lower >= 0 && upper <= USHRT_MAX, "bounds for 16-bit unsigned integer exceeded"); + break; + case 8: + if (b_env->signedp) + assert_message(lower >= SCHAR_MIN && upper <= SCHAR_MAX, "bounds for 8-bit signed integer exceeded"); + else + assert_message(lower >= 0 && upper <= UCHAR_MAX, "bounds for 8-bit unsigned integer exceeded"); + break; + default: + // how'd that happen? if we got here, this parser is broken. + return NULL; + } range_t *r_env = g_new(range_t, 1); r_env->p = p; @@ -557,24 +582,6 @@ typedef struct { } two_parsers_t; size_t accumulate_size(parse_result_t *pr) { - if (NULL != ((parse_result_t*)pr)->ast) { - switch (pr->ast->token_type) { - case TT_BYTES: - return pr->ast->bytes.len; - case TT_SINT: - case TT_UINT: - return sizeof(pr->ast->uint); - case TT_SEQUENCE: { - counted_array_t *arr = pr->ast->seq; - size_t ret = 0; - for (size_t i = 0; i < arr->used; i++) - ret += accumulate_size(arr->elements[i]); - return ret; - } - default: - return 0; - } - } // no else, if the AST is null then acc doesn't change return 0; } diff --git a/src/hammer.h b/src/hammer.h index c59cdbc6..ae6346c4 100644 --- a/src/hammer.h +++ b/src/hammer.h @@ -41,11 +41,13 @@ typedef enum token_type { TT_MAX } token_type_t; +typedef struct parsed_token parsed_token_t; + typedef struct counted_array { size_t capacity; size_t used; arena_t arena; - void **elements; + parsed_token_t **elements; } counted_array_t; typedef struct parsed_token { -- GitLab