The following commit has been merged in the master branch:
commit 141b8a46fae0a80313ca1968f55f45124ce70428
Author: Guillem Jover <[email protected]>
Date:   Sun Oct 31 07:55:47 2010 +0100

    libdpkg: Make str_escape_fmt buffer overflow safe
    
    Make sure we do not write more to the destination buffer than it can
    hold.

diff --git a/lib/dpkg/parsehelp.c b/lib/dpkg/parsehelp.c
index 70a4f8c..a2ed77b 100644
--- a/lib/dpkg/parsehelp.c
+++ b/lib/dpkg/parsehelp.c
@@ -52,7 +52,7 @@ parse_error(struct parsedb_state *ps,
   char buf1[768], buf2[1000], *q;
 
   parse_error_msg(ps, pigp, _("parse error"), buf1);
-  q = str_escape_fmt(buf2, buf1);
+  q = str_escape_fmt(buf2, buf1, sizeof(buf2));
   strcat(q,fmt);
 
   va_start(args, fmt);
@@ -67,7 +67,7 @@ parse_warn(struct parsedb_state *ps,
   char buf1[768], buf2[1000], *q;
 
   parse_error_msg(ps, pigp, _("warning"), buf1);
-  q = str_escape_fmt(buf2, buf1);
+  q = str_escape_fmt(buf2, buf1, sizeof(buf2));
   strcat(q, fmt);
 
   va_start(args, fmt);
diff --git a/lib/dpkg/string.c b/lib/dpkg/string.c
index 2a3fb63..cf53f4f 100644
--- a/lib/dpkg/string.c
+++ b/lib/dpkg/string.c
@@ -27,14 +27,22 @@
 #include <dpkg/string.h>
 
 char *
-str_escape_fmt(char *dst, const char *src)
+str_escape_fmt(char *dst, const char *src, size_t n)
 {
        char *d = dst;
        const char *s = src;
 
+       if (n == 0)
+               return d;
+
        while (*s) {
-               if (*s == '%')
+               if (*s == '%') {
+                       if (n-- <= 2)
+                               break;
                        *d++ = '%';
+               }
+               if (n-- <= 1)
+                       break;
                *d++ = *s++;
        }
 
diff --git a/lib/dpkg/string.h b/lib/dpkg/string.h
index e158356..af879e8 100644
--- a/lib/dpkg/string.h
+++ b/lib/dpkg/string.h
@@ -25,7 +25,7 @@
 
 DPKG_BEGIN_DECLS
 
-char *str_escape_fmt(char *dest, const char *src);
+char *str_escape_fmt(char *dest, const char *src, size_t n);
 char *str_strip_quotes(char *str);
 
 DPKG_END_DECLS
diff --git a/lib/dpkg/test/t-string.c b/lib/dpkg/test/t-string.c
index eb651f1..689f387 100644
--- a/lib/dpkg/test/t-string.c
+++ b/lib/dpkg/test/t-string.c
@@ -32,24 +32,35 @@ test_str_escape_fmt(void)
        char buf[1024], *q;
 
        memset(buf, 'a', sizeof(buf));
-       q = str_escape_fmt(buf, "");
+       q = str_escape_fmt(buf, "", sizeof(buf));
        strcpy(q, " end");
        test_str(buf, ==, " end");
 
        memset(buf, 'a', sizeof(buf));
-       q = str_escape_fmt(buf, "%");
+       q = str_escape_fmt(buf, "%", sizeof(buf));
        strcpy(q, " end");
        test_str(buf, ==, "%% end");
 
        memset(buf, 'a', sizeof(buf));
-       q = str_escape_fmt(buf, "%%%");
+       q = str_escape_fmt(buf, "%%%", sizeof(buf));
        strcpy(q, " end");
        test_str(buf, ==, "%%%%%% end");
 
        memset(buf, 'a', sizeof(buf));
-       q = str_escape_fmt(buf, "%b%b%c%c%%");
+       q = str_escape_fmt(buf, "%b%b%c%c%%", sizeof(buf));
        strcpy(q, " end");
        test_str(buf, ==, "%%b%%b%%c%%c%%%% end");
+
+       /* Test delimited buffer. */
+       memset(buf, 'a', sizeof(buf));
+       q = str_escape_fmt(buf, "%%%", 5);
+       strcpy(q, " end");
+       test_str(buf, ==, "%%%% end");
+
+       memset(buf, 'a', sizeof(buf));
+       q = str_escape_fmt(buf, "%%%", 4);
+       strcpy(q, " end");
+       test_str(buf, ==, "%% end");
 }
 
 static void

-- 
dpkg's main repository


-- 
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]

Reply via email to