diff --git a/plugins/sudoers/toke.c b/plugins/sudoers/toke.c index c35b24bb1..b56e0a5de 100644 --- a/plugins/sudoers/toke.c +++ b/plugins/sudoers/toke.c @@ -5475,11 +5475,23 @@ sudoers_input(char *buf, yy_size_t max_size) /* Refill line buffer if needed. */ if (avail == 0) { + char ch = sudolinebuf.len ? *sudolinebuf.buf : '\0'; avail = getdelim(&sudolinebuf.buf, &sudolinebuf.size, '\n', sudoersin); if (avail == (size_t)-1) { /* EOF or error. */ - if (ferror(sudoersin) && errno != EINTR) - YY_FATAL_ERROR("input in flex scanner failed"); + if (feof(sudoersin)) { + /* + * Some getdelim(3) implementations write NUL to buf on EOF. + * Restore the first character so we can report syntax errors + * on the last line. + */ + if (sudolinebuf.len != 0) + *sudolinebuf.buf = ch; + } else { + /* This matches the default YY_INPUT behavior. */ + if (errno != EINTR) + YY_FATAL_ERROR("input in flex scanner failed"); + } return 0; } diff --git a/plugins/sudoers/toke.l b/plugins/sudoers/toke.l index 02df387bb..4db86219e 100644 --- a/plugins/sudoers/toke.l +++ b/plugins/sudoers/toke.l @@ -1280,11 +1280,23 @@ sudoers_input(char *buf, yy_size_t max_size) /* Refill line buffer if needed. */ if (avail == 0) { + char ch = sudolinebuf.len ? *sudolinebuf.buf : '\0'; avail = getdelim(&sudolinebuf.buf, &sudolinebuf.size, '\n', sudoersin); if (avail == (size_t)-1) { /* EOF or error. */ - if (ferror(sudoersin) && errno != EINTR) - YY_FATAL_ERROR("input in flex scanner failed"); + if (feof(sudoersin)) { + /* + * Some getdelim(3) implementations write NUL to buf on EOF. + * Restore the first character so we can report syntax errors + * on the last line. + */ + if (sudolinebuf.len != 0) + *sudolinebuf.buf = ch; + } else { + /* This matches the default YY_INPUT behavior. */ + if (errno != EINTR) + YY_FATAL_ERROR("input in flex scanner failed"); + } return 0; }