diff --git a/src/cmdu.c b/src/cmdu.c index 3fdbfa2708e491f836f4145e2ca767563839b150..c01d7de7488d4e094bc74eba69d6fb4e12b54895 100644 --- a/src/cmdu.c +++ b/src/cmdu.c @@ -575,7 +575,7 @@ int cmdu_parse_tlv_single(struct cmdu_buff *c, struct tlv *tv[], int len; - if (!c) + if (!c || !c->data || !c->datalen) return -1; if (*num == 0) @@ -598,7 +598,7 @@ int cmdu_parse_tlv_single(struct cmdu_buff *c, struct tlv *tv[], continue; if (tv[0] && policy->present == TLV_PRESENT_ONE) - break; + return -1; if (i >= *num) break; @@ -606,6 +606,14 @@ int cmdu_parse_tlv_single(struct cmdu_buff *c, struct tlv *tv[], tv[i++] = t; } + /* malformed cmdu if data remaining */ + if (len) + return -1; + + /* exactly one tlv must be present */ + if (policy->present == TLV_PRESENT_ONE && !tv[0]) + return -1; + *num = i; return 0; } @@ -619,7 +627,7 @@ int cmdu_parse_tlvs(struct cmdu_buff *c, struct tlv *tv[][16], int i; - if (!c) + if (!c || !c->data || !c->datalen) return -1; for (i = 0; i < policy_len; i++) { @@ -646,13 +654,23 @@ int cmdu_parse_tlvs(struct cmdu_buff *c, struct tlv *tv[][16], if (tv[i][0]) { if (policy[i].present == TLV_PRESENT_ONE) - continue; + return -1; } tv[i][idx[i]++] = t; } } + /* malformed cmdu if data remaining */ + if (len) + return -1; + + /* strictly check against tlv policies */ + for (i = 0; i < policy_len; i++) { + if (policy[i].present == TLV_PRESENT_ONE && !tv[i][0]) + return -1; + } + return 0; }