LCOV - code coverage report
Current view: top level - src/include/common - int.h (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 22 22 100.0 %
Date: 2023-12-11 15:11:28 Functions: 11 11 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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
      47          54 : pg_add_s16_overflow(int16 a, int16 b, int16 *result)
      48             : {
      49             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
      50          54 :     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
      65        1218 : pg_sub_s16_overflow(int16 a, int16 b, int16 *result)
      66             : {
      67             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
      68        1218 :     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
      83          54 : pg_mul_s16_overflow(int16 a, int16 b, int16 *result)
      84             : {
      85             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
      86          54 :     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
     104    22362402 : pg_add_s32_overflow(int32 a, int32 b, int32 *result)
     105             : {
     106             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     107    22362402 :     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
     122     1445756 : pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
     123             : {
     124             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     125     1445756 :     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
     140     3035814 : pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
     141             : {
     142             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     143     3035814 :     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    21261464 : pg_add_s64_overflow(int64 a, int64 b, int64 *result)
     162             : {
     163             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     164    21261464 :     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      320782 : pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
     189             : {
     190             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     191      320782 :     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             :     /*
     204             :      * Note: overflow is also possible when a == 0 and b < 0 (specifically,
     205             :      * when b == PG_INT64_MIN).
     206             :      */
     207             :     if ((a < 0 && b > 0 && a < PG_INT64_MIN + b) ||
     208             :         (a >= 0 && b < 0 && a > PG_INT64_MAX + b))
     209             :     {
     210             :         *result = 0x5EED;       /* to avoid spurious warnings */
     211             :         return true;
     212             :     }
     213             :     *result = a - b;
     214             :     return false;
     215             : #endif
     216             : }
     217             : 
     218             : static inline bool
     219       78630 : pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
     220             : {
     221             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     222       78630 :     return __builtin_mul_overflow(a, b, result);
     223             : #elif defined(HAVE_INT128)
     224             :     int128      res = (int128) a * (int128) b;
     225             : 
     226             :     if (res > PG_INT64_MAX || res < PG_INT64_MIN)
     227             :     {
     228             :         *result = 0x5EED;       /* to avoid spurious warnings */
     229             :         return true;
     230             :     }
     231             :     *result = (int64) res;
     232             :     return false;
     233             : #else
     234             :     /*
     235             :      * Overflow can only happen if at least one value is outside the range
     236             :      * sqrt(min)..sqrt(max) so check that first as the division can be quite a
     237             :      * bit more expensive than the multiplication.
     238             :      *
     239             :      * Multiplying by 0 or 1 can't overflow of course and checking for 0
     240             :      * separately avoids any risk of dividing by 0.  Be careful about dividing
     241             :      * INT_MIN by -1 also, note reversing the a and b to ensure we're always
     242             :      * dividing it by a positive value.
     243             :      *
     244             :      */
     245             :     if ((a > PG_INT32_MAX || a < PG_INT32_MIN ||
     246             :          b > PG_INT32_MAX || b < PG_INT32_MIN) &&
     247             :         a != 0 && a != 1 && b != 0 && b != 1 &&
     248             :         ((a > 0 && b > 0 && a > PG_INT64_MAX / b) ||
     249             :          (a > 0 && b < 0 && b < PG_INT64_MIN / a) ||
     250             :          (a < 0 && b > 0 && a < PG_INT64_MIN / b) ||
     251             :          (a < 0 && b < 0 && a < PG_INT64_MAX / b)))
     252             :     {
     253             :         *result = 0x5EED;       /* to avoid spurious warnings */
     254             :         return true;
     255             :     }
     256             :     *result = a * b;
     257             :     return false;
     258             : #endif
     259             : }
     260             : 
     261             : /*------------------------------------------------------------------------
     262             :  * Overflow routines for unsigned integers
     263             :  *------------------------------------------------------------------------
     264             :  */
     265             : 
     266             : /*
     267             :  * UINT16
     268             :  */
     269             : static inline bool
     270             : pg_add_u16_overflow(uint16 a, uint16 b, uint16 *result)
     271             : {
     272             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     273             :     return __builtin_add_overflow(a, b, result);
     274             : #else
     275             :     uint16      res = a + b;
     276             : 
     277             :     if (res < a)
     278             :     {
     279             :         *result = 0x5EED;       /* to avoid spurious warnings */
     280             :         return true;
     281             :     }
     282             :     *result = res;
     283             :     return false;
     284             : #endif
     285             : }
     286             : 
     287             : static inline bool
     288             : pg_sub_u16_overflow(uint16 a, uint16 b, uint16 *result)
     289             : {
     290             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     291             :     return __builtin_sub_overflow(a, b, result);
     292             : #else
     293             :     if (b > a)
     294             :     {
     295             :         *result = 0x5EED;       /* to avoid spurious warnings */
     296             :         return true;
     297             :     }
     298             :     *result = a - b;
     299             :     return false;
     300             : #endif
     301             : }
     302             : 
     303             : static inline bool
     304             : pg_mul_u16_overflow(uint16 a, uint16 b, uint16 *result)
     305             : {
     306             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     307             :     return __builtin_mul_overflow(a, b, result);
     308             : #else
     309             :     uint32      res = (uint32) a * (uint32) b;
     310             : 
     311             :     if (res > PG_UINT16_MAX)
     312             :     {
     313             :         *result = 0x5EED;       /* to avoid spurious warnings */
     314             :         return true;
     315             :     }
     316             :     *result = (uint16) res;
     317             :     return false;
     318             : #endif
     319             : }
     320             : 
     321             : /*
     322             :  * INT32
     323             :  */
     324             : static inline bool
     325             : pg_add_u32_overflow(uint32 a, uint32 b, uint32 *result)
     326             : {
     327             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     328             :     return __builtin_add_overflow(a, b, result);
     329             : #else
     330             :     uint32      res = a + b;
     331             : 
     332             :     if (res < a)
     333             :     {
     334             :         *result = 0x5EED;       /* to avoid spurious warnings */
     335             :         return true;
     336             :     }
     337             :     *result = res;
     338             :     return false;
     339             : #endif
     340             : }
     341             : 
     342             : static inline bool
     343             : pg_sub_u32_overflow(uint32 a, uint32 b, uint32 *result)
     344             : {
     345             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     346             :     return __builtin_sub_overflow(a, b, result);
     347             : #else
     348             :     if (b > a)
     349             :     {
     350             :         *result = 0x5EED;       /* to avoid spurious warnings */
     351             :         return true;
     352             :     }
     353             :     *result = a - b;
     354             :     return false;
     355             : #endif
     356             : }
     357             : 
     358             : static inline bool
     359             : pg_mul_u32_overflow(uint32 a, uint32 b, uint32 *result)
     360             : {
     361             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     362             :     return __builtin_mul_overflow(a, b, result);
     363             : #else
     364             :     uint64      res = (uint64) a * (uint64) b;
     365             : 
     366             :     if (res > PG_UINT32_MAX)
     367             :     {
     368             :         *result = 0x5EED;       /* to avoid spurious warnings */
     369             :         return true;
     370             :     }
     371             :     *result = (uint32) res;
     372             :     return false;
     373             : #endif
     374             : }
     375             : 
     376             : /*
     377             :  * UINT64
     378             :  */
     379             : static inline bool
     380         178 : pg_add_u64_overflow(uint64 a, uint64 b, uint64 *result)
     381             : {
     382             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     383         178 :     return __builtin_add_overflow(a, b, result);
     384             : #else
     385             :     uint64      res = a + b;
     386             : 
     387             :     if (res < a)
     388             :     {
     389             :         *result = 0x5EED;       /* to avoid spurious warnings */
     390             :         return true;
     391             :     }
     392             :     *result = res;
     393             :     return false;
     394             : #endif
     395             : }
     396             : 
     397             : static inline bool
     398             : pg_sub_u64_overflow(uint64 a, uint64 b, uint64 *result)
     399             : {
     400             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     401             :     return __builtin_sub_overflow(a, b, result);
     402             : #else
     403             :     if (b > a)
     404             :     {
     405             :         *result = 0x5EED;       /* to avoid spurious warnings */
     406             :         return true;
     407             :     }
     408             :     *result = a - b;
     409             :     return false;
     410             : #endif
     411             : }
     412             : 
     413             : static inline bool
     414         178 : pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result)
     415             : {
     416             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     417         178 :     return __builtin_mul_overflow(a, b, result);
     418             : #elif defined(HAVE_INT128)
     419             :     uint128     res = (uint128) a * (uint128) b;
     420             : 
     421             :     if (res > PG_UINT64_MAX)
     422             :     {
     423             :         *result = 0x5EED;       /* to avoid spurious warnings */
     424             :         return true;
     425             :     }
     426             :     *result = (uint64) res;
     427             :     return false;
     428             : #else
     429             :     uint64      res = a * b;
     430             : 
     431             :     if (a != 0 && b != res / a)
     432             :     {
     433             :         *result = 0x5EED;       /* to avoid spurious warnings */
     434             :         return true;
     435             :     }
     436             :     *result = res;
     437             :     return false;
     438             : #endif
     439             : }
     440             : 
     441             : #endif                          /* COMMON_INT_H */

Generated by: LCOV version 1.14