Просмотр исходного кода

libdpkg: Make str_escape_fmt buffer overflow safe

Make sure we do not write more to the destination buffer than it can
hold.
Guillem Jover лет назад: 15
Родитель
Сommit
141b8a46fa
4 измененных файлов с 28 добавлено и 9 удалено
  1. 2 2
      lib/dpkg/parsehelp.c
  2. 10 2
      lib/dpkg/string.c
  3. 1 1
      lib/dpkg/string.h
  4. 15 4
      lib/dpkg/test/t-string.c

+ 2 - 2
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);

+ 10 - 2
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++;
 	}
 

+ 1 - 1
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

+ 15 - 4
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