diff --git a/include/sys/math_extras.h b/include/sys/math_extras.h index 43256151ee6198..bef9a78a6bbecb 100644 --- a/include/sys/math_extras.h +++ b/include/sys/math_extras.h @@ -28,6 +28,7 @@ * true if the operation overflowed. */ /**@{*/ +static bool u16_add_overflow(u16_t a, u16_t b, u16_t *result); static bool u32_add_overflow(u32_t a, u32_t b, u32_t *result); static bool u64_add_overflow(u64_t a, u64_t b, u64_t *result); static bool size_add_overflow(size_t a, size_t b, size_t *result); @@ -40,6 +41,7 @@ static bool size_add_overflow(size_t a, size_t b, size_t *result); * true if the operation overflowed. */ /**@{*/ +static bool u16_mul_overflow(u16_t a, u16_t b, u16_t *result); static bool u32_mul_overflow(u32_t a, u32_t b, u32_t *result); static bool u64_mul_overflow(u64_t a, u64_t b, u64_t *result); static bool size_mul_overflow(size_t a, size_t b, size_t *result); diff --git a/include/sys/math_extras_impl.h b/include/sys/math_extras_impl.h index 7aa0f48907ae48..022d0b5604c70f 100644 --- a/include/sys/math_extras_impl.h +++ b/include/sys/math_extras_impl.h @@ -29,6 +29,11 @@ #endif #if use_builtin(__builtin_add_overflow) +static inline bool u16_add_overflow(u16_t a, u16_t b, u16_t *result) +{ + return __builtin_add_overflow(a, b, result); +} + static inline bool u32_add_overflow(u32_t a, u32_t b, u32_t *result) { return __builtin_add_overflow(a, b, result); @@ -44,6 +49,15 @@ static inline bool size_add_overflow(size_t a, size_t b, size_t *result) return __builtin_add_overflow(a, b, result); } #else /* !use_builtin(__builtin_add_overflow) */ +static inline bool u16_add_overflow(u16_t a, u16_t b, u16_t *result) +{ + u16_t c = a + b; + + *result = c; + + return c < a; +} + static inline bool u32_add_overflow(u32_t a, u32_t b, u32_t *result) { u32_t c = a + b; @@ -73,6 +87,11 @@ static inline bool size_add_overflow(size_t a, size_t b, size_t *result) #endif /* use_builtin(__builtin_add_overflow) */ #if use_builtin(__builtin_mul_overflow) +static inline bool u16_mul_overflow(u16_t a, u16_t b, u16_t *result) +{ + return __builtin_mul_overflow(a, b, result); +} + static inline bool u32_mul_overflow(u32_t a, u32_t b, u32_t *result) { return __builtin_mul_overflow(a, b, result); @@ -88,6 +107,15 @@ static inline bool size_mul_overflow(size_t a, size_t b, size_t *result) return __builtin_mul_overflow(a, b, result); } #else /* !use_builtin(__builtin_mul_overflow) */ +static inline bool u16_mul_overflow(u16_t a, u16_t b, u16_t *result) +{ + u16_t c = a * b; + + *result = c; + + return a != 0 && (c / a) != b; +} + static inline bool u32_mul_overflow(u32_t a, u32_t b, u32_t *result) { u32_t c = a * b; diff --git a/subsys/net/lib/coap/coap.c b/subsys/net/lib/coap/coap.c index a4bcff36643601..ac0661919b2e1e 100644 --- a/subsys/net/lib/coap/coap.c +++ b/subsys/net/lib/coap/coap.c @@ -17,6 +17,7 @@ LOG_MODULE_REGISTER(net_coap, CONFIG_COAP_LOG_LEVEL); #include #include +#include #include #include @@ -469,7 +470,9 @@ static int parse_option(u8_t *data, u16_t offset, u16_t *pos, return -EINVAL; } - *opt_len += hdr_len; + if (u16_add_overflow(*opt_len, hdr_len, opt_len)) { + return -EINVAL; + } } if (len > COAP_OPTION_NO_EXT) { @@ -480,11 +483,15 @@ static int parse_option(u8_t *data, u16_t offset, u16_t *pos, return -EINVAL; } - *opt_len += hdr_len; + if (u16_add_overflow(*opt_len, hdr_len, opt_len)) { + return -EINVAL; + } } - *opt_delta += delta; - *opt_len += len; + if (u16_add_overflow(*opt_delta, delta, opt_delta) || + u16_add_overflow(*opt_len, len, opt_len)) { + return -EINVAL; + } if (r == 0) { if (len == 0U) { @@ -519,7 +526,10 @@ static int parse_option(u8_t *data, u16_t offset, u16_t *pos, return -EINVAL; } } else { - *pos += len; + if (u16_add_overflow(*pos, len, pos)) { + return -EINVAL; + } + r = max_len - *pos; }