# HG changeset patch # User Mario de Sousa # Date 1545824727 0 # Node ID 54445dfc28ec2d9eee2ec3c81b75623e4e5df782 # Parent 585445abc4a21b57f5d108a795cb92404639b9f8 addendum to issue #76: detect overflow when calculating least common multiple of task intervals. diff -r 585445abc4a2 -r 54445dfc28ec stage4/generate_c/generate_c.cc --- a/stage4/generate_c/generate_c.cc Wed Dec 26 11:40:45 2018 +0000 +++ b/stage4/generate_c/generate_c.cc Wed Dec 26 11:45:27 2018 +0000 @@ -547,6 +547,8 @@ #define MILLISECOND 1000000 #define SECOND 1000 * MILLISECOND +#define ULL_MAX std::numeric_limits::max() + unsigned long long calculate_time(symbol_c *symbol) { if (NULL == symbol) return 0; @@ -638,8 +640,10 @@ else return euclide(b, c); } - - void update_ticktime(unsigned long long time) { + + bool update_ticktime(unsigned long long time) { + bool overflow = false; + if (common_ticktime == 0) common_ticktime = time; else if (time > common_ticktime) @@ -648,10 +652,15 @@ common_ticktime = euclide(common_ticktime, time); if (least_common_ticktime == 0) least_common_ticktime = time; - else + else { + /* Test overflow on MUL by pre-condition: If (ULL_MAX / a) < b => overflow! */ + overflow = ((ULL_MAX / least_common_ticktime) < (time / common_ticktime)); least_common_ticktime = least_common_ticktime * (time / common_ticktime); - } - + } + fprintf(stderr, "time=%llu least_common_ticktime=%llu common_ticktime=%llu\n", time, least_common_ticktime, common_ticktime ); + return !overflow; + } + unsigned long long get_common_ticktime(void) { return common_ticktime; } @@ -667,9 +676,12 @@ //SYM_REF2(task_configuration_c, task_name, task_initialization) void *visit(task_initialization_c *symbol) { if (symbol->interval_data_source != NULL) { - unsigned long long time = calculate_time(symbol->interval_data_source); - if (time < 0) ERROR; - else update_ticktime(time); + unsigned long long time = calculate_time(symbol->interval_data_source); + if (!update_ticktime(time)) + /* time is being stored in ns resolution (MILLISECOND #define is set to 1000000) */ + /* time is being stored in unsigned long long (ISO C99 guarantees at least 64 bits) */ + /* 2⁶64ns works out to around 584.5 years, assuming 365.25 days per year */ + STAGE4_ERROR(symbol, symbol, "Internal overflow calculating least common multiple of task intervals (must be < 584 years)."); } return NULL; }