From 43c07919bfa0ecd723ca23ca6ae01879c26b1492 Mon Sep 17 00:00:00 2001 From: wolfreak99 Date: Fri, 17 Feb 2017 23:43:14 +0100 Subject: [PATCH] Create "add_clamp" functions family for overflow prevention These will clamp signed addition (or subtraction) to limits of their types to prevent signed overflows, which is undefined behaviour. --- src/openrct2/util/util.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/openrct2/util/util.h | 5 +++++ 2 files changed, 45 insertions(+) diff --git a/src/openrct2/util/util.c b/src/openrct2/util/util.c index 4a99733acb..27b6116861 100644 --- a/src/openrct2/util/util.c +++ b/src/openrct2/util/util.c @@ -494,3 +494,43 @@ uint8 *util_zlib_deflate(const uint8 *data, size_t data_in_size, size_t *data_ou buffer = realloc(buffer, *data_out_size); return buffer; } + +// Type-independant code left as macro to reduce duplicate code. +#define add_clamp_body(value, value_to_add, min_cap, max_cap) \ + if ((value_to_add > 0) && (value > (max_cap - value_to_add))) { \ + value = max_cap; \ + } \ + else if ((value_to_add < 0) && (value < (min_cap - value_to_add))) { \ + value = min_cap; \ + } \ + else { \ + value += value_to_add; \ + } + +sint8 add_clamp_sint8(sint8 value, sint8 value_to_add) +{ + add_clamp_body(value, value_to_add, INT8_MIN, INT8_MAX); + return value; +} + +sint16 add_clamp_sint16(sint16 value, sint16 value_to_add) +{ + add_clamp_body(value, value_to_add, INT16_MIN, INT16_MAX); + return value; +} + +sint32 add_clamp_sint32(sint32 value, sint32 value_to_add) +{ + add_clamp_body(value, value_to_add, INT32_MIN, INT32_MAX); + return value; +} + +money32 add_clamp_money32(money32 value, money32 value_to_add) +{ + // This function is intended only for clarity, as money32 + // is technically the same as sint32 + assert_struct_size(money32, sizeof(sint32)); + return add_clamp_sint32(value, value_to_add); +} + +#undef add_clamp_body diff --git a/src/openrct2/util/util.h b/src/openrct2/util/util.h index b0593a9237..388a0467bd 100644 --- a/src/openrct2/util/util.h +++ b/src/openrct2/util/util.h @@ -57,4 +57,9 @@ uint32 util_rand(); uint8 *util_zlib_deflate(const uint8 *data, size_t data_in_size, size_t *data_out_size); uint8 *util_zlib_inflate(uint8 *data, size_t data_in_size, size_t *data_out_size); +sint8 add_clamp_sint8(sint8 value, sint8 value_to_add); +sint16 add_clamp_sint16(sint16 value, sint16 value_to_add); +sint32 add_clamp_sint32(sint32 value, sint32 value_to_add); +money32 add_clamp_money32(money32 value, money32 value_to_add); + #endif