LCOV - code coverage report
Current view: top level - src/include/common - int.h (source / functions) Hit Total Coverage
Test: PostgreSQL 16beta1 Lines: 22 22 100.0 %
Date: 2023-06-02 19:12:20 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    20893176 : pg_add_s32_overflow(int32 a, int32 b, int32 *result)
     105             : {
     106             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     107    20893176 :     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     1426736 : pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
     123             : {
     124             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     125     1426736 :     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     3696014 : pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
     141             : {
     142             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     143     3696014 :     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    21080970 : pg_add_s64_overflow(int64 a, int64 b, int64 *result)
     162             : {
     163             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     164    21080970 :     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      317860 : pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
     189             : {
     190             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     191      317860 :     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       76384 : pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
     216             : {
     217             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     218       76384 :     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
     266             : pg_add_u16_overflow(uint16 a, uint16 b, uint16 *result)
     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
     284             : pg_sub_u16_overflow(uint16 a, uint16 b, 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             : static inline bool
     300             : pg_mul_u16_overflow(uint16 a, uint16 b, uint16 *result)
     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
     321             : pg_add_u32_overflow(uint32 a, uint32 b, uint32 *result)
     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
     339             : pg_sub_u32_overflow(uint32 a, uint32 b, 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             : static inline bool
     355             : pg_mul_u32_overflow(uint32 a, uint32 b, uint32 *result)
     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         148 : pg_add_u64_overflow(uint64 a, uint64 b, uint64 *result)
     377             : {
     378             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     379         148 :     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         148 : pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result)
     411             : {
     412             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     413         148 :     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 */

Generated by: LCOV version 1.14