[gcr] egg-asn1x: Fix corner case where long DER length overflows



commit b0bf0aeb6688c7ff3795f42f5e1a5bee27e52bf6
Author: Stef Walter <stefw gnome org>
Date:   Wed Nov 7 21:27:24 2012 +0100

    egg-asn1x: Fix corner case where long DER length overflows
    
     * Better detection of the case where TLV length overflows
       the size of an int.

 egg/egg-asn1x.c |   34 +++++++++++++++++++++++-----------
 1 files changed, 23 insertions(+), 11 deletions(-)
---
diff --git a/egg/egg-asn1x.c b/egg/egg-asn1x.c
index 105540f..c35cf1e 100644
--- a/egg/egg-asn1x.c
+++ b/egg/egg-asn1x.c
@@ -669,6 +669,7 @@ atlv_parse_cls_tag (const guchar *at,
 {
 	gint punt, ris, last;
 	gint n_data;
+	guchar val;
 
 	g_assert (end >= at);
 	g_assert (cls != NULL);
@@ -690,23 +691,27 @@ atlv_parse_cls_tag (const guchar *at,
 	} else {
 		punt = 1;
 		ris = 0;
-		while (punt <= n_data && at[punt] & 128) {
-			int last = ris;
-			ris = ris * 128 + (at[punt++] & 0x7F);
+		while (punt <= n_data) {
+			val = at[punt++];
+			last = ris;
+			ris = ris * 128;
 
 			/* wrapper around, and no bignums... */
 			if (ris < last)
 				return FALSE;
-		}
 
-		if (punt >= n_data)
-			return FALSE;
+			last = ris;
+			ris += (val & 0x7F);
+
+			/* wrapper around, and no bignums... */
+			if (ris < last)
+				return FALSE;
 
-		last = ris;
-		ris = ris * 128 + (at[punt++] & 0x7F);
+			if ((val & 0x7F) == val)
+				break;
+		}
 
-		/* wrapper around, and no bignums... */
-		if (ris < last)
+		if (punt >= n_data)
 			return FALSE;
 
 		*off = punt;
@@ -753,7 +758,14 @@ atlv_parse_length (const guchar *at,
 			ans = 0;
 			while (punt <= k && punt < n_data) {
 				last = ans;
-				ans = ans * 256 + at[punt++];
+				ans = ans * 256;
+
+				/* we wrapped around, no bignum support... */
+				if (ans < last)
+					return -2;
+
+				last = ans;
+				ans += at[punt++];
 
 				/* we wrapped around, no bignum support... */
 				if (ans < last)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]