if (len > 0)
if (len > 0) { PORT_SetError (SEC_ERROR_BAD_DER);
SEC_ASN1DecoderUpdate (SEC_ASN1DecoderContext *cx,		       const char *buf, unsigned long len){    sec_asn1d_state *state = NULL;    unsigned long consumed;    SEC_ASN1EncodingPart what;    sec_asn1d_state *stateEnd = cx->current;    if (cx->status == needBytes)	cx->status = keepGoing;    while (cx->status == keepGoing) {	state = cx->current;	what = SEC_ASN1_Contents;	consumed = 0;#ifdef DEBUG_ASN1D_STATES        printf("\nPLACE = %s, next byte = 0x%02x, %08x[%d]\n",               (state->place >= 0 && state->place <= notInUse) ?               place_names[ state->place ] : "(undefined)",               (unsigned int)((unsigned char *)buf)[ consumed ],               buf, consumed);        dump_states(cx);#endif /* DEBUG_ASN1D_STATES */	switch (state->place) {	  case beforeIdentifier:	    consumed = sec_asn1d_parse_identifier (state, buf, len);	    what = SEC_ASN1_Identifier;	    break;	  case duringIdentifier:	    consumed = sec_asn1d_parse_more_identifier (state, buf, len);	    what = SEC_ASN1_Identifier;	    break;	  case afterIdentifier:	    sec_asn1d_confirm_identifier (state);	    break;	  case beforeLength:	    consumed = sec_asn1d_parse_length (state, buf, len);	    what = SEC_ASN1_Length;	    break;	  case duringLength:	    consumed = sec_asn1d_parse_more_length (state, buf, len);	    what = SEC_ASN1_Length;	    break;	  case afterLength:	    sec_asn1d_prepare_for_contents (state);	    break;	  case beforeBitString:	    consumed = sec_asn1d_parse_bit_string (state, buf, len);	    break;	  case duringBitString:	    consumed = sec_asn1d_parse_more_bit_string (state, buf, len);	    break;	  case duringConstructedString:	    sec_asn1d_next_substring (state);	    break;	  case duringGroup:	    sec_asn1d_next_in_group (state);	    break;	  case duringLeaf:	    consumed = sec_asn1d_parse_leaf (state, buf, len);	    break;	  case duringSaveEncoding:	    sec_asn1d_reuse_encoding (state);	    if (cx->status == decodeError) {		/* recursive call has already popped all states from stack.		** Bail out quickly.		*/		return SECFailure;	    }	    if (cx->status == needBytes) {		/* recursive call wanted more data. Fatal. Clean up below. */		cx->status = decodeError;	    }	    break;	  case duringSequence:	    sec_asn1d_next_in_sequence (state);	    break;	  case afterConstructedString:	    sec_asn1d_concat_substrings (state);	    break;	  case afterExplicit:	  case afterImplicit:	  case afterInline:	  case afterPointer:	    sec_asn1d_absorb_child (state);	    break;	  case afterGroup:	    sec_asn1d_concat_group (state);	    break;	  case afterSaveEncoding:	    /* SEC_ASN1DecoderUpdate has called itself recursively to 	    ** decode SAVEd encoded data, and now is done decoding that.	    ** Return to the calling copy of SEC_ASN1DecoderUpdate.	    */	    return SECSuccess;	  case beforeEndOfContents:	    sec_asn1d_prepare_for_end_of_contents (state);	    break;	  case duringEndOfContents:	    consumed = sec_asn1d_parse_end_of_contents (state, buf, len);	    what = SEC_ASN1_EndOfContents;	    break;	  case afterEndOfContents:	    sec_asn1d_pop_state (state);	    break;          case beforeChoice:            state = sec_asn1d_before_choice(state);            break;          case duringChoice:            state = sec_asn1d_during_choice(state);            break;          case afterChoice:            sec_asn1d_after_choice(state);            break;	  case notInUse:	  default:	    /* This is not an error, but rather a plain old BUG! */	    PORT_Assert (0);	    PORT_SetError (SEC_ERROR_BAD_DER);	    cx->status = decodeError;	    break;	}	if (cx->status == decodeError)	    break;	/* 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;	/* If it is NULL, we have popped all the way to the top.  */	if (state == NULL) {	    PORT_Assert (consumed == 0);#if 0	/* XXX I want this here, but it seems that we have situations (like	 * downloading a pkcs7 cert chain from some issuers) that give us a	 * length which is greater than the entire encoding.  So, we cannot	 * have this be an error.	 */	    if (len > 0)		cx->status = decodeError;	    else#endif		cx->status = allDone;	    break;	}	else if (state->theTemplate->kind == SEC_ASN1_SKIP_REST) {	    cx->status = allDone;	    break;	}	  	if (consumed == 0)	    continue;	/*	 * The following check is specifically looking for an ANY	 * that is *not* also an INNER, because we need to save aside	 * all bytes in that case -- the contents parts will get	 * handled like all other contents, and the end-of-contents	 * bytes are added by the concat code, but the outer header	 * bytes need to get saved too, so we do them explicitly here.	 */	if (state->underlying_kind == SEC_ASN1_ANY	    && !cx->filter_only && (what == SEC_ASN1_Identifier				    || what == SEC_ASN1_Length)) {	    sec_asn1d_record_any_header (state, buf, consumed);	}	/*	 * We had some number of good, accepted bytes.  If the caller	 * has registered to see them, pass them along.	 */	if (state->top->filter_proc != NULL) {	    int depth;	    depth = state->depth;	    if (what == SEC_ASN1_EndOfContents && !state->indefinite) {		PORT_Assert (state->parent != NULL			     && state->parent->indefinite);		depth--;		PORT_Assert (depth == state->parent->depth);	    }	    (* state->top->filter_proc) (state->top->filter_arg,					 buf, consumed, depth, what);	}	state->consumed += consumed;	buf += consumed;	len -= consumed;    }    if (cx->status == decodeError) {	while (state != NULL && stateEnd->parent!=state) {	    sec_asn1d_free_child (state, PR_TRUE);	    state = state->parent;	}#ifdef SEC_ASN1D_FREE_ON_ERROR	/*				 * XXX This does not work because we can				 * end up leaving behind dangling pointers				 * to stuff that was allocated.  In order				 * to make this really work (which would				 * be a good thing, I think), we need to				 * keep track of every place/pointer that				 * was allocated and make sure to NULL it				 * out before we then free back to the mark.					 */	if (cx->their_pool != NULL) {	    PORT_Assert (cx->their_mark != NULL);	    PORT_ArenaRelease (cx->their_pool, cx->their_mark);	}#endif	return SECFailure;    }#if 0	/* XXX This is what I want, but cannot have because it seems we	 * have situations (like when downloading a pkcs7 cert chain from	 * some issuers) that give us a total length which is greater than	 * the entire encoding.  So, we have to allow allDone to have a	 * remaining length greater than zero.  I wanted to catch internal	 * bugs with this, noticing when we do not have the right length.	 * Oh well.	 */    PORT_Assert (len == 0		 && (cx->status == needBytes || cx->status == allDone));#else    PORT_Assert ((len == 0 && cx->status == needBytes)		 || cx->status == allDone);#endif    return SECSuccess;}