aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatt Widmann <mw@mattwidmann.net>2017-11-25 13:27:59 -0800
committerMatt Widmann <mw@mattwidmann.net>2017-11-25 14:21:02 -0800
commitbab2f8200aea09ad32bbcb2e83404bbd4076a227 (patch)
treed1890a3f0b8cadabb3f57d222e0081848a072570 /src
parent0f9c90e0edd27d2db04d48e7bd98bb46d2c4a918 (diff)
downloadrneovim-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.c35
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.