From: Willem Toorop Date: Mon, 15 Feb 2021 20:54:00 +0000 (+0100) Subject: bugfix #119: Let example tools read longer RR's than LDNS_MAX_LINELEN X-Git-Tag: 1.8.0-rc.1~34 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4294a911d485b8fe7c889f8300667e004793042a;p=thirdparty%2Fldns.git bugfix #119: Let example tools read longer RR's than LDNS_MAX_LINELEN --- diff --git a/Changelog b/Changelog index 1cb47686..d67658fd 100644 --- a/Changelog +++ b/Changelog @@ -22,6 +22,8 @@ non existence of RR types at the root. Thanks ZjYwMj * Set NSEC(3) ttls to the minimum of the MINIMUM field of the SOA record and the TTL of the SOA itself. draft-ietf-dnsop-nsec-ttl + * bugfix #119: Let example tools read longer RR's than + LDNS_MAX_LINELEN 1.7.1 2019-07-26 * bugfix: Manage verification paths for OpenSSL >= 1.1.0 diff --git a/ldns/parse.h b/ldns/parse.h index 0e9034c3..e98fb95b 100644 --- a/ldns/parse.h +++ b/ldns/parse.h @@ -69,6 +69,32 @@ ssize_t ldns_fget_token(FILE *f, char *token, const char *delim, size_t limit); */ ssize_t ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr); +/** + * returns a token/char from the stream f. + * This function deals with ( and ) in the stream, + * and ignores when it finds them. + * \param[in] *f the file to read from + * \param[out] **token this should be a reference to a string buffer in which + * the token is put. A new buffer will be allocated when + * *token is NULL and fixed is false. If the buffer is too + * small to hold the token, the buffer is reallocated with + * double the size (of limit). + * If fixed is true, the string buffer may not be NULL + * and limit must be set to the buffer size. In that case + * no reallocations will be done. + * \param[in,out] *limit reference to the size of the token buffer. Will be + * reset to the new limit of the token buffer if the + * buffer is reallocated. + * \param [in] fixed If fixed is false, the token buffer is allowed to grow + * when needed (by way of reallocation). If true, the token + * buffer will not be resized. + * \param[in] *delim chars at which the parsing should stop + * \param[in] line_nr pointer to an integer containing the current line number (for debugging purposes) + * \return LDNS_STATUS_OK on success, LDNS_STATUS_SYNTAX_EMPTY when no token + * was read and an error otherwise. + */ +ldns_status ldns_fget_token_l_st(FILE *f, char **token, size_t *limit, bool fixed, const char *delim, int *line_nr); + /** * returns a token/char from the buffer b. * This function deals with ( and ) in the buffer, diff --git a/parse.c b/parse.c index 947dbb89..a6f7871d 100644 --- a/parse.c +++ b/parse.c @@ -27,13 +27,14 @@ ldns_fget_token(FILE *f, char *token, const char *delim, size_t limit) return ldns_fget_token_l(f, token, delim, limit, NULL); } -ssize_t -ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr) +ldns_status +ldns_fget_token_l_st(FILE *f, char **token, size_t *limit, bool fixed + , const char *delim, int *line_nr) { int c, prev_c; int p; /* 0 -> no parenthese seen, >0 nr of ( seen */ int com, quoted; - char *t; + char *t, *old_token; size_t i; const char *d; const char *del; @@ -45,13 +46,26 @@ ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *li } else { del = delim; } + if (!token || !limit) + return LDNS_STATUS_NULL; + + if (fixed) { + if (*token == NULL || *limit == 0) + return LDNS_STATUS_NULL; + } else if (*token == NULL) { + *limit = LDNS_MAX_LINELEN; + if (!(*token = LDNS_XMALLOC(char, *limit + 1))) + return LDNS_STATUS_MEM_ERR; + + } else if (*limit == 0) + return LDNS_STATUS_ERR; p = 0; i = 0; com = 0; quoted = 0; prev_c = 0; - t = token; + t = *token; if (del[0] == '"') { quoted = 1; } @@ -79,7 +93,8 @@ ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *li if (p < 0) { /* more ) then ( - close off the string */ *t = '\0'; - return 0; + return i == 0 ? LDNS_STATUS_SYNTAX_EMPTY + : LDNS_STATUS_OK; } /* do something with comments ; */ @@ -113,14 +128,27 @@ ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *li continue; } - if (c == '\n' && p != 0 && t > token) { + if (c == '\n' && p != 0 && t > *token) { /* in parentheses */ if (line_nr) { *line_nr = *line_nr + 1; } - if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) { - *t = '\0'; - return -1; + if (*limit > 0 + && (i >= *limit || (size_t)(t - *token) >= *limit)) { + if (fixed) { + *t = '\0'; + return LDNS_STATUS_SYNTAX_ERR; + } + old_token = *token; + *limit *= 2; + *token = LDNS_XREALLOC(*token, char, *limit + 1); + if (*token == NULL) { + *token = old_token; + *t = '\0'; + return LDNS_STATUS_MEM_ERR; + } + if (*token != old_token) + t = *token + (t - old_token); } *t++ = ' '; prev_c = c; @@ -139,9 +167,22 @@ ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *li if (c != '\0' && c != '\n') { i++; } - if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) { - *t = '\0'; - return -1; + if (*limit > 0 + && (i >= *limit || (size_t)(t - *token) >= *limit)) { + if (fixed) { + *t = '\0'; + return LDNS_STATUS_SYNTAX_ERR; + } + old_token = *token; + *limit *= 2; + *token = LDNS_XREALLOC(*token, char, *limit + 1); + if (*token == NULL) { + *token = old_token; + *t = '\0'; + return LDNS_STATUS_MEM_ERR; + } + if (*token != old_token) + t = *token + (t - old_token); } if (c != '\0' && c != '\n') { *t++ = c; @@ -152,17 +193,13 @@ ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *li } *t = '\0'; if (c == EOF) { - return (ssize_t)i; + return i == 0 ? LDNS_STATUS_SYNTAX_EMPTY : LDNS_STATUS_OK; } - if (i == 0) { - /* nothing read */ - return -1; - } if (p != 0) { - return -1; + return LDNS_STATUS_SYNTAX_ERR; } - return (ssize_t)i; + return i == 0 ? LDNS_STATUS_SYNTAX_EMPTY : LDNS_STATUS_OK; tokenread: if(*del == '"') /* do not skip over quotes, they are significant */ @@ -170,10 +207,19 @@ tokenread: else ldns_fskipcs_l(f, del, line_nr); *t = '\0'; if (p != 0) { - return -1; + return LDNS_STATUS_SYNTAX_ERR; } + return i == 0 ? LDNS_STATUS_SYNTAX_EMPTY : LDNS_STATUS_OK; +} - return (ssize_t)i; + +ssize_t +ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr) +{ + if (ldns_fget_token_l_st(f, &token, &limit, true, delim, line_nr)) + return -1; + else + return (ssize_t)strlen(token); } ssize_t diff --git a/rr.c b/rr.c index 9dec8003..3c483b8c 100644 --- a/rr.c +++ b/rr.c @@ -717,42 +717,23 @@ ldns_rr_new_frm_fp(ldns_rr **newrr, FILE *fp, uint32_t *ttl, ldns_rdf **origin, ldns_status ldns_rr_new_frm_fp_l(ldns_rr **newrr, FILE *fp, uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev, int *line_nr) { - char *line; + char *line = NULL; + size_t limit = 0; const char *endptr; /* unused */ ldns_rr *rr; uint32_t ttl; ldns_rdf *tmp; ldns_status s; - ssize_t size; if (default_ttl) { ttl = *default_ttl; } else { ttl = 0; } - - line = LDNS_XMALLOC(char, LDNS_MAX_LINELEN + 1); - if (!line) { - return LDNS_STATUS_MEM_ERR; - } - /* read an entire line in from the file */ - if ((size = ldns_fget_token_l(fp, line, LDNS_PARSE_SKIP_SPACE, LDNS_MAX_LINELEN, line_nr)) == -1) { - LDNS_FREE(line); - /* if last line was empty, we are now at feof, which is not - * always a parse error (happens when for instance last line - * was a comment) - */ - return LDNS_STATUS_SYNTAX_ERR; - } - - /* we can have the situation, where we've read ok, but still got - * no bytes to play with, in this case size is 0 - */ - if (size == 0) { - LDNS_FREE(line); - return LDNS_STATUS_SYNTAX_EMPTY; - } + if ((s = ldns_fget_token_l_st( fp, &line, &limit, false + , LDNS_PARSE_SKIP_SPACE, line_nr))) + return s; if (strncmp(line, "$ORIGIN", 7) == 0 && isspace((unsigned char)line[7])) { if (*origin) {