After further review, this code should work best (but please feel free
to double-check my work):

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

The attached patch contains this change (but is otherwise unaltered from
the original patch).

NOTE: The last message contained the exact same patch that my initial
bug report did.  Sorry about resending it.

Dave


On Tue, Jul 26, 2005 at 03:14:24PM -0500, David D. Kilzer wrote:

> 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-07-26 15:21:29.716569500 -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+1) : 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-07-26 15:22:02.558230700 -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+1) : 
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