- 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.
*/
while(ctx->left < 0) {
while(ctx->left < 0)
{
ssize_t tl;
tl = ber_fetch_tag(ptr, LEFT, &tlv_tag);
@ -304,13 +305,17 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/*
* Expected <0><0>...
*/
if(((const uint8_t *)ptr)[0] == 0) {
if(LEFT < 2) {
if(SIZE_VIOLATION)
if (((const uint8_t*)ptr)[0] == 0)
{
if (LEFT < 2)
{
if (SIZE_VIOLATION)
RETURN(RC_FAIL);
else
RETURN(RC_WMORE);
} else if(((const uint8_t *)ptr)[1] == 0) {
}
else if (((const uint8_t*)ptr)[1] == 0)
{
/*
* Correctly finished with <0><0>.
*/
@ -318,7 +323,14 @@ CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
ctx->left++;
continue;
}
} else {
else
{
/* this case should not happen when the message is correctly encoded */
RETURN(RC_FAIL);
}
}
else
{
RETURN(RC_FAIL);
}

@ -223,19 +223,21 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
case -1: RETURN(RC_FAIL);
}
if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
if(LEFT < 2) {
if(SIZE_VIOLATION)
if (ctx->left < 0 && ((const uint8_t*)ptr)[0] == 0)
{
if (LEFT < 2)
{
if (SIZE_VIOLATION)
RETURN(RC_FAIL);
else
RETURN(RC_WMORE);
} else if(((const uint8_t *)ptr)[1] == 0) {
}
else if (((const uint8_t*)ptr)[1] == 0)
{
if((edx + elements[edx].optional
== td->elements_count)
|| (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.
@ -248,6 +250,11 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
goto phase3;
}
}
else
{
/* this case should not happen when the message is correctly encoded */
RETURN(RC_FAIL);
}
}
/*
@ -421,14 +428,17 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
/*
* If expected <0><0>...
*/
if(ctx->left < 0
&& ((const uint8_t *)ptr)[0] == 0) {
if(LEFT < 2) {
if(SIZE_VIOLATION)
if (ctx->left < 0 && ((const uint8_t*)ptr)[0] == 0)
{
if (LEFT < 2)
{
if (SIZE_VIOLATION)
RETURN(RC_FAIL);
else
RETURN(RC_WMORE);
} else if(((const uint8_t *)ptr)[1] == 0) {
}
else if (((const uint8_t*)ptr)[1] == 0)
{
/*
* Correctly finished with <0><0>.
*/
@ -436,6 +446,11 @@ SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
ctx->left++;
ctx->phase = 4;
continue;
}
else
{
/* this case should not happen when the message is correctly encoded */
RETURN(RC_FAIL);
}
}

@ -158,19 +158,28 @@ SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
case -1: RETURN(RC_FAIL);
}
if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) {
if(LEFT < 2) {
if(SIZE_VIOLATION)
if (ctx->left < 0 && ((const uint8_t*)ptr)[0] == 0)
{
if (LEFT < 2)
{
if (SIZE_VIOLATION)
RETURN(RC_FAIL);
else
RETURN(RC_WMORE);
} else if(((const uint8_t *)ptr)[1] == 0) {
}
else if (((const uint8_t*)ptr)[1] == 0)
{
/*
* 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 */

Loading…
Cancel
Save