summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Sperling <ssperling@sysmocom.de>2018-01-08 19:20:02 +0100
committerHarald Welte <laforge@gnumonks.org>2018-01-12 13:48:59 +0000
commit1e50e2ad4813c037b0fbc5559381ec22776225d7 (patch)
tree389ada1e65127e552ef730f6d216280826760a8d
parentffad574a4b68596d17671965bf145f11f0b00e57 (diff)
TLVP_PRESENT() should not return TRUE after tlv_parse() fails.
If the length provided in the patcket exceeds the buffer length, tlv_parse() returns -2 but leaves tlv.val and tlv.len initializd. Many callers of tlv_parse() do not check its return value, but rely on TLVP_PRESENT() to see if a particular TLV was parsed successfully. By clearing tlv.val and tlv.len we make it less likely that those callers will use an overlong TLV length value. Change-Id: I4dda6938e1650b4bcaac45809a4763f86f5a9794
-rw-r--r--src/gsm/tlv_parser.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/src/gsm/tlv_parser.c b/src/gsm/tlv_parser.c
index ead856c9..9b1fb17a 100644
--- a/src/gsm/tlv_parser.c
+++ b/src/gsm/tlv_parser.c
@@ -127,7 +127,7 @@ int osmo_tlvp_merge(struct tlv_parsed *dst, const struct tlv_parsed *src)
* \param[in] def structure defining the valid TLV tags / configurations
* \param[in] buf the input data buffer to be parsed
* \param[in] buf_len length of the input data buffer
- * \returns number of bytes consumed by the TLV entry / IE parsed
+ * \returns number of bytes consumed by the TLV entry / IE parsed; negative in case of error
*/
int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val,
const struct tlv_definition *def,
@@ -227,7 +227,7 @@ tlv: /* GSM TS 04.07 11.2.4: Type 4 TLV */
* \param[in] buf_len length of the input data buffer
* \param[in] lv_tag an initial LV tag at the start of the buffer
* \param[in] lv_tag2 a second initial LV tag following the \a lv_tag
- * \returns number of bytes consumed by the TLV entry / IE parsed
+ * \returns number of bytes consumed by the TLV entry / IE parsed; negative in case of error
*/
int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
const uint8_t *buf, int buf_len, uint8_t lv_tag,
@@ -244,8 +244,11 @@ int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
dec->lv[lv_tag].val = &buf[ofs+1];
dec->lv[lv_tag].len = buf[ofs];
len = dec->lv[lv_tag].len + 1;
- if (ofs + len > buf_len)
+ if (ofs + len > buf_len) {
+ dec->lv[lv_tag].val = NULL;
+ dec->lv[lv_tag].len = 0;
return -2;
+ }
num_parsed++;
ofs += len;
}
@@ -255,8 +258,11 @@ int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
dec->lv[lv_tag2].val = &buf[ofs+1];
dec->lv[lv_tag2].len = buf[ofs];
len = dec->lv[lv_tag2].len + 1;
- if (ofs + len > buf_len)
+ if (ofs + len > buf_len) {
+ dec->lv[lv_tag2].val = NULL;
+ dec->lv[lv_tag2].len = 0;
return -2;
+ }
num_parsed++;
ofs += len;
}