shithub: puzzles

Download patch

ref: 93be3f7ccaa63b0fd953bcfd88d685b47b76605e
parent: 9dbcfa765ba59a8201425df18bec09c7bc334c5e
author: Ben Harris <[email protected]>
date: Sun Feb 26 09:24:38 EST 2023

Be more careful with type of left operand of <<

On a 32-bit system, evaluating 1<<31 causes undefined behaviour because
1 is signed and so it produces signed overflow.  UBSan has spotted a
couple of occasions where this happens in Puzzles, so in each case I've
converted the left operand to the unsigned result type we actually want.

--- a/cube.c
+++ b/cube.c
@@ -202,8 +202,8 @@
 };
 
 #define SET_SQUARE(state, i, val) \
-    ((state)->bluemask[(i)/32] &= ~(1 << ((i)%32)), \
-     (state)->bluemask[(i)/32] |= ((!!val) << ((i)%32)))
+    ((state)->bluemask[(i)/32] &= ~(1UL << ((i)%32)), \
+     (state)->bluemask[(i)/32] |= ((unsigned long)(!!val) << ((i)%32)))
 #define GET_SQUARE(state, i) \
     (((state)->bluemask[(i)/32] >> ((i)%32)) & 1)
 
--- a/random.c
+++ b/random.c
@@ -254,12 +254,12 @@
     }
 
     /*
-     * `(1 << bits) - 1' is not good enough, since if bits==32 on a
+     * `(1UL << bits) - 1' is not good enough, since if bits==32 on a
      * 32-bit machine, behaviour is undefined and Intel has a nasty
      * habit of shifting left by zero instead. We'll shift by
      * bits-1 and then separately shift by one.
      */
-    ret &= (1 << (bits-1)) * 2 - 1;
+    ret &= (1UL << (bits-1)) * 2 - 1;
     return ret;
 }