diff options
author | nicolson%netscape.com <devnull@localhost> | 2002-03-26 01:13:23 +0000 |
---|---|---|
committer | nicolson%netscape.com <devnull@localhost> | 2002-03-26 01:13:23 +0000 |
commit | fd476cc36bc0675f09f7f9ca9fc7218f8d467e3c (patch) | |
tree | 21694a11241352bea0bca223d52eb3be2943136b | |
parent | 23a769af691b3354fa705688593bdb6cc5c142cc (diff) | |
download | nss-hg-fd476cc36bc0675f09f7f9ca9fc7218f8d467e3c.tar.gz |
Fix 130522: ASN.1 decoder asserts with corrupt input.
r=wtc
-rw-r--r-- | security/nss/lib/util/secasn1d.c | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/security/nss/lib/util/secasn1d.c b/security/nss/lib/util/secasn1d.c index b0f62b75c..4bb0e7d3f 100644 --- a/security/nss/lib/util/secasn1d.c +++ b/security/nss/lib/util/secasn1d.c @@ -1513,7 +1513,11 @@ sec_asn1d_next_substring (sec_asn1d_state *state) if (state->pending) { PORT_Assert (!state->indefinite); - PORT_Assert (child_consumed <= state->pending); + if( child_consumed > state->pending ) { + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return; + } state->pending -= child_consumed; if (state->pending == 0) @@ -1628,7 +1632,11 @@ sec_asn1d_next_in_group (sec_asn1d_state *state) */ if (state->pending) { PORT_Assert (!state->indefinite); - PORT_Assert (child_consumed <= state->pending); + if( child_consumed > state->pending ) { + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return; + } state->pending -= child_consumed; if (state->pending == 0) { @@ -1694,7 +1702,11 @@ sec_asn1d_next_in_sequence (sec_asn1d_state *state) sec_asn1d_free_child (child, PR_FALSE); if (state->pending) { PORT_Assert (!state->indefinite); - PORT_Assert (child_consumed <= state->pending); + if( child_consumed > state->pending ) { + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return; + } state->pending -= child_consumed; if (state->pending == 0) { child->theTemplate++; @@ -1739,8 +1751,13 @@ sec_asn1d_next_in_sequence (sec_asn1d_state *state) */ if (state->indefinite && child->endofcontents) { PORT_Assert (child_consumed == 2); - state->consumed += child_consumed; - state->place = afterEndOfContents; + if( child_consumed != 2 ) { + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + } else { + state->consumed += child_consumed; + state->place = afterEndOfContents; + } } else { PORT_SetError (SEC_ERROR_BAD_DER); state->top->status = decodeError; @@ -2090,8 +2107,12 @@ sec_asn1d_pop_state (sec_asn1d_state *state) state->consumed += state->child->consumed; if (state->pending) { PORT_Assert (!state->indefinite); - PORT_Assert (state->child->consumed <= state->pending); - state->pending -= state->child->consumed; + if( state->child->consumed > state->pending ) { + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + } else { + state->pending -= state->child->consumed; + } } state->child->consumed = 0; } @@ -2176,7 +2197,11 @@ sec_asn1d_during_choice /* cargo'd from next_in_sequence innards */ if( state->pending ) { PORT_Assert(!state->indefinite); - PORT_Assert(child->consumed <= state->pending); + if( child->consumed > state->pending ) { + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return NULL; + } state->pending -= child->consumed; if( 0 == state->pending ) { /* XXX uh.. not sure if I should have stopped this @@ -2432,6 +2457,11 @@ SEC_ASN1DecoderUpdate (SEC_ASN1DecoderContext *cx, /* We should not consume more than we have. */ PORT_Assert (consumed <= len); + if( consumed > len ) { + PORT_SetError (SEC_ERROR_BAD_DER); + cx->status = decodeError; + break; + } /* It might have changed, so we have to update our local copy. */ state = cx->current; |