From cf180114660e5e5a632a8625f0c791716a9c6ecb Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Tue, 9 Feb 2021 09:06:17 -0700 Subject: [PATCH] Some getdelim(3) implementations write a NUL to the buffer on EOF. AIX and Illumos appear to have this behavior. We now preserve the first character of the buffer on EOF to work around this. Fixes reporting of syntax errors on the last line of a file. --- plugins/sudoers/toke.c | 16 ++++++++++++++-- plugins/sudoers/toke.l | 16 ++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) 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; }