[dpkg] 86/192: libdpkg: Fix integer overflow in deb(5) version parser
Ximin Luo
infinity0 at debian.org
Tue Oct 17 11:04:03 UTC 2017
This is an automated email from the git hooks/post-receive script.
infinity0 pushed a commit to branch pu/reproducible_builds
in repository dpkg.
commit 59f63342b9121b9d941d3dbd09487c953a113f6e
Author: Guillem Jover <guillem at debian.org>
Date: Sun Aug 20 10:03:33 2017 +0200
libdpkg: Fix integer overflow in deb(5) version parser
The previous code was both not checking for overflows, and triggering
undefined behavior as it was overflowing a signed integer.
Closes: #868356
---
debian/changelog | 2 ++
lib/dpkg/deb-version.c | 27 +++++++++++++++++++++------
lib/dpkg/t/t-deb-version.c | 22 +++++++++++++++++++++-
3 files changed, 44 insertions(+), 7 deletions(-)
diff --git a/debian/changelog b/debian/changelog
index c788319..9278737 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -9,6 +9,8 @@ dpkg (1.19.0) UNRELEASED; urgency=medium
Based on a patch by Niels Thykier <niels at thykier.net>. Closes: #846405
* Always use the binary version for the .buildinfo filename in
dpkg-genbuildinfo. Reported by Raphaël Hertzog <hertzog at debian.org>.
+ * Fix integer overflow in deb(5) format version parser.
+ Closes: #868356
* Perl modules:
- Switch from Dpkg::Util to List::Util, now that the module in the
new required Perl contains the needed functions.
diff --git a/lib/dpkg/deb-version.c b/lib/dpkg/deb-version.c
index ea53a59..cee5ddd 100644
--- a/lib/dpkg/deb-version.c
+++ b/lib/dpkg/deb-version.c
@@ -21,6 +21,7 @@
#include <config.h>
#include <compat.h>
+#include <limits.h>
#include <string.h>
#include <stdlib.h>
@@ -46,19 +47,33 @@ const char *
deb_version_parse(struct deb_version *version, const char *str)
{
const char *str_minor, *end;
- int major = 0;
- int minor = 0;
+ unsigned int major = 0;
+ unsigned int minor = 0;
+ unsigned int divlimit = INT_MAX / 10;
+ int modlimit = INT_MAX % 10;
- for (end = str; *end && c_isdigit(*end); end++)
- major = major * 10 + *end - '0';
+ for (end = str; *end && c_isdigit(*end); end++) {
+ int ord = *end - '0';
+
+ if (major > divlimit || (major == divlimit && ord > modlimit))
+ return _("format version with too big major component");
+
+ major = major * 10 + ord;
+ }
if (end == str)
return _("format version with empty major component");
if (*end != '.')
return _("format version has no dot");
- for (end = str_minor = end + 1; *end && c_isdigit(*end); end++)
- minor = minor * 10 + *end - '0';
+ for (end = str_minor = end + 1; *end && c_isdigit(*end); end++) {
+ int ord = *end - '0';
+
+ if (minor > divlimit || (minor == divlimit && ord > modlimit))
+ return _("format version with too big minor component");
+
+ minor = minor * 10 + ord;
+ }
if (end == str_minor)
return _("format version with empty minor component");
diff --git a/lib/dpkg/t/t-deb-version.c b/lib/dpkg/t/t-deb-version.c
index 2e06907..fef1151 100644
--- a/lib/dpkg/t/t-deb-version.c
+++ b/lib/dpkg/t/t-deb-version.c
@@ -21,6 +21,9 @@
#include <config.h>
#include <compat.h>
+#include <limits.h>
+#include <stdio.h>
+
#include <dpkg/test.h>
#include <dpkg/deb-version.h>
@@ -28,6 +31,7 @@ static void
test_deb_version_parse(void)
{
struct deb_version v;
+ char *vs;
/* Test valid versions. */
test_pass(deb_version_parse(&v, "0.0") == NULL);
@@ -59,12 +63,28 @@ test_deb_version_parse(void)
test_fail(deb_version_parse(&v, "4.4 ") == NULL);
test_fail(deb_version_parse(&v, " 5.5 ") == NULL);
+ /* Test integer limits. */
+ if (asprintf(&vs, "%d.0", INT_MAX) < 0)
+ test_bail("cannot allocate memory for asprintf()");
+ test_pass(deb_version_parse(&v, vs) == NULL);
+ free(vs);
+
+ if (asprintf(&vs, "%d.0", INT_MAX - 1) < 0)
+ test_bail("cannot allocate memory for asprintf()");
+ test_pass(deb_version_parse(&v, vs) == NULL);
+ free(vs);
+
+ if (asprintf(&vs, "%ld.0", (long int)(1L + INT_MAX)) < 0)
+ test_bail("cannot allocate memory for asprintf()");
+ test_fail(deb_version_parse(&v, vs) == NULL);
+ free(vs);
+
/* FIXME: Complete. */
}
TEST_ENTRY(test)
{
- test_plan(21);
+ test_plan(24);
test_deb_version_parse();
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/dpkg.git
More information about the Reproducible-commits
mailing list