Browse Source

libdpkg: Use snprintf() instead of sprintf()

The field width in a format string does not limit the number of bytes
emitted, so we can overflow, even if we are checking the number of bytes
written. Use snprintf() to limit the amount written.

Warned-by: gcc-7
Guillem Jover 7 years ago
parent
commit
f34ce93600
2 changed files with 7 additions and 4 deletions
  1. 2 0
      debian/changelog
  2. 5 4
      lib/dpkg/ar.c

+ 2 - 0
debian/changelog

@@ -9,6 +9,8 @@ dpkg (1.18.23) UNRELEASED; urgency=medium
     Thanks to Jörg Sonnenberger <joerg@netbsd.org>.
   * Add a comment on any C code switch case that falls through. Fixes new
     gcc-7 warnings.
+  * Use snprintf() instead of sprintf() in libdpkg when constructing the ar
+    member header, as we might overflow depending on the input data.
   * Portability:
     - Do not redeclare sys_siglist in libcompat when the system does so.
       Thanks to Thomas Klausner <wiz@NetBSD.org>.

+ 5 - 4
lib/dpkg/ar.c

@@ -173,10 +173,11 @@ dpkg_ar_member_put_header(struct dpkg_ar *ar, struct dpkg_ar_member *member)
 	if (member->size > 9999999999L)
 		ohshit(_("ar member size %jd too large"), (intmax_t)member->size);
 
-	n = sprintf(header, "%-16s%-12lu%-6lu%-6lu%-8lo%-10jd`\n",
-	            member->name, (unsigned long)member->time,
-	            (unsigned long)member->uid, (unsigned long)member->gid,
-	            (unsigned long)member->mode, (intmax_t)member->size);
+	n = snprintf(header, sizeof(struct dpkg_ar_hdr) + 1,
+	             "%-16s%-12lu%-6lu%-6lu%-8lo%-10jd`\n",
+	             member->name, (unsigned long)member->time,
+	             (unsigned long)member->uid, (unsigned long)member->gid,
+	             (unsigned long)member->mode, (intmax_t)member->size);
 	if (n != sizeof(struct dpkg_ar_hdr))
 		ohshit(_("generated corrupt ar header for '%s'"), ar->name);