From bd9fbade05fefa05c1605e741f6000f75b163509 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sun, 29 Mar 2020 15:35:48 +0800 Subject: [PATCH] libc/netdb: Fix the buffer overwrite in lib_parse_hostfile and other minor issue Signed-off-by: Xiang Xiao Change-Id: I732f63a312ac5c2ddf61ab8084c404bde1b114d4 --- libs/libc/netdb/lib_parsehostfile.c | 52 +++++++++++++---------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/libs/libc/netdb/lib_parsehostfile.c b/libs/libc/netdb/lib_parsehostfile.c index 16da958755d..cddb1a48851 100644 --- a/libs/libc/netdb/lib_parsehostfile.c +++ b/libs/libc/netdb/lib_parsehostfile.c @@ -193,6 +193,13 @@ static ssize_t lib_copystring(FAR FILE *stream, FAR char *ptr, for (; ; ) { + /* There there space to buffer one more character? */ + + if (nwritten >= buflen) + { + return -ERANGE; + } + /* Read the next character from the file */ ch = fgetc(stream); @@ -215,20 +222,13 @@ static ssize_t lib_copystring(FAR FILE *stream, FAR char *ptr, /* Return EOF if nothing has written */ - return nwritten == 0 ? 0 : nwritten + 1; + return nwritten + 1; } /* Write the next string to the buffer */ *ptr++ = ch; nwritten++; - - /* There there space to buffer one more character? */ - - if (nwritten >= buflen) - { - return -ERANGE; - } } } @@ -322,7 +322,7 @@ ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct hostent *host, addrstring[0] = ch; nwritten = lib_copystring(stream, &addrstring[1], &nread, 47, &ch); - if (nwritten <= 0) + if (nwritten < 0) { return nwritten; } @@ -331,7 +331,7 @@ ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct hostent *host, { /* The string was terminated with a newline of EOF */ - return -EAGAIN; + return ch == EOF ? -EPIPE : -EAGAIN; } /* If the address contains a colon, say it is IPv6 */ @@ -347,7 +347,7 @@ ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct hostent *host, } ret = inet_pton(AF_INET6, addrstring, ptr); - if (ret < 0) + if (ret <= 0) { /* Conversion failed. Entry is corrupted */ @@ -355,7 +355,7 @@ ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct hostent *host, return -EAGAIN; } - host->h_addrtype = AF_INET6; + host->h_addrtype = AF_INET6; } else { @@ -368,7 +368,7 @@ ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct hostent *host, } ret = inet_pton(AF_INET, addrstring, ptr); - if (ret < 0) + if (ret <= 0) { /* Conversion failed. Entry is corrupted */ @@ -376,7 +376,7 @@ ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct hostent *host, return -EAGAIN; } - host->h_addrtype = AF_INET; + host->h_addrtype = AF_INET; } info->hi_addrlist[0] = ptr; @@ -397,6 +397,10 @@ ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct hostent *host, { return -EAGAIN; } + else if (buflen == 0) + { + return -ERANGE; + } /* Parse the host name */ @@ -405,7 +409,7 @@ ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct hostent *host, buflen--; nwritten = lib_copystring(stream, ptr, &nread, buflen, &ch); - if (nwritten <= 0) + if (nwritten < 0) { return nwritten; } @@ -424,7 +428,7 @@ ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct hostent *host, /* Parse any host name aliases */ - for (i = 0; i < CONFIG_NETDB_MAX_ALTNAMES; i++) + for (i = 0; ; i++) { /* Skip over any leading whitespace */ @@ -435,6 +439,10 @@ ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct hostent *host, return nread; } + else if (buflen == 0 || i >= CONFIG_NETDB_MAX_ALTNAMES) + { + return -ERANGE; + } /* Parse the next alias */ @@ -447,10 +455,6 @@ ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct hostent *host, { return nwritten; } - else if (nwritten == 0) - { - return nread; - } /* Save the pointer to the beginning of the next alias */ @@ -470,14 +474,6 @@ ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct hostent *host, ptr += nwritten; buflen -= nwritten; } - - /* We get here only if there are more than CONFIG_NETDB_MAX_ALTNAMES - * aliases on the line. Skip to the endof the line, ignoring any - * additional aliases. - */ - - lib_skipline(stream, &nread); - return nread; } #endif /* CONFIG_NETDB_HOSTFILE */