LCOV - differential code coverage report
Current view: top level - src/include/common - int.h (source / functions) Coverage Total Hit CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 100.0 % 22 22 22
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 11 11 11
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  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 CBC          27 : pg_add_s16_overflow(int16 a, int16 b, int16 *result)
      48                 : {
      49                 : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
      50              27 :     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             609 : pg_sub_s16_overflow(int16 a, int16 b, int16 *result)
      66                 : {
      67                 : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
      68             609 :     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              27 : pg_mul_s16_overflow(int16 a, int16 b, int16 *result)
      84                 : {
      85                 : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
      86              27 :     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        10565990 : pg_add_s32_overflow(int32 a, int32 b, int32 *result)
     105                 : {
     106                 : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     107        10565990 :     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          713393 : pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
     123                 : {
     124                 : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     125          713393 :     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         1847938 : pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
     141                 : {
     142                 : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     143         1847938 :     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         9287990 : pg_add_s64_overflow(int64 a, int64 b, int64 *result)
     162                 : {
     163                 : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     164         9287990 :     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          154420 : pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
     189                 : {
     190                 : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     191          154420 :     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           38141 : pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
     216                 : {
     217                 : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     218           38141 :     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              74 : pg_add_u64_overflow(uint64 a, uint64 b, uint64 *result)
     377                 : {
     378                 : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     379              74 :     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              74 : pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result)
     411                 : {
     412                 : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     413              74 :     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 v1.16-55-g56c0a2a