Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7dedfd2

Browse files
committed
Add overflow-safe math inline functions for unsigned integers
Similarly to the signed versions added in4d6ad31, this adds a set ofinline functions for overflow checks with unsigned integers, includinguint16, uint32 and uint64. This relies on compiler built-in overflowchecks by default if available. The behavior of unsigned integers iswell-defined so the fallback implementations checks are simple foradditions and subtractions. Multiplications avoid division-based checkswhich are expensive if possible, still this can happen for uint64 if128-bit integers are not available.While on it, the code in common/int.h is reorganized to avoid too manyduplicated comments. The new macros will be used in a follow-up patch.All thanks to Andres Freund for the input provided.Author: Fabien Coelho, Michael PaquierDiscussion:https://postgr.es/m/20190830073423.GB2354@paquier.xyz
1 parent36515e4 commit7dedfd2

File tree

1 file changed

+203
-39
lines changed

1 file changed

+203
-39
lines changed

‎src/include/common/int.h

Lines changed: 203 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,28 @@
2020
#ifndefCOMMON_INT_H
2121
#defineCOMMON_INT_H
2222

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
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
2631
* 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
2745
*/
2846
staticinlinebool
2947
pg_add_s16_overflow(int16a,int16b,int16*result)
@@ -43,11 +61,6 @@ pg_add_s16_overflow(int16 a, int16 b, int16 *result)
4361
#endif
4462
}
4563

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-
*/
5164
staticinlinebool
5265
pg_sub_s16_overflow(int16a,int16b,int16*result)
5366
{
@@ -66,11 +79,6 @@ pg_sub_s16_overflow(int16 a, int16 b, int16 *result)
6679
#endif
6780
}
6881

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-
*/
7482
staticinlinebool
7583
pg_mul_s16_overflow(int16a,int16b,int16*result)
7684
{
@@ -90,9 +98,7 @@ pg_mul_s16_overflow(int16 a, int16 b, int16 *result)
9098
}
9199

92100
/*
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.
101+
* INT32
96102
*/
97103
staticinlinebool
98104
pg_add_s32_overflow(int32a,int32b,int32*result)
@@ -112,11 +118,6 @@ pg_add_s32_overflow(int32 a, int32 b, int32 *result)
112118
#endif
113119
}
114120

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-
*/
120121
staticinlinebool
121122
pg_sub_s32_overflow(int32a,int32b,int32*result)
122123
{
@@ -135,11 +136,6 @@ pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
135136
#endif
136137
}
137138

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-
*/
143139
staticinlinebool
144140
pg_mul_s32_overflow(int32a,int32b,int32*result)
145141
{
@@ -159,9 +155,7 @@ pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
159155
}
160156

161157
/*
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.
158+
* INT64
165159
*/
166160
staticinlinebool
167161
pg_add_s64_overflow(int64a,int64b,int64*result)
@@ -190,11 +184,6 @@ pg_add_s64_overflow(int64 a, int64 b, int64 *result)
190184
#endif
191185
}
192186

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-
*/
198187
staticinlinebool
199188
pg_sub_s64_overflow(int64a,int64b,int64*result)
200189
{
@@ -222,11 +211,6 @@ pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
222211
#endif
223212
}
224213

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-
*/
230214
staticinlinebool
231215
pg_mul_s64_overflow(int64a,int64b,int64*result)
232216
{
@@ -270,4 +254,184 @@ pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
270254
#endif
271255
}
272256

257+
/*------------------------------------------------------------------------
258+
* Overflow routines for unsigned integers
259+
*------------------------------------------------------------------------
260+
*/
261+
262+
/*
263+
* UINT16
264+
*/
265+
staticinlinebool
266+
pg_add_u16_overflow(uint16a,uint16b,uint16*result)
267+
{
268+
#if defined(HAVE__BUILTIN_OP_OVERFLOW)
269+
return__builtin_add_overflow(a,b,result);
270+
#else
271+
uint16res=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+
staticinlinebool
284+
pg_sub_u16_overflow(uint16a,uint16b,uint16*result)
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+
staticinlinebool
300+
pg_mul_u16_overflow(uint16a,uint16b,uint16*result)
301+
{
302+
#if defined(HAVE__BUILTIN_OP_OVERFLOW)
303+
return__builtin_mul_overflow(a,b,result);
304+
#else
305+
uint32res= (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+
staticinlinebool
321+
pg_add_u32_overflow(uint32a,uint32b,uint32*result)
322+
{
323+
#if defined(HAVE__BUILTIN_OP_OVERFLOW)
324+
return__builtin_add_overflow(a,b,result);
325+
#else
326+
uint32res=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+
staticinlinebool
339+
pg_sub_u32_overflow(uint32a,uint32b,uint32*result)
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+
staticinlinebool
355+
pg_mul_u32_overflow(uint32a,uint32b,uint32*result)
356+
{
357+
#if defined(HAVE__BUILTIN_OP_OVERFLOW)
358+
return__builtin_mul_overflow(a,b,result);
359+
#else
360+
uint64res= (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+
staticinlinebool
376+
pg_add_u64_overflow(uint64a,uint64b,uint64*result)
377+
{
378+
#if defined(HAVE__BUILTIN_OP_OVERFLOW)
379+
return__builtin_add_overflow(a,b,result);
380+
#else
381+
uint64res=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+
staticinlinebool
394+
pg_sub_u64_overflow(uint64a,uint64b,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+
staticinlinebool
410+
pg_mul_u64_overflow(uint64a,uint64b,uint64*result)
411+
{
412+
#if defined(HAVE__BUILTIN_OP_OVERFLOW)
413+
return__builtin_mul_overflow(a,b,result);
414+
#elif defined(HAVE_INT128)
415+
uint128res= (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+
uint64res=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+
273437
#endif/* COMMON_INT_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp