summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_ecommunity.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 66898d07b..1beb0307d 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -1856,7 +1856,7 @@ ecommunity_add_origin_validation_state(enum rpki_states rpki_state,
*/
const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint64_t *bw)
{
- const uint8_t *eval;
+ const uint8_t *data;
uint32_t i;
if (bw)
@@ -1869,10 +1869,19 @@ const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint64_t *bw)
const uint8_t *pnt;
uint8_t type, sub_type;
- eval = pnt = (ecom->val + (i * ecom->unit_size));
+ data = pnt = (ecom->val + (i * ecom->unit_size));
type = *pnt++;
sub_type = *pnt++;
+ const uint8_t *end = data + ecom->unit_size;
+ size_t len = end - data;
+
+ /* Sanity check for extended communities lenght, to avoid
+ * overrun when dealing with bits, e.g. ptr_get_be64().
+ */
+ if (len < ecom->unit_size)
+ return NULL;
+
if ((type == ECOMMUNITY_ENCODE_AS ||
type == ECOMMUNITY_ENCODE_AS_NON_TRANS) &&
sub_type == ECOMMUNITY_LINK_BANDWIDTH) {
@@ -1886,11 +1895,14 @@ const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint64_t *bw)
? bwval
: ieee_float_uint32_to_uint32(
bwval));
- return eval;
+ return data;
} else if (type == ECOMMUNITY_ENCODE_AS4 &&
sub_type == ECOMMUNITY_EXTENDED_LINK_BANDWIDTH) {
uint64_t bwval;
+ if (len < IPV6_ECOMMUNITY_SIZE)
+ return NULL;
+
pnt += 2; /* Reserved */
pnt = ptr_get_be64(pnt, &bwval);
(void)pnt;
@@ -1898,7 +1910,7 @@ const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint64_t *bw)
if (bw)
*bw = bwval;
- return eval;
+ return data;
}
}