From d2d16d26da02d815b5822e08454bdd34cc7c621c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Wed, 22 Mar 2017 16:50:01 +0100 Subject: [PATCH] Make rolN / rorN safe for all counts. The current version invokes undefined behavior when the count is negative, zero, or equal to or greater than the width of the operand. The new version masks the count to avoid these situations. Although branchless, it is relatively inefficient if the compiler does not recognize it and translate it to a rol or ror instruction. Empirical tests show that both clang and gcc get it right for constant counts, and recent versions of clang (but not gcc) get it right for variable counts as well. Note that our current code base has no instances of rolN / rorN with a variable count. --- include/cryb/bitwise.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/cryb/bitwise.h b/include/cryb/bitwise.h index a1eff65..c7f9107 100644 --- a/include/cryb/bitwise.h +++ b/include/cryb/bitwise.h @@ -1,6 +1,6 @@ /*- * Copyright (c) 2012 The University of Oslo - * Copyright (c) 2012-2016 Dag-Erling Smørgrav + * Copyright (c) 2012-2017 Dag-Erling Smørgrav * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,11 +40,11 @@ CRYB_BEGIN #define CRYB_ROL_ROR(N) \ static inline uint##N##_t rol##N(uint##N##_t i, int n) \ { \ - return (i << n | i >> (N - n)); \ + return (i << (n & (N - 1)) | i >> (-n & (N - 1))); \ } \ static inline uint##N##_t ror##N(uint##N##_t i, int n) \ { \ - return (i << (N - n) | i >> n); \ + return (i << (-n & (N - 1)) | i >> (n & (N - 1))); \ } CRYB_ROL_ROR(8);