The branch main has been updated by kp:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=d401664009554167bfc3c1cdb51aba8d1065e92c

commit d401664009554167bfc3c1cdb51aba8d1065e92c
Author:     Kristof Provost <k...@freebsd.org>
AuthorDate: 2025-06-23 13:17:17 +0000
Commit:     Kristof Provost <k...@freebsd.org>
CommitDate: 2025-06-27 14:55:16 +0000

    pfctl: fix reporting of line numbers for included files
    
    Fix (include file ) line number counting by keeping track of the unget
    buffer per file; also use that buffer to expand macros.
    ok sashan@ dennis@ krw@
    
    Obtained from:  OpenBSD, otto <o...@openbsd.org>, 475a466cc5
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sbin/pfctl/parse.y | 122 ++++++++++++++++++++++++++++++++---------------------
 1 file changed, 75 insertions(+), 47 deletions(-)

diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 257a62df76f4..e4cd4883e2c9 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -89,6 +89,10 @@ static struct file {
        TAILQ_ENTRY(file)        entry;
        FILE                    *stream;
        char                    *name;
+       size_t                   ungetpos;
+       size_t                   ungetsize;
+       u_char                  *ungetbuf;
+       int                      eof_reached;
        int                      lineno;
        int                      errors;
 } *file;
@@ -100,8 +104,9 @@ int          yylex(void);
 int             yyerror(const char *, ...);
 int             kw_cmp(const void *, const void *);
 int             lookup(char *);
+int             igetc(void);
 int             lgetc(int);
-int             lungetc(int);
+void            lungetc(int);
 int             findeol(void);
 
 static TAILQ_HEAD(symhead, sym)         symhead = 
TAILQ_HEAD_INITIALIZER(symhead);
@@ -6825,34 +6830,37 @@ lookup(char *s)
        }
 }
 
-#define MAXPUSHBACK    128
+#define        START_EXPAND    1
+#define        DONE_EXPAND             2
 
-static char    *parsebuf;
-static int      parseindex;
-static char     pushback_buffer[MAXPUSHBACK];
-static int      pushback_index = 0;
+static int expanding;
 
 int
-lgetc(int quotec)
+igetc(void)
 {
-       int             c, next;
-
-       if (parsebuf) {
-               /* Read character from the parsebuffer instead of input. */
-               if (parseindex >= 0) {
-                       c = parsebuf[parseindex++];
-                       if (c != '\0')
-                               return (c);
-                       parsebuf = NULL;
-               } else
-                       parseindex++;
+       int c;
+       while (1) {
+               if (file->ungetpos > 0)
+                       c = file->ungetbuf[--file->ungetpos];
+               else
+                       c = getc(file->stream);
+               if (c == START_EXPAND)
+                       expanding = 1;
+               else if (c == DONE_EXPAND)
+                       expanding = 0;
+               else
+                       break;
        }
+       return (c);
+}
 
-       if (pushback_index)
-               return (pushback_buffer[--pushback_index]);
+int
+lgetc(int quotec)
+{
+       int     c, next;
 
        if (quotec) {
-               if ((c = getc(file->stream)) == EOF) {
+               if ((c = igetc()) == EOF) {
                        yyerror("reached end of file while parsing quoted 
string");
                        if (popfile() == EOF)
                                return (EOF);
@@ -6861,8 +6869,8 @@ lgetc(int quotec)
                return (c);
        }
 
-       while ((c = getc(file->stream)) == '\\') {
-               next = getc(file->stream);
+       while ((c = igetc()) == '\\') {
+               next = igetc();
                if (next != '\n') {
                        c = next;
                        break;
@@ -6871,28 +6879,38 @@ lgetc(int quotec)
                file->lineno++;
        }
 
-       while (c == EOF) {
-               if (popfile() == EOF)
-                       return (EOF);
-               c = getc(file->stream);
+       if (c == EOF) {
+               /*
+                * Fake EOL when hit EOF for the first time. This gets line
+                * count right if last line in included file is syntactically
+                * invalid and has no newline.
+                */
+               if (file->eof_reached == 0) {
+                       file->eof_reached = 1;
+                       return ('\n');
+               }
+               while (c == EOF) {
+                       if (popfile() == EOF)
+                               return (EOF);
+                       c = igetc();
+               }
        }
        return (c);
 }
 
-int
+void
 lungetc(int c)
 {
        if (c == EOF)
-               return (EOF);
-       if (parsebuf) {
-               parseindex--;
-               if (parseindex >= 0)
-                       return (c);
+               return;
+       if (file->ungetpos >= file->ungetsize) {
+               void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
+               if (p == NULL)
+                       err(1, "lungetc");
+               file->ungetbuf = p;
+               file->ungetsize *= 2;
        }
-       if (pushback_index < MAXPUSHBACK-1)
-               return (pushback_buffer[pushback_index++] = c);
-       else
-               return (EOF);
+       file->ungetbuf[file->ungetpos++] = c;
 }
 
 int
@@ -6900,14 +6918,9 @@ findeol(void)
 {
        int     c;
 
-       parsebuf = NULL;
-
        /* skip to either EOF or the first real EOL */
        while (1) {
-               if (pushback_index)
-                       c = pushback_buffer[--pushback_index];
-               else
-                       c = lgetc(0);
+               c = lgetc(0);
                if (c == '\n') {
                        file->lineno++;
                        break;
@@ -6935,7 +6948,7 @@ top:
        if (c == '#')
                while ((c = lgetc(0)) != '\n' && c != EOF)
                        ; /* nothing */
-       if (c == '$' && parsebuf == NULL) {
+       if (c == '$' && !expanding) {
                while (1) {
                        if ((c = lgetc(0)) == EOF)
                                return (0);
@@ -6957,8 +6970,13 @@ top:
                        yyerror("macro '%s' not defined", buf);
                        return (findeol());
                }
-               parsebuf = val;
-               parseindex = 0;
+               p = val + strlen(val) - 1;
+               lungetc(DONE_EXPAND);
+               while (p >= val) {
+                       lungetc(*p);
+                       p--;
+               }
+               lungetc(START_EXPAND);
                goto top;
        }
 
@@ -7148,7 +7166,16 @@ pushfile(const char *name, int secret)
                free(nfile);
                return (NULL);
        }
-       nfile->lineno = 1;
+       nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0;
+       nfile->ungetsize = 16;
+       nfile->ungetbuf = malloc(nfile->ungetsize);
+       if (nfile->ungetbuf == NULL) {
+               warn("malloc");
+               fclose(nfile->stream);
+               free(nfile->name);
+               free(nfile);
+               return (NULL);
+       }
        TAILQ_INSERT_TAIL(&files, nfile, entry);
        return (nfile);
 }
@@ -7163,6 +7190,7 @@ popfile(void)
                TAILQ_REMOVE(&files, file, entry);
                fclose(file->stream);
                free(file->name);
+               free(file->ungetbuf);
                free(file);
                file = prev;
                return (0);

Reply via email to