From 0597c1a1a47ff5593a7c6a9d9505195a960383e7 Mon Sep 17 00:00:00 2001
From: Thomas Blume <Thomas.Blume@suse.com>
Date: Tue, 24 Jan 2023 17:21:28 +0100
Subject: [PATCH] CVE-2022-38725 Fix buffer handling of syslog parsers

bsc#1207460
---
 lib/str-format.c                     | 59 +++++++++++++++-------------
 modules/syslogformat/syslog-format.c | 15 ++++---
 2 files changed, 41 insertions(+), 33 deletions(-)

diff --git a/lib/str-format.c b/lib/str-format.c
index 4b9e20613..31182fcda 100644
--- a/lib/str-format.c
+++ b/lib/str-format.c
@@ -303,41 +303,43 @@ scan_day_abbrev(const gchar **buf, gint *left, gint *wday)
 {
   *wday = -1;
 
-  if (*left < 3)
+  const gsize abbrev_length = 3;
+
+  if (*left < abbrev_length)
     return FALSE;
 
   switch (**buf)
     {
     case 'S':
-      if (memcmp(*buf, "Sun", 3) == 0)
+      if (memcmp(*buf, "Sun", abbrev_length) == 0)
         *wday = 0;
-      else if (memcmp(*buf, "Sat", 3) == 0)
+      else if (memcmp(*buf, "Sat", abbrev_length) == 0)
         *wday = 6;
       break;
     case 'M':
-      if (memcmp(*buf, "Mon", 3) == 0)
+      if (memcmp(*buf, "Mon", abbrev_length) == 0)
         *wday = 1;
       break;
     case 'T':
-      if (memcmp(*buf, "Tue", 3) == 0)
+      if (memcmp(*buf, "Tue", abbrev_length) == 0)
         *wday = 2;
-      else if (memcmp(*buf, "Thu", 3) == 0)
+      else if (memcmp(*buf, "Thu", abbrev_length) == 0)
         *wday = 4;
       break;
     case 'W':
-      if (memcmp(*buf, "Wed", 3) == 0)
-        *wday = 3;
+      if (memcmp(*buf, "Wed", abbrev_length) == 0)
+        *wday = abbrev_length;
       break;
     case 'F':
-      if (memcmp(*buf, "Fri", 3) == 0)
+      if (memcmp(*buf, "Fri", abbrev_length) == 0)
         *wday = 5;
       break;
     default:
       return FALSE;
     }
 
-  (*buf) += 3;
-  (*left) -= 3;
+  (*buf) += abbrev_length;
+  (*left) -= abbrev_length;
   return TRUE;
 }
 
@@ -346,57 +348,60 @@ scan_month_abbrev(const gchar **buf, gint *left, gint *mon)
 {
   *mon = -1;
 
-  if (*left < 3)
+  const gsize abbrev_length = 3;
+
+  if (*left < abbrev_length)
+
     return FALSE;
 
   switch (**buf)
     {
     case 'J':
-      if (memcmp(*buf, "Jan", 3) == 0)
+      if (memcmp(*buf, "Jan", abbrev_length) == 0)
         *mon = 0;
-      else if (memcmp(*buf, "Jun", 3) == 0)
+      else if (memcmp(*buf, "Jun", abbrev_length) == 0)
         *mon = 5;
-      else if (memcmp(*buf, "Jul", 3) == 0)
+      else if (memcmp(*buf, "Jul", abbrev_length) == 0)
         *mon = 6;
       break;
     case 'F':
-      if (memcmp(*buf, "Feb", 3) == 0)
+      if (memcmp(*buf, "Feb", abbrev_length) == 0)
         *mon = 1;
       break;
     case 'M':
-      if (memcmp(*buf, "Mar", 3) == 0)
+      if (memcmp(*buf, "Mar", abbrev_length) == 0)
         *mon = 2;
-      else if (memcmp(*buf, "May", 3) == 0)
+      else if (memcmp(*buf, "May", abbrev_length) == 0)
         *mon = 4;
       break;
     case 'A':
-      if (memcmp(*buf, "Apr", 3) == 0)
-        *mon = 3;
-      else if (memcmp(*buf, "Aug", 3) == 0)
+      if (memcmp(*buf, "Apr", abbrev_length) == 0)
+        *mon = abbrev_length;
+      else if (memcmp(*buf, "Aug", abbrev_length) == 0)
         *mon = 7;
       break;
     case 'S':
-      if (memcmp(*buf, "Sep", 3) == 0)
+      if (memcmp(*buf, "Sep", abbrev_length) == 0)
         *mon = 8;
       break;
     case 'O':
-      if (memcmp(*buf, "Oct", 3) == 0)
+      if (memcmp(*buf, "Oct", abbrev_length) == 0)
         *mon = 9;
       break;
     case 'N':
-      if (memcmp(*buf, "Nov",3 ) == 0)
+      if (memcmp(*buf, "Nov",abbrev_length ) == 0)
         *mon = 10;
       break;
     case 'D':
-      if (memcmp(*buf, "Dec", 3) == 0)
+      if (memcmp(*buf, "Dec", abbrev_length) == 0)
         *mon = 11;
       break;
     default:
       return FALSE;
     }
 
-  (*buf) += 3;
-  (*left) -= 3;
+  (*buf) += abbrev_length;
+  (*left) -= abbrev_length;
   return TRUE;
 }
 
