[xiph-commits] r18356 - icecast/trunk/log

dm8tbr at svn.xiph.org dm8tbr at svn.xiph.org
Thu Jun 7 08:57:59 PDT 2012


Author: dm8tbr
Date: 2012-06-07 08:57:59 -0700 (Thu, 07 Jun 2012)
New Revision: 18356

Modified:
   icecast/trunk/log/log.c
Log:
This is part of the patch-set addressing CVE-2011-4612. 



Modified: icecast/trunk/log/log.c
===================================================================
--- icecast/trunk/log/log.c	2012-06-07 15:57:11 UTC (rev 18355)
+++ icecast/trunk/log/log.c	2012-06-07 15:57:59 UTC (rev 18356)
@@ -419,11 +419,132 @@
     _unlock_logger ();
 }
 
+static void __vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+    int in_block = 0;
+    int block_size = 0;
+    int block_len;
+    const char * arg;
+    char buf[80];
 
+    for (; *format && size; format++)
+    {
+        if ( !in_block )
+        {
+            if ( *format == '%' ) {
+                in_block = 1;
+                block_size = 0;
+                block_len  = 0;
+            }
+            else
+            {
+                *(str++) = *format;
+                size--;
+            }
+        }
+        else
+        {
+            // TODO: %l*[sdupi] as well as %.4080s and "%.*s
+            arg = NULL;
+            switch (*format)
+            {
+                case 'l':
+                    block_size++;
+                    break;
+                case '.':
+                    // just ignore '.'. If somebody cares: fix it.
+                    break;
+                case '*':
+                    block_len = va_arg(ap, int);
+                    break;
+                case '1':
+                case '2':
+                case '3':
+                case '4':
+                case '5':
+                case '6':
+                case '7':
+                case '8':
+                case '9':
+                    block_len = atoi(format);
+                    for (; *format >= '0' && *format <= '9'; format++);
+                    break;
+                case 'p':
+                    snprintf(buf, sizeof(buf), "%p", (void*)va_arg(ap, void *));
+                    arg = buf;
+                case 'd':
+                case 'i':
+                case 'u':
+                    if (!arg)
+                    {
+                        switch (block_size)
+                        {
+                            case 0:
+                                if (*format == 'u')
+                                    snprintf(buf, sizeof(buf), "%u", (unsigned int)va_arg(ap, unsigned int));
+                                else
+                                    snprintf(buf, sizeof(buf), "%i", (int)va_arg(ap, int));
+                                break;
+                            case 1:
+                                if (*format == 'u')
+                                    snprintf(buf, sizeof(buf), "%lu", (unsigned long int)va_arg(ap, unsigned long int));
+                                else
+                                    snprintf(buf, sizeof(buf), "%li", (long int)va_arg(ap, long int));
+                                break;
+                            case 2:
+                                if (*format == 'u')
+                                    snprintf(buf, sizeof(buf), "%llu", (unsigned long long int)va_arg(ap, unsigned long long int));
+                                else
+                                    snprintf(buf, sizeof(buf), "%lli", (long long int)va_arg(ap, long long int));
+                                break;
+                            default:
+                                snprintf(buf, sizeof(buf), "<<<invalid>>>");
+                                break;
+                        }
+                        arg = buf;
+                    }
+                case 's':
+                case 'H':
+                    // TODO.
+                    if (!arg)
+                        arg = va_arg(ap, const char *);
+                    if (!arg)
+                        arg = "(null)";
+                    if (!block_len)
+                        block_len = strlen(arg);
+
+                    // the if() is the outer structure so the inner for()
+                    // is branch optimized.
+                    if (*format == 'H' )
+                    {
+                        for (; *arg && block_len && size; arg++, size--)
+                        {
+                            if (*arg <= '"')
+                                *(str++) = '.';
+                            else
+                                *(str++) = *arg;
+                        }
+                    }
+                    else
+                    {
+                        for (; *arg && block_len && size; arg++, size--)
+                            *(str++) = *arg;
+                    }
+                    in_block = 0;
+                    break;
+            }
+        }
+    }
+
+    if ( !size )
+        str--;
+
+    *str = 0;
+}
+
 void log_write(int log_id, unsigned priority, const char *cat, const char *func, 
         const char *fmt, ...)
 {
-    static char *prior[] = { "EROR", "WARN", "INFO", "DBUG" };
+    static const char *prior[] = { "EROR", "WARN", "INFO", "DBUG" };
     int datelen;
     time_t now;
     char pre[256];
@@ -434,16 +555,16 @@
     if (loglist[log_id].level < priority) return;
     if (priority > sizeof(prior)/sizeof(prior[0])) return; /* Bad priority */
 
+
     va_start(ap, fmt);
-    vsnprintf(line, LOG_MAXLINELEN, fmt, ap);
+    __vsnprintf(line, sizeof(line), fmt, ap);
+    va_end(ap);
 
     now = time(NULL);
-
-    _lock_logger();
     datelen = strftime (pre, sizeof (pre), "[%Y-%m-%d  %H:%M:%S]", localtime(&now)); 
-
     snprintf (pre+datelen, sizeof (pre)-datelen, " %s %s%s ", prior [priority-1], cat, func);
 
+    _lock_logger();
     if (_log_open (log_id))
     {
         int len = create_log_entry (log_id, pre, line);
@@ -451,8 +572,6 @@
             loglist[log_id].size += len;
     }
     _unlock_logger();
-
-    va_end(ap);
 }
 
 void log_write_direct(int log_id, const char *fmt, ...)



More information about the commits mailing list