Package: polipo
Version: 0.9.9-1
Severity: important
Tags: patch

In atom.c around line 182, the va_list args can be used twice between
va_start and va_end. This results in undefined behaviour according to
the va_start manpage. At least on amd64, it results in a segmentation
fault. I have attached a patch that contains a fix, and as a bonus
another patch that removes a lot of compiler warnings.

-- System Information:
Debian Release: testing/unstable
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.17.7
Locale: LANG=nl_NL.UTF-8, LC_CTYPE=nl_NL.UTF-8 (charmap=UTF-8)

Versions of packages polipo depends on:
ii  libc6                        2.3.6.ds1-4 GNU C Library: Shared libraries

polipo recommends no packages.

-- no debconf information
--- polipo-0.9.9.orig/atom.c    2006-09-02 19:28:22.152075017 +0200
+++ polipo-0.9.9/atom.c 2006-09-02 20:45:20.079873542 +0200
@@ -182,16 +182,19 @@
 
     va_start(args, format);
     n = vsnprintf(buf, 150, format, args);
+    va_end(args);
+
     if(n >= 0 && n < 150) {
         atom = internAtomN(buf, n);
     } else {
+       va_start(args, format);
         s = vsprintf_a(format, args);
         if(s != NULL) {
             atom = internAtom(s);
             free(s);
         }
+       va_end(args);
     }
-    va_end(args);
     return atom;
 }
 
diff -urN polipo-0.9.9.orig/atom.c polipo-0.9.9/atom.c
--- polipo-0.9.9.orig/atom.c	2006-09-02 19:28:22.152075017 +0200
+++ polipo-0.9.9/atom.c	2006-09-02 20:45:20.079873542 +0200
@@ -72,7 +72,7 @@
         atomHashTable[h] = atom;
         used_atoms++;
     }
-    do_log(D_ATOM_REFCOUNT, "A 0x%x %d++\n", (unsigned)atom, atom->refcount);
+    do_log(D_ATOM_REFCOUNT, "A %p %d++\n", atom, atom->refcount);
     atom->refcount++;
     return atom;
 }
@@ -132,7 +132,7 @@
     if(atom == NULL)
         return NULL;
 
-    do_log(D_ATOM_REFCOUNT, "A 0x%x %d++\n", (unsigned)atom, atom->refcount);
+    do_log(D_ATOM_REFCOUNT, "A %p %d++\n", atom, atom->refcount);
     assert(atom->refcount >= 1 && atom->refcount < 50000);
     atom->refcount++;
     return atom;
@@ -144,7 +144,7 @@
     if(atom == NULL)
         return;
 
-    do_log(D_ATOM_REFCOUNT, "A 0x%x %d--\n", (unsigned)atom, atom->refcount);
+    do_log(D_ATOM_REFCOUNT, "A %p %d--\n", atom, atom->refcount);
     assert(atom->refcount >= 1 && atom->refcount < 50000);
 
     atom->refcount--;
diff -urN polipo-0.9.9.orig/client.c polipo-0.9.9/client.c
--- polipo-0.9.9.orig/client.c	2006-09-02 19:28:22.166072523 +0200
+++ polipo-0.9.9/client.c	2006-09-02 19:32:37.060315276 +0200
@@ -105,8 +105,8 @@
     connection->fd = fd;
     connection->timeout = timeout;
 
-    do_log(D_CLIENT_CONN, "Accepted client connection 0x%x\n",
-           (unsigned)connection);
+    do_log(D_CLIENT_CONN, "Accepted client connection %p\n",
+           connection);
 
     connection->flags = CONN_READER;
 
@@ -236,8 +236,8 @@
         return;
     }
     
