1 /*-------------------------------------------------------------------------
2  *
3  * int.h
4  *	  Routines to perform integer math, while checking for overflows.
5  *
6  * The routines in this file are intended to be well defined C, without
7  * relying on compiler flags like -fwrapv.
8  *
9  * To reduce the overhead of these routines try to use compiler intrinsics
10  * where available. That's not that important for the 16, 32 bit cases, but
11  * the 64 bit cases can be considerably faster with intrinsics. In case no
12  * intrinsics are available 128 bit math is used where available.
13  *
14  * Copyright (c) 2017-2018, PostgreSQL Global Development Group
15  *
16  * src/include/common/int.h
17  *
18  *-------------------------------------------------------------------------
19  */
20 #ifndef COMMON_INT_H
21 #define COMMON_INT_H
22 
23 /*
24  * If a + b overflows, return true, otherwise store the result of a + b into
25  * *result. The content of *result is implementation defined in case of
26  * overflow.
27  */
28 static inline bool
pg_add_s16_overflow(int16 a,int16 b,int16 * result)29 pg_add_s16_overflow(int16 a, int16 b, int16 *result)
30 {
31 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
32 	return __builtin_add_overflow(a, b, result);
33 #else
34 	int32		res = (int32) a + (int32) b;
35 
36 	if (res > PG_INT16_MAX || res < PG_INT16_MIN)
37 	{
38 		*result = 0x5EED;		/* to avoid spurious warnings */
39 		return true;
40 	}
41 	*result = (int16) res;
42 	return false;
43 #endif
44 }
45 
46 /*
47  * If a - b overflows, return true, otherwise store the result of a - b into
48  * *result. The content of *result is implementation defined in case of
49  * overflow.
50  */
51 static inline bool
pg_sub_s16_overflow(int16 a,int16 b,int16 * result)52 pg_sub_s16_overflow(int16 a, int16 b, int16 *result)
53 {
54 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
55 	return __builtin_sub_overflow(a, b, result);
56 #else
57 	int32		res = (int32) a - (int32) b;
58 
59 	if (res > PG_INT16_MAX || res < PG_INT16_MIN)
60 	{
61 		*result = 0x5EED;		/* to avoid spurious warnings */
62 		return true;
63 	}
64 	*result = (int16) res;
65 	return false;
66 #endif
67 }
68 
69 /*
70  * If a * b overflows, return true, otherwise store the result of a * b into
71  * *result. The content of *result is implementation defined in case of
72  * overflow.
73  */
74 static inline bool
pg_mul_s16_overflow(int16 a,int16 b,int16 * result)75 pg_mul_s16_overflow(int16 a, int16 b, int16 *result)
76 {
77 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
78 	return __builtin_mul_overflow(a, b, result);
79 #else
80 	int32		res = (int32) a * (int32) b;
81 
82 	if (res > PG_INT16_MAX || res < PG_INT16_MIN)
83 	{
84 		*result = 0x5EED;		/* to avoid spurious warnings */
85 		return true;
86 	}
87 	*result = (int16) res;
88 	return false;
89 #endif
90 }
91 
92 /*
93  * If a + b overflows, return true, otherwise store the result of a + b into
94  * *result. The content of *result is implementation defined in case of
95  * overflow.
96  */
97 static inline bool
pg_add_s32_overflow(int32 a,int32 b,int32 * result)98 pg_add_s32_overflow(int32 a, int32 b, int32 *result)
99 {
100 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
101 	return __builtin_add_overflow(a, b, result);
102 #else
103 	int64		res = (int64) a + (int64) b;
104 
105 	if (res > PG_INT32_MAX || res < PG_INT32_MIN)
106 	{
107 		*result = 0x5EED;		/* to avoid spurious warnings */
108 		return true;
109 	}
110 	*result = (int32) res;
111 	return false;
112 #endif
113 }
114 
115 /*
116  * If a - b overflows, return true, otherwise store the result of a - b into
117  * *result. The content of *result is implementation defined in case of
118  * overflow.
119  */
120 static inline bool
pg_sub_s32_overflow(int32 a,int32 b,int32 * result)121 pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
122 {
123 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
124 	return __builtin_sub_overflow(a, b, result);
125 #else
126 	int64		res = (int64) a - (int64) b;
127 
128 	if (res > PG_INT32_MAX || res < PG_INT32_MIN)
129 	{
130 		*result = 0x5EED;		/* to avoid spurious warnings */
131 		return true;
132 	}
133 	*result = (int32) res;
134 	return false;
135 #endif
136 }
137 
138 /*
139  * If a * b overflows, return true, otherwise store the result of a * b into
140  * *result. The content of *result is implementation defined in case of
141  * overflow.
142  */
143 static inline bool
pg_mul_s32_overflow(int32 a,int32 b,int32 * result)144 pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
145 {
146 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
147 	return __builtin_mul_overflow(a, b, result);
148 #else
149 	int64		res = (int64) a * (int64) b;
150 
151 	if (res > PG_INT32_MAX || res < PG_INT32_MIN)
152 	{
153 		*result = 0x5EED;		/* to avoid spurious warnings */
154 		return true;
155 	}
156 	*result = (int32) res;
157 	return false;
158 #endif
159 }
160 
161 /*
162  * If a + b overflows, return true, otherwise store the result of a + b into
163  * *result. The content of *result is implementation defined in case of
164  * overflow.
165  */
166 static inline bool
pg_add_s64_overflow(int64 a,int64 b,int64 * result)167 pg_add_s64_overflow(int64 a, int64 b, int64 *result)
168 {
169 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
170 	return __builtin_add_overflow(a, b, result);
171 #elif defined(HAVE_INT128)
172 	int128		res = (int128) a + (int128) b;
173 
174 	if (res > PG_INT64_MAX || res < PG_INT64_MIN)
175 	{
176 		*result = 0x5EED;		/* to avoid spurious warnings */
177 		return true;
178 	}
179 	*result = (int64) res;
180 	return false;
181 #else
182 	if ((a > 0 && b > 0 && a > PG_INT64_MAX - b) ||
183 		(a < 0 && b < 0 && a < PG_INT64_MIN - b))
184 	{
185 		*result = 0x5EED;		/* to avoid spurious warnings */
186 		return true;
187 	}
188 	*result = a + b;
189 	return false;
190 #endif
191 }
192 
193 /*
194  * If a - b overflows, return true, otherwise store the result of a - b into
195  * *result. The content of *result is implementation defined in case of
196  * overflow.
197  */
198 static inline bool
pg_sub_s64_overflow(int64 a,int64 b,int64 * result)199 pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
200 {
201 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
202 	return __builtin_sub_overflow(a, b, result);
203 #elif defined(HAVE_INT128)
204 	int128		res = (int128) a - (int128) b;
205 
206 	if (res > PG_INT64_MAX || res < PG_INT64_MIN)
207 	{
208 		*result = 0x5EED;		/* to avoid spurious warnings */
209 		return true;
210 	}
211 	*result = (int64) res;
212 	return false;
213 #else
214 	if ((a < 0 && b > 0 && a < PG_INT64_MIN + b) ||
215 		(a > 0 && b < 0 && a > PG_INT64_MAX + b))
216 	{
217 		*result = 0x5EED;		/* to avoid spurious warnings */
218 		return true;
219 	}
220 	*result = a - b;
221 	return false;
222 #endif
223 }
224 
225 /*
226  * If a * b overflows, return true, otherwise store the result of a * b into
227  * *result. The content of *result is implementation defined in case of
228  * overflow.
229  */
230 static inline bool
pg_mul_s64_overflow(int64 a,int64 b,int64 * result)231 pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
232 {
233 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
234 	return __builtin_mul_overflow(a, b, result);
235 #elif defined(HAVE_INT128)
236 	int128		res = (int128) a * (int128) b;
237 
238 	if (res > PG_INT64_MAX || res < PG_INT64_MIN)
239 	{
240 		*result = 0x5EED;		/* to avoid spurious warnings */
241 		return true;
242 	}
243 	*result = (int64) res;
244 	return false;
245 #else
246 	/*
247 	 * Overflow can only happen if at least one value is outside the range
248 	 * sqrt(min)..sqrt(max) so check that first as the division can be quite a
249 	 * bit more expensive than the multiplication.
250 	 *
251 	 * Multiplying by 0 or 1 can't overflow of course and checking for 0
252 	 * separately avoids any risk of dividing by 0.  Be careful about dividing
253 	 * INT_MIN by -1 also, note reversing the a and b to ensure we're always
254 	 * dividing it by a positive value.
255 	 *
256 	 */
257 	if ((a > PG_INT32_MAX || a < PG_INT32_MIN ||
258 		 b > PG_INT32_MAX || b < PG_INT32_MIN) &&
259 		a != 0 && a != 1 && b != 0 && b != 1 &&
260 		((a > 0 && b > 0 && a > PG_INT64_MAX / b) ||
261 		 (a > 0 && b < 0 && b < PG_INT64_MIN / a) ||
262 		 (a < 0 && b > 0 && a < PG_INT64_MIN / b) ||
263 		 (a < 0 && b < 0 && a < PG_INT64_MAX / b)))
264 	{
265 		*result = 0x5EED;		/* to avoid spurious warnings */
266 		return true;
267 	}
268 	*result = a * b;
269 	return false;
270 #endif
271 }
272 
273 #endif							/* COMMON_INT_H */
274