diff --git a/modules/syslogformat/syslog-format.c b/modules/syslogformat/syslog-format.c
index 9f894b462..d89ee7537 100644
--- a/modules/syslogformat/syslog-format.c
+++ b/modules/syslogformat/syslog-format.c
@@ -201,7 +201,7 @@ log_msg_parse_seq(LogMessage *self, const guchar **data, gint *length)
 
   /* if the next char is not space, then we may try to read a date */
 
-  if (*src != ' ')
+  if (!left || *src != ' ')
     return FALSE;
 
   log_msg_set_value(self, cisco_seqid, (gchar *) *data, *length - left - 1);
@@ -223,6 +223,9 @@ log_msg_parse_date(LogMessage *self, const guchar **data, gint *length, guint pa
 
   cached_g_current_time(&now);
 
+  if (!left)
+    return;
+
   if ((parse_flags & LP_SYSLOG_PROTOCOL) == 0)
     {
       /* Cisco timestamp extensions, the first '*' indicates that the clock is
@@ -276,7 +279,7 @@ log_msg_parse_date(LogMessage *self, const guchar **data, gint *length, guint pa
               src++;
               left--;
             }
-          while (isdigit(*src))
+          while (*length > 0 && isdigit(*src))
             {
               src++;
               left--;
@@ -321,7 +324,7 @@ log_msg_parse_date(LogMessage *self, const guchar **data, gint *length, guint pa
           if (!scan_pix_timestamp((const gchar **) &src, &left, &tm))
             goto error;
 
-          if (*src == ':')
+          if (left && *src == ':')
             {
               src++;
               left--;
@@ -679,7 +682,7 @@ log_msg_parse_sd(LogMessage *self, const guchar **data, gint *length, const MsgF
       open_sd++;
       do
         {
-          if (!isascii(*src) || *src == '=' || *src == ' ' || *src == ']' || *src == '"')
+          if (!left || !isascii(*src) || *src == '=' || *src == ' ' || *src == ']' || *src == '"')
             goto error;
           /* read sd_id */
           pos = 0;
@@ -713,7 +716,7 @@ log_msg_parse_sd(LogMessage *self, const guchar **data, gint *length, const MsgF
           strcpy(sd_value_name, logmsg_sd_prefix);
           /* this strcat is safe, as sd_id_name is at most 32 chars */
           strncpy(sd_value_name + logmsg_sd_prefix_len, sd_id_name, sizeof(sd_value_name) - logmsg_sd_prefix_len);
-          if (*src == ']')
+          if (left && *src == ']')
             {
               log_msg_set_value_by_name(self, sd_value_name, "", 0);
             }
@@ -730,7 +733,7 @@ log_msg_parse_sd(LogMessage *self, const guchar **data, gint *length, const MsgF
               else
                 goto error;
 
-              if (!isascii(*src) || *src == '=' || *src == ' ' || *src == ']' || *src == '"')
+              if (!left || !isascii(*src) || *src == '=' || *src == ' ' || *src == ']' || *src == '"')
                 goto error;
 
               /* read sd-param */
-- 
2.39.0

