From d2971f3fca929d9085ed17b71aa4ec8e96499d99 Mon Sep 17 00:00:00 2001 From: =?utf8?q?St=C3=A9phane=20Nicolet?= Date: Wed, 11 Jan 2017 18:11:17 +0100 Subject: [PATCH] Check for overflow in Score * int multiplication (#969) Add asserts to check for overflow in Score * int multiplication. There is no overflow in current master, but it would be easy to create one as the scale of the current eval does not leave many spare bits. For instance, adding the following unused variables in master at the end of evaluate() (line 882 of evaluate.cpp) overflows: Score s1 = score * 4; // no overflow Score s2 = score * 5; // overflow Assertion failed: (eg_value(result) == (i * eg_value(s))), function operator*, file ./types.h, line 336. Same md5 checksum as current master for non debug compiles. No functional change. --- src/types.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/types.h b/src/types.h index 595290df..4d113e1b 100644 --- a/src/types.h +++ b/src/types.h @@ -285,19 +285,19 @@ inline Value mg_value(Score s) { #define ENABLE_BASE_OPERATORS_ON(T) \ inline T operator+(T d1, T d2) { return T(int(d1) + int(d2)); } \ inline T operator-(T d1, T d2) { return T(int(d1) - int(d2)); } \ -inline T operator*(int i, T d) { return T(i * int(d)); } \ -inline T operator*(T d, int i) { return T(int(d) * i); } \ inline T operator-(T d) { return T(-int(d)); } \ inline T& operator+=(T& d1, T d2) { return d1 = d1 + d2; } \ inline T& operator-=(T& d1, T d2) { return d1 = d1 - d2; } \ -inline T& operator*=(T& d, int i) { return d = T(int(d) * i); } #define ENABLE_FULL_OPERATORS_ON(T) \ ENABLE_BASE_OPERATORS_ON(T) \ +inline T operator*(int i, T d) { return T(i * int(d)); } \ +inline T operator*(T d, int i) { return T(int(d) * i); } \ inline T& operator++(T& d) { return d = T(int(d) + 1); } \ inline T& operator--(T& d) { return d = T(int(d) - 1); } \ inline T operator/(T d, int i) { return T(int(d) / i); } \ inline int operator/(T d1, T d2) { return int(d1) / int(d2); } \ +inline T& operator*=(T& d, int i) { return d = T(int(d) * i); } \ inline T& operator/=(T& d, int i) { return d = T(int(d) / i); } ENABLE_FULL_OPERATORS_ON(Value) @@ -329,6 +329,17 @@ inline Score operator/(Score s, int i) { return make_score(mg_value(s) / i, eg_value(s) / i); } +/// Multiplication of a Score by an integer. We check for overflow in debug mode. +inline Score operator*(Score s, int i) { + Score result = Score(int(s) * i); + + assert(eg_value(result) == (i * eg_value(s))); + assert(mg_value(result) == (i * mg_value(s))); + assert((i == 0) || (result / i) == s ); + + return result; +} + inline Color operator~(Color c) { return Color(c ^ BLACK); // Toggle color } -- 2.39.2