PostgreSQL Source Code  git master
int.h
Go to the documentation of this file.
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-2023, 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 /*---------
25  * The following guidelines apply to all the routines:
26  * - If a + b overflows, return true, otherwise store the result of a + b
27  * into *result. The content of *result is implementation defined in case of
28  * overflow.
29  * - If a - b overflows, return true, otherwise store the result of a - b
30  * into *result. The content of *result is implementation defined in case of
31  * overflow.
32  * - If a * b overflows, return true, otherwise store the result of a * b
33  * into *result. The content of *result is implementation defined in case of
34  * overflow.
35  *---------
36  */
37 
38 /*------------------------------------------------------------------------
39  * Overflow routines for signed integers
40  *------------------------------------------------------------------------
41  */
42 
43 /*
44  * INT16
45  */
46 static inline bool
48 {
49 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
50  return __builtin_add_overflow(a, b, result);
51 #else
52  int32 res = (int32) a + (int32) b;
53 
54  if (res > PG_INT16_MAX || res < PG_INT16_MIN)
55  {
56  *result = 0x5EED; /* to avoid spurious warnings */
57  return true;
58  }
59  *result = (int16) res;
60  return false;
61 #endif
62 }
63 
64 static inline bool
66 {
67 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
68  return __builtin_sub_overflow(a, b, result);
69 #else
70  int32 res = (int32) a - (int32) b;
71 
72  if (res > PG_INT16_MAX || res < PG_INT16_MIN)
73  {
74  *result = 0x5EED; /* to avoid spurious warnings */
75  return true;
76  }
77  *result = (int16) res;
78  return false;
79 #endif
80 }
81 
82 static inline bool
84 {
85 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
86  return __builtin_mul_overflow(a, b, result);
87 #else
88  int32 res = (int32) a * (int32) b;
89 
90  if (res > PG_INT16_MAX || res < PG_INT16_MIN)
91  {
92  *result = 0x5EED; /* to avoid spurious warnings */
93  return true;
94  }
95  *result = (int16) res;
96  return false;
97 #endif
98 }
99 
100 /*
101  * INT32
102  */
103 static inline bool
105 {
106 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
107  return __builtin_add_overflow(a, b, result);
108 #else
109  int64 res = (int64) a + (int64) b;
110 
111  if (res > PG_INT32_MAX || res < PG_INT32_MIN)
112  {
113  *result = 0x5EED; /* to avoid spurious warnings */
114  return true;
115  }
116  *result = (int32) res;
117  return false;
118 #endif
119 }
120 
121 static inline bool
123 {
124 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
125  return __builtin_sub_overflow(a, b, result);
126 #else
127  int64 res = (int64) a - (int64) b;
128 
129  if (res > PG_INT32_MAX || res < PG_INT32_MIN)
130  {
131  *result = 0x5EED; /* to avoid spurious warnings */
132  return true;
133  }
134  *result = (int32) res;
135  return false;
136 #endif
137 }
138 
139 static inline bool
141 {
142 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
143  return __builtin_mul_overflow(a, b, result);
144 #else
145  int64 res = (int64) a * (int64) b;
146 
147  if (res > PG_INT32_MAX || res < PG_INT32_MIN)
148  {
149  *result = 0x5EED; /* to avoid spurious warnings */
150  return true;
151  }
152  *result = (int32) res;
153  return false;
154 #endif
155 }
156 
157 /*
158  * INT64
159  */
160 static inline bool
161 pg_add_s64_overflow(int64 a, int64 b, int64 *result)
162 {
163 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
164  return __builtin_add_overflow(a, b, result);
165 #elif defined(HAVE_INT128)
166  int128 res = (int128) a + (int128) b;
167 
168  if (res > PG_INT64_MAX || res < PG_INT64_MIN)
169  {
170  *result = 0x5EED; /* to avoid spurious warnings */
171  return true;
172  }
173  *result = (int64) res;
174  return false;
175 #else
176  if ((a > 0 && b > 0 && a > PG_INT64_MAX - b) ||
177  (a < 0 && b < 0 && a < PG_INT64_MIN - b))
178  {
179  *result = 0x5EED; /* to avoid spurious warnings */
180  return true;
181  }
182  *result = a + b;
183  return false;
184 #endif
185 }
186 
187 static inline bool
188 pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
189 {
190 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
191  return __builtin_sub_overflow(a, b, result);
192 #elif defined(HAVE_INT128)
193  int128 res = (int128) a - (int128) b;
194 
195  if (res > PG_INT64_MAX || res < PG_INT64_MIN)
196  {
197  *result = 0x5EED; /* to avoid spurious warnings */
198  return true;
199  }
200  *result = (int64) res;
201  return false;
202 #else
203  if ((a < 0 && b > 0 && a < PG_INT64_MIN + b) ||
204  (a > 0 && b < 0 && a > PG_INT64_MAX + b))
205  {
206  *result = 0x5EED; /* to avoid spurious warnings */
207  return true;
208  }
209  *result = a - b;
210  return false;
211 #endif
212 }
213 
214 static inline bool
215 pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
216 {
217 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
218  return __builtin_mul_overflow(a, b, result);
219 #elif defined(HAVE_INT128)
220  int128 res = (int128) a * (int128) b;
221 
222  if (res > PG_INT64_MAX || res < PG_INT64_MIN)
223  {
224  *result = 0x5EED; /* to avoid spurious warnings */
225  return true;
226  }
227  *result = (int64) res;
228  return false;
229 #else
230  /*
231  * Overflow can only happen if at least one value is outside the range
232  * sqrt(min)..sqrt(max) so check that first as the division can be quite a
233  * bit more expensive than the multiplication.
234  *
235  * Multiplying by 0 or 1 can't overflow of course and checking for 0
236  * separately avoids any risk of dividing by 0. Be careful about dividing
237  * INT_MIN by -1 also, note reversing the a and b to ensure we're always
238  * dividing it by a positive value.
239  *
240  */
241  if ((a > PG_INT32_MAX || a < PG_INT32_MIN ||
242  b > PG_INT32_MAX || b < PG_INT32_MIN) &&
243  a != 0 && a != 1 && b != 0 && b != 1 &&
244  ((a > 0 && b > 0 && a > PG_INT64_MAX / b) ||
245  (a > 0 && b < 0 && b < PG_INT64_MIN / a) ||
246  (a < 0 && b > 0 && a < PG_INT64_MIN / b) ||
247  (a < 0 && b < 0 && a < PG_INT64_MAX / b)))
248  {
249  *result = 0x5EED; /* to avoid spurious warnings */
250  return true;
251  }
252  *result = a * b;
253  return false;
254 #endif
255 }
256 
257 /*------------------------------------------------------------------------
258  * Overflow routines for unsigned integers
259  *------------------------------------------------------------------------
260  */
261 
262 /*
263  * UINT16
264  */
265 static inline bool
267 {
268 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
269  return __builtin_add_overflow(a, b, result);
270 #else
271  uint16 res = a + b;
272 
273  if (res < a)
274  {
275  *result = 0x5EED; /* to avoid spurious warnings */
276  return true;
277  }
278  *result = res;
279  return false;
280 #endif
281 }
282 
283 static inline bool
285 {
286 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
287  return __builtin_sub_overflow(a, b, result);
288 #else
289  if (b > a)
290  {
291  *result = 0x5EED; /* to avoid spurious warnings */
292  return true;
293  }
294  *result = a - b;
295  return false;
296 #endif
297 }
298 
299 static inline bool
301 {
302 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
303  return __builtin_mul_overflow(a, b, result);
304 #else
305  uint32 res = (uint32) a * (uint32) b;
306 
307  if (res > PG_UINT16_MAX)
308  {
309  *result = 0x5EED; /* to avoid spurious warnings */
310  return true;
311  }
312  *result = (uint16) res;
313  return false;
314 #endif
315 }
316 
317 /*
318  * INT32
319  */
320 static inline bool
322 {
323 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
324  return __builtin_add_overflow(a, b, result);
325 #else
326  uint32 res = a + b;
327 
328  if (res < a)
329  {
330  *result = 0x5EED; /* to avoid spurious warnings */
331  return true;
332  }
333  *result = res;
334  return false;
335 #endif
336 }
337 
338 static inline bool
340 {
341 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
342  return __builtin_sub_overflow(a, b, result);
343 #else
344  if (b > a)
345  {
346  *result = 0x5EED; /* to avoid spurious warnings */
347  return true;
348  }
349  *result = a - b;
350  return false;
351 #endif
352 }
353 
354 static inline bool
356 {
357 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
358  return __builtin_mul_overflow(a, b, result);
359 #else
360  uint64 res = (uint64) a * (uint64) b;
361 
362  if (res > PG_UINT32_MAX)
363  {
364  *result = 0x5EED; /* to avoid spurious warnings */
365  return true;
366  }
367  *result = (uint32) res;
368  return false;
369 #endif
370 }
371 
372 /*
373  * UINT64
374  */
375 static inline bool
376 pg_add_u64_overflow(uint64 a, uint64 b, uint64 *result)
377 {
378 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
379  return __builtin_add_overflow(a, b, result);
380 #else
381  uint64 res = a + b;
382 
383  if (res < a)
384  {
385  *result = 0x5EED; /* to avoid spurious warnings */
386  return true;
387  }
388  *result = res;
389  return false;
390 #endif
391 }
392 
393 static inline bool
394 pg_sub_u64_overflow(uint64 a, uint64 b, uint64 *result)
395 {
396 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
397  return __builtin_sub_overflow(a, b, result);
398 #else
399  if (b > a)
400  {
401  *result = 0x5EED; /* to avoid spurious warnings */
402  return true;
403  }
404  *result = a - b;
405  return false;
406 #endif
407 }
408 
409 static inline bool
410 pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result)
411 {
412 #if defined(HAVE__BUILTIN_OP_OVERFLOW)
413  return __builtin_mul_overflow(a, b, result);
414 #elif defined(HAVE_INT128)
415  uint128 res = (uint128) a * (uint128) b;
416 
417  if (res > PG_UINT64_MAX)
418  {
419  *result = 0x5EED; /* to avoid spurious warnings */
420  return true;
421  }
422  *result = (uint64) res;
423  return false;
424 #else
425  uint64 res = a * b;
426 
427  if (a != 0 && b != res / a)
428  {
429  *result = 0x5EED; /* to avoid spurious warnings */
430  return true;
431  }
432  *result = res;
433  return false;
434 #endif
435 }
436 
437 #endif /* COMMON_INT_H */
unsigned short uint16
Definition: c.h:489
unsigned int uint32
Definition: c.h:490
#define PG_INT32_MAX
Definition: c.h:573
signed short int16
Definition: c.h:477
#define PG_UINT32_MAX
Definition: c.h:574
signed int int32
Definition: c.h:478
#define PG_INT16_MIN
Definition: c.h:569
#define PG_INT64_MAX
Definition: c.h:576
#define PG_INT64_MIN
Definition: c.h:575
#define PG_UINT16_MAX
Definition: c.h:571
#define PG_UINT64_MAX
Definition: c.h:577
#define PG_INT32_MIN
Definition: c.h:572
#define PG_INT16_MAX
Definition: c.h:570
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:215
static bool pg_sub_u32_overflow(uint32 a, uint32 b, uint32 *result)
Definition: int.h:339
static bool pg_add_u32_overflow(uint32 a, uint32 b, uint32 *result)
Definition: int.h:321
static bool pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:188
static bool pg_add_u64_overflow(uint64 a, uint64 b, uint64 *result)
Definition: int.h:376
static bool pg_sub_s16_overflow(int16 a, int16 b, int16 *result)
Definition: int.h:65
static bool pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:140
static bool pg_mul_u16_overflow(uint16 a, uint16 b, uint16 *result)
Definition: int.h:300
static bool pg_mul_u32_overflow(uint32 a, uint32 b, uint32 *result)
Definition: int.h:355
static bool pg_mul_s16_overflow(int16 a, int16 b, int16 *result)
Definition: int.h:83
static bool pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result)
Definition: int.h:410
static bool pg_sub_u16_overflow(uint16 a, uint16 b, uint16 *result)
Definition: int.h:284
static bool pg_add_u16_overflow(uint16 a, uint16 b, uint16 *result)
Definition: int.h:266
static bool pg_add_s16_overflow(int16 a, int16 b, int16 *result)
Definition: int.h:47
static bool pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:122
static bool pg_add_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:161
static bool pg_sub_u64_overflow(uint64 a, uint64 b, uint64 *result)
Definition: int.h:394
static bool pg_add_s32_overflow(int32 a, int32 b, int32 *result)
Definition: int.h:104
int b
Definition: isn.c:70
int a
Definition: isn.c:69