Index: nss/lib/util/dersubr.c |
diff --git a/nss/lib/util/dersubr.c b/nss/lib/util/dersubr.c |
index 0f4c6d95c4331848fe1d7cd2ed4c4b2880eb37c7..657dd9f0139d5e57470bc49b280e813e25af5d87 100644 |
--- a/nss/lib/util/dersubr.c |
+++ b/nss/lib/util/dersubr.c |
@@ -179,10 +179,12 @@ long |
DER_GetInteger(const SECItem *it) |
{ |
long ival = 0; |
- unsigned len = it->len; |
+ PRBool negative = PR_FALSE; |
+ unsigned int len = it->len; |
+ unsigned int originalLength = len; |
unsigned char *cp = it->data; |
unsigned long overflow = 0x1ffUL << (((sizeof(ival) - 1) * 8) - 1); |
- unsigned long ofloinit; |
+ unsigned long mask = 1; |
PORT_Assert(len); |
if (!len) { |
@@ -190,14 +192,15 @@ DER_GetInteger(const SECItem *it) |
return 0; |
} |
- if (*cp & 0x80) |
- ival = -1L; |
- ofloinit = ival & overflow; |
+ if (*cp & 0x80) { |
+ negative = PR_TRUE; |
+ overflow <<= 1; |
+ } |
while (len) { |
- if ((ival & overflow) != ofloinit) { |
+ if ((ival & overflow) != 0) { |
PORT_SetError(SEC_ERROR_BAD_DER); |
- if (ival < 0) { |
+ if (negative) { |
return LONG_MIN; |
} |
return LONG_MAX; |
@@ -206,6 +209,11 @@ DER_GetInteger(const SECItem *it) |
ival |= *cp++; |
--len; |
} |
+ if (negative && ival && (overflow & ival) == 0) { |
+ mask <<= ((originalLength * 8) - 1); |
+ ival &= ~mask; |
+ ival -= mask; |
+ } |
return ival; |
} |