From 2b4edf1807e645337908415a652409573d48d74f Mon Sep 17 00:00:00 2001 From: Balint Joo Date: Mon, 11 Oct 2021 16:17:22 -0400 Subject: [PATCH] Added a DML_site_rotl32() function to eliminate Undefined Behaviour --- lib/dml/DML_utils.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/lib/dml/DML_utils.c b/lib/dml/DML_utils.c index c9d3ce4..d9387c9 100644 --- a/lib/dml/DML_utils.c +++ b/lib/dml/DML_utils.c @@ -17,6 +17,8 @@ #include //#include #include +#include +#include #undef DML_DEBUG @@ -993,6 +995,28 @@ void DML_destroy_subset_rank(DML_SiteList *sites){ /*------------------------------------------------------------------*/ /* Checksum "class" */ + +/* A safe and nearly constant time bitwise rotate which + * avoids Undefined Behaviour. + * + * This implementation follows this Wikipedia entry: + * https://en.wikipedia.org/wiki/Circular_shift#Implementing_circular_shifts + * + * and is based on the work of: + * John Regehr https://blog.regehr.org/archives/1063 + * and + * Peter Cordes in his stack overflow answers: + * + * https://stackoverflow.com/questions/776508/best-practices-for-circular-shift-rotate-operations-in-c/776523#776523 + * https://stackoverflow.com/questions/31387778/near-constant-time-rotate-that-does-not-violate-the-standards/31488147#31488147 + */ +uint32_t DML_rank_rotl32(uint32_t work, DML_SiteRank rank) +{ + const unsigned int mask = CHAR_BIT * sizeof(work) - 1; + rank &= mask; + return (work << rank) | (work >> (-rank & mask)); +} + /* We do a crc32 sum on the site data -- then do two lexicographic- rank-based bit rotations and XORs on the resulting crc32 checksum */ @@ -1013,8 +1037,12 @@ void DML_checksum_accum(DML_Checksum *checksum, DML_SiteRank rank, rank29 %= 29; rank31 %= 31; - checksum->suma ^= work<>(32-rank29); - checksum->sumb ^= work<>(32-rank31); + /* + checksum->suma ^= work<>(32-rank29); + checksum->sumb ^= work<>(32-rank31); + */ + checksum->suma ^= DML_rank_rotl32(work, rank29); + checksum->sumb ^= DML_rank_rotl32(work, rank31); } /* Combine checksums over all nodes */