- fixed BER decoder infinite length handling to avoid inifite loop while decoding (LIB61850-516)

v1.6
Michael Zillgith 4 weeks ago
parent 813b62356e
commit cb343b6de6

@ -291,7 +291,8 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/* /*
* Read in the "end of data chunks"'s. * Read in the "end of data chunks"'s.
*/ */
while(ctx->left < 0) { while(ctx->left < 0)
{
ssize_t tl; ssize_t tl;
tl = ber_fetch_tag(ptr, LEFT, &tlv_tag); tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
@ -304,25 +305,36 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/* /*
* Expected <0><0>... * Expected <0><0>...
*/ */
if(((const uint8_t *)ptr)[0] == 0) { if (((const uint8_t*)ptr)[0] == 0)
if(LEFT < 2) { {
if(SIZE_VIOLATION) if (LEFT < 2)
RETURN(RC_FAIL); {
else if (SIZE_VIOLATION)
RETURN(RC_WMORE); RETURN(RC_FAIL);
} else if(((const uint8_t *)ptr)[1] == 0) { else
/* RETURN(RC_WMORE);
* Correctly finished with <0><0>. }
*/ else if (((const uint8_t*)ptr)[1] == 0)
ADVANCE(2); {
ctx->left++; /*
continue; * Correctly finished with <0><0>.
} */
} else { ADVANCE(2);
RETURN(RC_FAIL); ctx->left++;
} continue;
}
/* UNREACHABLE */ else
{
/* this case should not happen when the message is correctly encoded */
RETURN(RC_FAIL);
}
}
else
{
RETURN(RC_FAIL);
}
/* UNREACHABLE */
} }
NEXT_PHASE(ctx); NEXT_PHASE(ctx);

@ -223,34 +223,41 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
case -1: RETURN(RC_FAIL); case -1: RETURN(RC_FAIL);
} }
if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) { if (ctx->left < 0 && ((const uint8_t*)ptr)[0] == 0)
if(LEFT < 2) { {
if(SIZE_VIOLATION) if (LEFT < 2)
RETURN(RC_FAIL); {
else if (SIZE_VIOLATION)
RETURN(RC_WMORE); RETURN(RC_FAIL);
} else if(((const uint8_t *)ptr)[1] == 0) { else
RETURN(RC_WMORE);
if((edx + elements[edx].optional }
== td->elements_count) else if (((const uint8_t*)ptr)[1] == 0)
|| (IN_EXTENSION_GROUP(specs, edx) {
&& specs->ext_before
> td->elements_count)) { if ((edx + elements[edx].optional == td->elements_count) ||
/* (IN_EXTENSION_GROUP(specs, edx) && specs->ext_before > td->elements_count))
* Yeah, baby! Found the terminator {
* of the indefinite length structure. /*
*/ * Yeah, baby! Found the terminator
/* * of the indefinite length structure.
* Proceed to the canonical */
* finalization function. /*
* No advancing is necessary. * Proceed to the canonical
*/ * finalization function.
goto phase3; * No advancing is necessary.
} */
} goto phase3;
} }
}
/* else
{
/* this case should not happen when the message is correctly encoded */
RETURN(RC_FAIL);
}
}
/*
* Find the next available type with this tag. * Find the next available type with this tag.
*/ */
use_bsearch = 0; use_bsearch = 0;
@ -421,25 +428,33 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/* /*
* If expected <0><0>... * If expected <0><0>...
*/ */
if(ctx->left < 0 if (ctx->left < 0 && ((const uint8_t*)ptr)[0] == 0)
&& ((const uint8_t *)ptr)[0] == 0) { {
if(LEFT < 2) { if (LEFT < 2)
if(SIZE_VIOLATION) {
RETURN(RC_FAIL); if (SIZE_VIOLATION)
else RETURN(RC_FAIL);
RETURN(RC_WMORE); else
} else if(((const uint8_t *)ptr)[1] == 0) { RETURN(RC_WMORE);
/* }
* Correctly finished with <0><0>. else if (((const uint8_t*)ptr)[1] == 0)
*/ {
ADVANCE(2); /*
ctx->left++; * Correctly finished with <0><0>.
ctx->phase = 4; */
continue; ADVANCE(2);
} ctx->left++;
} ctx->phase = 4;
continue;
}
else
{
/* this case should not happen when the message is correctly encoded */
RETURN(RC_FAIL);
}
}
if(!IN_EXTENSION_GROUP(specs, td->elements_count) if(!IN_EXTENSION_GROUP(specs, td->elements_count)
|| ctx->phase == 4) { || ctx->phase == 4) {
RETURN(RC_FAIL); RETURN(RC_FAIL);
} }

@ -158,22 +158,31 @@ SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
case -1: RETURN(RC_FAIL); case -1: RETURN(RC_FAIL);
} }
if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) { if (ctx->left < 0 && ((const uint8_t*)ptr)[0] == 0)
if(LEFT < 2) { {
if(SIZE_VIOLATION) if (LEFT < 2)
RETURN(RC_FAIL); {
else if (SIZE_VIOLATION)
RETURN(RC_WMORE); RETURN(RC_FAIL);
} else if(((const uint8_t *)ptr)[1] == 0) { else
/* RETURN(RC_WMORE);
* Found the terminator of the }
* indefinite length structure. else if (((const uint8_t*)ptr)[1] == 0)
*/ {
break; /*
* Found the terminator of the
* indefinite length structure.
*/
break;
}
else
{
/* this case should not happen when the message is correctly encoded */
RETURN(RC_FAIL);
} }
} }
/* Outmost tag may be unknown and cannot be fetched/compared */ /* Outmost tag may be unknown and cannot be fetched/compared */
if(elm->tag != (ber_tlv_tag_t)-1) { if(elm->tag != (ber_tlv_tag_t)-1) {
if(BER_TAGS_EQUAL(tlv_tag, elm->tag)) { if(BER_TAGS_EQUAL(tlv_tag, elm->tag)) {
/* /*

Loading…
Cancel
Save