Package: strace
Version: 4.5.17+cvs080723-2
Severity: important
Tags: patch


I have decided to notify you of the "off by one" BUG in string_quote.
This stuff seems to be fixed in CVS HEAD between revision 1.80 and 1.81
for util.c. For your convenience I have attached the patch as lifted
from CVS. Applying attached patch fixed the BUG for me for a debian
lenny system running on x86_64 arch (AMD64).

Regard,
Joachim Falk

-- System Information:
Debian Release: lenny/sid
  APT prefers testing
  APT policy: (520, 'testing')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.18-openvz-028stab059.6 (SMP w/2 CPU cores)
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages strace depends on:
ii  libc6                         2.7-16     GNU C Library: Shared libraries

strace recommends no packages.

strace suggests no packages.

-- no debconf information
2008-11-09  Dmitry V. Levin  <l...@altlinux.org>

        * util.c (string_quote): Fix support for NUL-terminated string.
        Add comments.
        (printpathn): Fix the case when "..." was appended to the output
        but no truncation was actually made.  Add comments.
        (printstr): Fix memory allocation.  Fix two cases when "..." was
        appended to the output but no truncation was actually made.
        Add comments.

--- util.c.orig 2008-07-19 15:08:55.000000000 +0200
+++ util.c      2008-12-08 18:46:21.000000000 +0100
@@ -407,6 +407,12 @@
 
 static char path[MAXPATHLEN + 1];
 
+/*
+ * Quote string `instr' of length `size'
+ * Write up to (3 + `size' * 4) bytes to `outstr' buffer.
+ * If `len' < 0, treat `instr' as a NUL-terminated string
+ * and quote at most (`size' - 1) bytes.
+ */
 static int
 string_quote(const char *instr, char *outstr, int len, int size)
 {
@@ -417,12 +423,18 @@
        if (xflag > 1)
                usehex = 1;
        else if (xflag) {
+               /* Check for presence of symbol which require
+                  to hex-quote the whole string. */
                for (i = 0; i < size; ++i) {
                        c = ustr[i];
-                       if (len < 0 && i == size - 2 && c != '\0')
-                               ++i;
-                       if (len < 0 && c == '\0')
-                               break;
+                       /* Check for NUL-terminated string. */
+                       if (len < 0) {
+                               if (c == '\0')
+                                       break;
+                               /* Quote at most size - 1 bytes. */
+                               if (i == size - 1)
+                                       continue;
+                       }
                        if (!isprint(c) && !isspace(c)) {
                                usehex = 1;
                                break;
@@ -433,20 +445,31 @@
        *s++ = '\"';
 
        if (usehex) {
+               /* Hex-quote the whole string. */
                for (i = 0; i < size; ++i) {
                        c = ustr[i];
-                       if (len < 0 && c == '\0')
-                               break;
+                       /* Check for NUL-terminated string. */
+                       if (len < 0) {
+                               if (c == '\0')
+                                       break;
+                               /* Quote at most size - 1 bytes. */
+                               if (i == size - 1)
+                                       continue;
+                       }
                        sprintf(s, "\\x%02x", c);
                        s += 4;
                }
        } else {
                for (i = 0; i < size; ++i) {
                        c = ustr[i];
-                       if (len < 0 && i == size - 2 && c != '\0')
-                               ++i;
-                       if (len < 0 && c == '\0')
-                               break;
+                       /* Check for NUL-terminated string. */
+                       if (len < 0) {
+                               if (c == '\0')
+                                       break;
+                               /* Quote at most size - 1 bytes. */
+                               if (i == size - 1)
+                                       continue;
+                       }
                        switch (c) {
                                case '\"': case '\\':
                                        *s++ = '\\';
@@ -495,18 +518,25 @@
        return i == size;
 }
 
+/*
+ * Print path string specified by address `addr' and length `n'.
+ * If path length exceeds `n', append `...' to the output.
+ */
 void
 printpathn(struct tcb *tcp, long addr, int n)
 {
-       if (n > sizeof path - 1)
-               n = sizeof path - 1;
-
-       if (addr == 0) {
+       if (!addr) {
                tprintf("NULL");
                return;
        }
 
+       /* Cap path length to the path buffer size,
+          and NUL-terminate the buffer. */
+       if (n > sizeof path - 1)
+               n = sizeof path - 1;
        path[n] = '\0';
+
+       /* Fetch one byte more to find out whether path length > n. */
        if (umovestr(tcp, addr, n + 1, path) < 0)
                tprintf("%#lx", addr);
        else {
@@ -515,7 +545,8 @@
 
                if (trunc)
                        path[n] = '\0';
-               if (string_quote(path, outstr, -1, n + 1) || trunc)
+               (void) string_quote(path, outstr, -1, n + 1);
+               if (trunc)
                        strcat(outstr, "...");
                tprintf("%s", outstr);
        }
@@ -527,6 +558,11 @@
        printpathn(tcp, addr, sizeof path - 1);
 }
 
+/*
+ * Print string specified by address `addr' and length `len'.
+ * If `len' < 0, treat the string as a NUL-terminated string.
+ * If string length exceeds `max_strlen', append `...' to the output.
+ */
 void
 printstr(struct tcb *tcp, long addr, int len)
 {
@@ -538,32 +574,39 @@
                tprintf("NULL");
                return;
        }
-       if (!str) {
-               if ((str = malloc(max_strlen + 1)) == NULL
-                   || (outstr = malloc(4*max_strlen
-                                       + sizeof "\"\"...")) == NULL) {
-                       fprintf(stderr, "out of memory\n");
-                       tprintf("%#lx", addr);
-                       return;
-               }
+       /* Allocate static buffers if they are not allocated yet. */
+       if (!str)
+               str = malloc(max_strlen + 1);
+       if (!outstr)
+               outstr = malloc(4 * max_strlen + sizeof "\"...\"");
+       if (!str || !outstr) {
+               fprintf(stderr, "out of memory\n");
+               tprintf("%#lx", addr);
+               return;
        }
 
        if (len < 0) {
+               /*
+                * Treat as a NUL-terminated string: fetch one byte more
+                * because string_quote() quotes one byte less.
+                */
                size = max_strlen + 1;
+               str[max_strlen] = '\0';
                if (umovestr(tcp, addr, size, str) < 0) {
                        tprintf("%#lx", addr);
                        return;
                }
        }
        else {
-               size = MIN(len, max_strlen + 1);
+               size = MIN(len, max_strlen);
                if (umoven(tcp, addr, size, str) < 0) {
                        tprintf("%#lx", addr);
                        return;
                }
        }
 
-       if (string_quote(str, outstr, len, size))
+       if (string_quote(str, outstr, len, size) &&
+           (len < 0 || len > max_strlen))
                strcat(outstr, "...");
 
        tprintf("%s", outstr);

Reply via email to