-    do_log(D_CLIENT_CONN, "Closing client connection 0x%x\n",
-           (unsigned)connection);
+    do_log(D_CLIENT_CONN, "Closing client connection %p\n",
+           connection);
 
     while(1) {
         HTTPRequestPtr requestee;
@@ -1734,8 +1734,8 @@
 
     connection->offset = request->from;
     httpSetTimeout(connection, 120);
-    do_log(D_CLIENT_DATA, "Serving on 0x%x for 0x%x: offset %d len %d\n",
-           (unsigned)connection, (unsigned)object,
+    do_log(D_CLIENT_DATA, "Serving on %p for %p: offset %d len %d\n",
+           connection, object,
            connection->offset, len);
     do_stream_h(IO_WRITE |
                 (connection->te == TE_CHUNKED && len > 0 ? IO_CHUNKED : 0),
@@ -1914,8 +1914,8 @@
         if(len2 == 0) {
             httpSetTimeout(connection, 120);
             do_log(D_CLIENT_DATA, 
-                   "Serving on 0x%x for 0x%x: offset %d len %d\n",
-                   (unsigned)connection, (unsigned)object,
+                   "Serving on %p for %p: offset %d len %d\n",
+                   connection, object,
                    connection->offset, len);
             /* IO_NOTNOW in order to give other clients a chance to run. */
             do_stream(IO_WRITE | IO_NOTNOW |
@@ -1927,8 +1927,8 @@
         } else {
             httpSetTimeout(connection, 120);
             do_log(D_CLIENT_DATA, 
-                   "Serving on 0x%x for 0x%x: offset %d len %d + %d\n",
-                   (unsigned)connection, (unsigned)object,
+                   "Serving on %p for %p: offset %d len %d + %d\n",
+                   connection, object,
                    connection->offset, len, len2);
             do_stream_2(IO_WRITE | IO_NOTNOW |
                         (connection->te == TE_CHUNKED ? IO_CHUNKED : 0) |
diff -urN polipo-0.9.9.orig/http.c polipo-0.9.9/http.c
--- polipo-0.9.9.orig/http.c	2006-09-02 19:28:22.153074839 +0200
+++ polipo-0.9.9/http.c	2006-09-02 19:31:58.367452637 +0200
@@ -199,8 +199,8 @@
         new = scheduleTimeEvent(secs, httpTimeoutHandler,
                                 sizeof(connection), &connection);
         if(!new) {
-            do_log(L_ERROR, "Couldn't schedule timeout for connection 0x%x\n",
-                   (unsigned)connection);
+            do_log(L_ERROR, "Couldn't schedule timeout for connection %p\n",
+                   connection);
             return -1;
         }
     } else {
diff -urN polipo-0.9.9.orig/object.c polipo-0.9.9/object.c
--- polipo-0.9.9.orig/object.c	2006-09-02 19:28:22.162073235 +0200
+++ polipo-0.9.9/object.c	2006-09-02 19:30:56.639145655 +0200
@@ -268,7 +268,7 @@
 ObjectPtr
 retainObject(ObjectPtr object)
 {
-    do_log(D_REFCOUNT, "O 0x%x %d++\n", (unsigned)object, object->refcount);
+    do_log(D_REFCOUNT, "O %p %d++\n", object, object->refcount);
     object->refcount++;
     return object;
 }
@@ -276,7 +276,7 @@
 void
 releaseObject(ObjectPtr object)
 {
-    do_log(D_REFCOUNT, "O 0x%x %d--\n", (unsigned)object, object->refcount);
+    do_log(D_REFCOUNT, "O %p %d--\n", object, object->refcount);
     object->refcount--;
     if(object->refcount == 0) {
         assert(!object->handlers && !(object->flags & OBJECT_INPROGRESS));
@@ -288,7 +288,7 @@
 void
 releaseNotifyObject(ObjectPtr object)
 {
-    do_log(D_REFCOUNT, "O 0x%x %d--\n", (unsigned)object, object->refcount);
+    do_log(D_REFCOUNT, "O %p %d--\n", object, object->refcount);
     object->refcount--;
     if(object->refcount > 0) {
         notifyObject(object);
@@ -302,7 +302,7 @@
 void 
 lockChunk(ObjectPtr object, int i)
 {
-    do_log(D_LOCK, "Lock 0x%x[%d]: ", (unsigned)object, i);
+    do_log(D_LOCK, "Lock %p[%d]: ", object, i);
     assert(i >= 0);
     if(i >= object->numchunks)
         objectSetChunks(object, i + 1);
@@ -313,7 +313,7 @@
 void 
 unlockChunk(ObjectPtr object, int i)
 {
-    do_log(D_LOCK, "Unlock 0x%x[%d]: ", (unsigned)object, i);
+    do_log(D_LOCK, "Unlock %p[%d]: ", object, i);
     assert(i >= 0 && i < object->numchunks);
     assert(object->chunks[i].locked > 0);
     object->chunks[i].locked--;
@@ -467,8 +467,8 @@
 {
     int rc;
 
-    do_log(D_OBJECT_DATA, "Adding data to 0x%x (%d) at %d: %d bytes\n",
-           (unsigned)object, object->length, offset, len);
+    do_log(D_OBJECT_DATA, "Adding data to %p (%d) at %d: %d bytes\n",
+           object, object->length, offset, len);
 
     if(len == 0)
         return 1;

Reply via email to