Correct offset arithmetic for "choice" templates. Bug 161580.

Patch by wtc@netscape.com
This commit is contained in:
nelsonb%netscape.com 2003-05-17 01:18:53 +00:00
Родитель d9f7fd70f9
Коммит 88601a07fa
2 изменённых файлов: 12 добавлений и 7 удалений

Просмотреть файл

@ -35,7 +35,7 @@
* Support for DEcoding ASN.1 data based on BER/DER (Basic/Distinguished * Support for DEcoding ASN.1 data based on BER/DER (Basic/Distinguished
* Encoding Rules). * Encoding Rules).
* *
* $Id: secasn1d.c,v 1.24 2003-05-03 06:54:48 nelsonb%netscape.com Exp $ * $Id: secasn1d.c,v 1.25 2003-05-17 01:18:52 nelsonb%netscape.com Exp $
*/ */
/* #define DEBUG_ASN1D_STATES 1 */ /* #define DEBUG_ASN1D_STATES 1 */
@ -2298,7 +2298,8 @@ sec_asn1d_before_choice (sec_asn1d_state *state)
} }
child = sec_asn1d_push_state(state->top, state->theTemplate + 1, child = sec_asn1d_push_state(state->top, state->theTemplate + 1,
state->dest, PR_FALSE); (char *)state->dest - state->theTemplate->offset,
PR_FALSE);
if ((sec_asn1d_state *)NULL == child) { if ((sec_asn1d_state *)NULL == child) {
return (sec_asn1d_state *)NULL; return (sec_asn1d_state *)NULL;
} }
@ -2326,6 +2327,7 @@ sec_asn1d_during_choice (sec_asn1d_state *state)
if (child->missing) { if (child->missing) {
unsigned char child_found_tag_modifiers = 0; unsigned char child_found_tag_modifiers = 0;
unsigned long child_found_tag_number = 0; unsigned long child_found_tag_number = 0;
void * dest;
state->consumed += child->consumed; state->consumed += child->consumed;
@ -2347,6 +2349,7 @@ sec_asn1d_during_choice (sec_asn1d_state *state)
return NULL; return NULL;
} }
dest = (char *)child->dest - child->theTemplate->offset;
child->theTemplate++; child->theTemplate++;
if (0 == child->theTemplate->kind) { if (0 == child->theTemplate->kind) {
@ -2355,6 +2358,7 @@ sec_asn1d_during_choice (sec_asn1d_state *state)
state->top->status = decodeError; state->top->status = decodeError;
return (sec_asn1d_state *)NULL; return (sec_asn1d_state *)NULL;
} }
child->dest = (char *)dest + child->theTemplate->offset;
/* cargo'd from next_in_sequence innards */ /* cargo'd from next_in_sequence innards */
if (state->pending) { if (state->pending) {
@ -2400,7 +2404,7 @@ sec_asn1d_during_choice (sec_asn1d_state *state)
} }
if ((void *)NULL != state->dest) { if ((void *)NULL != state->dest) {
/* Store the enum */ /* Store the enum */
int *which = (int *)((char *)state->dest + state->theTemplate->offset); int *which = (int *)state->dest;
*which = (int)child->theTemplate->size; *which = (int)child->theTemplate->size;
} }

Просмотреть файл

@ -35,7 +35,7 @@
* Support for ENcoding ASN.1 data based on BER/DER (Basic/Distinguished * Support for ENcoding ASN.1 data based on BER/DER (Basic/Distinguished
* Encoding Rules). * Encoding Rules).
* *
* $Id: secasn1e.c,v 1.10 2003-03-11 02:31:16 wtc%netscape.com Exp $ * $Id: secasn1e.c,v 1.11 2003-05-17 01:18:53 nelsonb%netscape.com Exp $
*/ */
#include "secasn1.h" #include "secasn1.h"
@ -466,7 +466,7 @@ sec_asn1e_which_choice
) )
{ {
int rv; int rv;
unsigned int which = *(unsigned int *)((char *)src + theTemplate->offset); unsigned int which = *(unsigned int *)src;
for( rv = 1, theTemplate++; theTemplate->kind != 0; rv++, theTemplate++ ) { for( rv = 1, theTemplate++; theTemplate->kind != 0; rv++, theTemplate++ ) {
if( which == theTemplate->size ) { if( which == theTemplate->size ) {
@ -529,7 +529,7 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src,
return 0; return 0;
} }
src2 = (void *)((char *)src + theTemplate[indx].offset); src2 = (void *)((char *)src - theTemplate->offset + theTemplate[indx].offset);
return sec_asn1e_contents_length(&theTemplate[indx], src2, return sec_asn1e_contents_length(&theTemplate[indx], src2,
PR_FALSE, noheaderp); PR_FALSE, noheaderp);
@ -756,7 +756,8 @@ sec_asn1e_write_header (sec_asn1e_state *state)
state->place = afterChoice; state->place = afterChoice;
state = sec_asn1e_push_state(state->top, &state->theTemplate[indx], state = sec_asn1e_push_state(state->top, &state->theTemplate[indx],
state->src, PR_TRUE); (char *)state->src - state->theTemplate->offset,
PR_TRUE);
if( (sec_asn1e_state *)NULL != state ) { if( (sec_asn1e_state *)NULL != state ) {
/* /*