From 788a4c1f9e78700049c60ff2ec409cbee923beb8 Mon Sep 17 00:00:00 2001
From: Selva Nair <selva.nair@gmail.com>
Date: Thu, 4 Aug 2022 20:22:21 -0400
Subject: [PATCH] Do not tokenize comments -- save it as a string

- Comments (whole line or trailing segment) are assigned as
  a single string to ce->comment. The comment character is
  preserved.

- Also some bug fixes and error logging:
    Initialize status variable before use
    Do not parse escaped single quote (matches openvpn.exe)
    Log parsing error
    Remove leading "--" from first token

Signed-off-by: Selva Nair <selva.nair@gmail.com>
---
 config_parser.c | 36 ++++++++++++++++++++++++++++++++----
 config_parser.h |  1 +
 2 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/config_parser.c b/config_parser.c
index c2e20d3..8d4b274 100644
--- a/config_parser.c
+++ b/config_parser.c
@@ -30,10 +30,17 @@
 static int
 legal_escape(wchar_t c)
 {
-    wchar_t *escapes = L"\"\' \\"; /* space, ", ' or backslash */
+    wchar_t *escapes = L"\" \\"; /* ", space, and backslash */
     return (wcschr(escapes, c) != NULL);
 }
 
+static int
+is_comment(wchar_t *s)
+{
+    wchar_t *comment_chars = L";#";
+    return (s && (wcschr(comment_chars, s[0]) != NULL));
+}
+
 static int
 copy_token(wchar_t **dest, wchar_t **src, wchar_t* delim)
 {
@@ -49,6 +56,7 @@ copy_token(wchar_t **dest, wchar_t **src, wchar_t* delim)
         }
         else if (*p == L'\\')
         {
+            MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Parse error in copy_token: illegal backslash");
             return -1; /* parse error -- illegal backslash in input */
         }
         else
@@ -68,7 +76,7 @@ tokenize(config_entry_t *ce)
     p = ce->line;
     s = ce->sline;
     unsigned int i = 0;
-    int status;
+    int status = 0;
 
     for ( ; *p != L'\0';  p++, s++)
     {
@@ -92,9 +100,23 @@ tokenize(config_entry_t *ce)
             p++;
             status = copy_token(&s, &p, L"\"");
         }
+        else if (is_comment(p))
+        {
+            /* store rest of the line as comment -- remove from tokens */
+            ce->comment = s;
+            wcsncpy(s, p, wcslen(p));
+            ce->tokens[--i] = NULL;
+            break;
+        }
         else
+        {
             status = copy_token(&s, &p, L" \t");
-        if (status != 0) return status;
+        }
+
+        if (status != 0)
+        {
+            return status;
+        }
 
         if (*p == L'\0') break;
     }
@@ -122,7 +144,7 @@ config_readline(FILE *fd, int first)
     config_entry_t *ce = calloc(sizeof(*ce), 1);
     if (!ce)
     {
-       MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Out of memory in tokenize");
+       MsgToEventLog(EVENTLOG_ERROR_TYPE, L"Out of memory in config_readline");
        return NULL;
     }
 
@@ -137,6 +159,12 @@ config_readline(FILE *fd, int first)
         return NULL;
     }
 
+    /* skip leading "--" in first token if any */
+    if (ce->ntokens > 0)
+    {
+        ce->tokens[0] += wcsspn(ce->tokens[0], L"--");
+    }
+
     return ce;
 }
 
diff --git a/config_parser.h b/config_parser.h
index 4848aed..acffa9b 100644
--- a/config_parser.h
+++ b/config_parser.h
@@ -30,6 +30,7 @@ struct config_entry {
     wchar_t line[MAX_LINE_LENGTH];
     wchar_t sline[MAX_LINE_LENGTH];
     wchar_t *tokens[16];
+    wchar_t *comment;
     int ntokens;
     config_entry_t *next;
 };