I believe the original patch that I submitted for this Debian bug may
have an off-by-one error when reallocating more space for a log message
that is longer than LOG_STR_MAX.  In that case, I use the length of the
new message but don't add one to it (meaning that there will not be room
for the termination character).  This line (which appears TWICE in the
patch):

    logbufflen += (len > LOG_STR_MAX ? len : LOG_STR_MAX);

should probably be something like this (note '>' to '>=' change, too):

    logbufflen += ((len+1) >= LOG_STR_MAX ? (len+1) : LOG_STR_MAX);

It's also somewhat inefficient because it guarantees that a new buffer
will have to be allocated the next time through the loop anyway.  That's
a different issue, though.

Dave


On Mon, Jun 20, 2005 at 01:04:34AM -0500, David D. Kilzer wrote:

> Package: cvsps
> Version: 2.0rc1-5
> Severity: normal
> Tags: patch
> 
> On anoncvs.opensource.apple.com (Apple's anonymous CVS server for
> WebKit), some very long log entries were included in CVS.  I got tired
> of cvsps-2.1 truncating them, so I made the 'logbuff' buffer be
> dynamically allocated.
> 
> Patch attached to implement this feature.
> 
> -- System Information:
> Debian Release: testing/unstable
>   APT prefers unstable
>   APT policy: (500, 'unstable')
> Architecture: powerpc (ppc)
> Shell:  /bin/sh linked to /bin/bash
> Kernel: Linux 2.4.20-ben7
> Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)
> 
> Versions of packages cvsps depends on:
> ii  cvs                         1:1.12.9-13  Concurrent Versions System
> ii  libc6                       2.3.2.ds1-22 GNU C Library: Shared libraries 
> an
> ii  zlib1g                      1:1.2.2-4    compression library - runtime
> 
> cvsps recommends no packages.
> 
> -- no debconf information

diff -urN cvsps-2.1.orig/cache.c cvsps-2.1/cache.c
--- cvsps-2.1.orig/cache.c      2005-05-25 22:39:40.000000000 -0500
+++ cvsps-2.1/cache.c   2005-06-19 21:41:25.000000000 -0500
@@ -108,10 +108,19 @@
     int tag_flags = 0;
     char branchbuff[LOG_STR_MAX] = "";
     int branch_add = 0;
-    char logbuff[LOG_STR_MAX] = "";
+    int logbufflen = LOG_STR_MAX + 1;
+    char * logbuff = malloc(logbufflen);
     time_t cache_date = -1;
     int read_version;
 
+    if (logbuff == NULL)
+    {
+       debug(DEBUG_SYSERROR, "could not malloc %d bytes for logbuff in 
read_cache", logbufflen);
+       exit(1);
+    }
+
+    logbuff[0] = 0;
+
     if (!(fp = cache_open("r")))
        goto out;
 
@@ -299,8 +308,19 @@
            else
            {
                /* Make sure we have enough in the buffer */
-               if (strlen(logbuff)+strlen(buff)<LOG_STR_MAX)
-                   strcat(logbuff, buff);
+               int len = strlen(buff);
+               if (strlen(logbuff) + len >= LOG_STR_MAX)
+               {
+                   logbufflen += (len > LOG_STR_MAX ? len : LOG_STR_MAX);
+                   char * newlogbuff = realloc(logbuff, logbufflen);
+                   if (newlogbuff == NULL)
+                   {
+                       debug(DEBUG_SYSERROR, "could not realloc %d bytes for 
logbuff in read_cache", logbufflen);
+                       exit(1);
+                   }
+                   logbuff = newlogbuff;
+               }
+               strcat(logbuff, buff);
            }
            break;
        case CACHE_NEED_PS_MEMBERS:
@@ -332,6 +352,7 @@
  out_close:
     fclose(fp);
  out:
+    free(logbuff);
     return cache_date;
 }
 
diff -urN cvsps-2.1.orig/cvsps.c cvsps-2.1/cvsps.c
--- cvsps-2.1.orig/cvsps.c      2005-05-25 22:39:40.000000000 -0500
+++ cvsps-2.1/cvsps.c   2005-06-19 23:07:20.000000000 -0500
@@ -265,7 +265,8 @@
     PatchSetMember * psm = NULL;
     char datebuff[20];
     char authbuff[AUTH_STR_MAX];
-    char logbuff[LOG_STR_MAX + 1];
+    int logbufflen = LOG_STR_MAX + 1;
+    char * logbuff = malloc(logbufflen);
     int loglen = 0;
     int have_log = 0;
     char cmd[BUFSIZ];
@@ -273,6 +274,12 @@
     char use_rep_buff[PATH_MAX];
     char * ltype;
 
+    if (logbuff == NULL)
+    {
+       debug(DEBUG_SYSERROR, "could not malloc %d bytes for logbuff in 
load_from_cvs", logbufflen);
+       exit(1);
+    }
+
     if (!no_rlog && !test_log_file && cvs_check_cap(CAP_HAVE_RLOG))
     {
        ltype = "rlog";
@@ -480,24 +487,22 @@
                 */
                if (have_log || !is_revision_metadata(buff))
                {
-                   /* if the log buffer is full, that's it.  
-                    * 
-                    * Also, read lines (fgets) always have \n in them
-                    * which we count on.  So if truncation happens,
-                    * be careful to put a \n on.
-                    * 
-                    * Buffer has LOG_STR_MAX + 1 for room for \0 if
-                    * necessary
-                    */
-                   if (loglen < LOG_STR_MAX)
+                   /* If the log buffer is full, try to reallocate more. */
+                   if (loglen < logbufflen)
                    {
                        int len = strlen(buff);
                        
-                       if (len >= LOG_STR_MAX - loglen)
+                       if (len >= logbufflen - loglen)
                        {
-                           debug(DEBUG_APPMSG1, "WARNING: maximum log length 
exceeded, truncating log");
-                           len = LOG_STR_MAX - loglen;
-                           buff[len - 1] = '\n';
+                           debug(DEBUG_STATUS, "reallocating logbufflen to %d 
bytes for file %s", logbufflen, file->filename);
+                           logbufflen += (len > LOG_STR_MAX ? len : 
LOG_STR_MAX);
+                           char * newlogbuff = realloc(logbuff, logbufflen);
+                           if (newlogbuff == NULL)
+                           {
+                               debug(DEBUG_SYSERROR, "could not realloc %d 
bytes for logbuff in load_from_cvs", logbufflen);
+                               exit(1);
+                           }
+                           logbuff = newlogbuff;
                        }
 
                        debug(DEBUG_STATUS, "appending %s to log", buff);

Reply via email to