diff options
author | Matt Widmann <mw@mattwidmann.net> | 2017-11-25 13:27:59 -0800 |
---|---|---|
committer | Matt Widmann <mw@mattwidmann.net> | 2017-11-25 14:21:02 -0800 |
commit | bab2f8200aea09ad32bbcb2e83404bbd4076a227 (patch) | |
tree | d1890a3f0b8cadabb3f57d222e0081848a072570 /src | |
parent | 0f9c90e0edd27d2db04d48e7bd98bb46d2c4a918 (diff) | |
download | rneovim-bab2f8200aea09ad32bbcb2e83404bbd4076a227.tar.gz rneovim-bab2f8200aea09ad32bbcb2e83404bbd4076a227.tar.bz2 rneovim-bab2f8200aea09ad32bbcb2e83404bbd4076a227.zip |
io: fix handling EOF in vim_fgets
If an EOF is returned from `fgets`, `vim_fgets` might spin forever, as
it tries to consume the current line.
A `NULL` return value from `fgets` should break out of the function
(unless `errno` is `EINTR`), and then `feof` should be used to check for
the EOF condition on the stream.
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/fileio.c | 35 |
1 files changed, 20 insertions, 15 deletions
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 9214e1e644..1f4cd22754 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -4443,27 +4443,32 @@ char *modname(const char *fname, const char *ext, bool prepend_dot) /// @return true for end-of-file. bool vim_fgets(char_u *buf, int size, FILE *fp) FUNC_ATTR_NONNULL_ALL { - char *eof; -#define FGETS_SIZE 200 - char tbuf[FGETS_SIZE]; + char *retval; + assert(size > 0); buf[size - 2] = NUL; -retry: - errno = 0; - eof = fgets((char *)buf, size, fp); - if (eof == NULL && errno == EINTR) { - goto retry; - } + + do { + errno = 0; + retval = fgets((char *)buf, size, fp); + } while (retval == NULL && errno == EINTR); + if (buf[size - 2] != NUL && buf[size - 2] != '\n') { - buf[size - 1] = NUL; /* Truncate the line */ + char tbuf[200]; + + buf[size - 1] = NUL; // Truncate the line. - /* Now throw away the rest of the line: */ + // Now throw away the rest of the line: do { - tbuf[FGETS_SIZE - 2] = NUL; - ignoredp = fgets((char *)tbuf, FGETS_SIZE, fp); - } while (tbuf[FGETS_SIZE - 2] != NUL && tbuf[FGETS_SIZE - 2] != '\n'); + tbuf[sizeof(tbuf) - 2] = NUL; + errno = 0; + retval = fgets((char *)tbuf, sizeof(tbuf), fp); + if (retval == NULL && errno != EINTR) { + break; + } + } while (tbuf[sizeof(tbuf) - 2] != NUL && tbuf[sizeof(tbuf) - 2] != '\n'); } - return eof == NULL; + return retval ? false : feof(fp); } /// Read 2 bytes from "fd" and turn them into an int, MSB first. |