]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
bugfix #119: Let example tools read longer RR's than LDNS_MAX_LINELEN
authorWillem Toorop <willem@nlnetlabs.nl>
Mon, 15 Feb 2021 20:54:00 +0000 (21:54 +0100)
committerWillem Toorop <willem@nlnetlabs.nl>
Mon, 15 Feb 2021 20:54:00 +0000 (21:54 +0100)
Changelog
ldns/parse.h
parse.c
rr.c

index 1cb47686ae859672b5111d403076f26590549285..d67658fd309103596cd2c79ba53988be663c1fca 100644 (file)
--- 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
index 0e9034c3414ea88e2c13849dfc2d200d3826c4b7..e98fb95be566b82e9bb44f220685b324c114d144 100644 (file)
@@ -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 947dbb8984f79ebb11f12d92b511b567d8a57789..a6f7871d98fbb3e959e4fa48032ab4fb7a6b11d2 100644 (file)
--- 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 9dec80033c074bf292935ef48de187348941327a..3c483b8c96049bc87584cfda6eeec8ff66272c94 100644 (file)
--- 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) {