LCOV - code coverage report
Current view: directory - src/include - nacl_macros.h (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 5 0 0.0 %
Date: 2014-09-25 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : 
       8                 : /*
       9                 :  * NaCl Safety Macro Definitions
      10                 :  */
      11                 : #ifndef NATIVE_CLIENT_SRC_INCLUDE_NACL_MACROS_H_
      12                 : #define NATIVE_CLIENT_SRC_INCLUDE_NACL_MACROS_H_ 1
      13                 : 
      14                 : #include <stdio.h>
      15                 : #include <stdlib.h>
      16                 : 
      17                 : #define NACL_TO_STRING_INTERNAL(v) #v
      18                 : #define NACL_TO_STRING(v) NACL_TO_STRING_INTERNAL(v)
      19                 : 
      20                 : #define NACL_CONCAT_INTERNAL(a, b) a ## b
      21                 : #define NACL_CONCAT(a, b) NACL_CONCAT_INTERNAL(a, b)
      22                 : 
      23                 : /*****************************************************************************
      24                 :  * Safety macros                                                             *
      25                 :  *****************************************************************************/
      26                 : 
      27                 : #define NACL_ARRAY_SIZE_UNSAFE(arr) ((sizeof arr)/sizeof arr[0])
      28                 : 
      29                 : /*
      30                 :  * ASSERT_IS_ARRAY(arr) generates a somewhat opaque compile-time
      31                 :  * error if arr is a non-array pointer.  This protects against
      32                 :  * situations where one writes code like:
      33                 :  *
      34                 :  * foo.h:  struct Foo { char buffer[BUFFERSIZE]; size_t sofar; ... };
      35                 :  *
      36                 :  * foo.c:  got = read(d, fp->buffer + fp->sofar, sizeof fp->buffer - fp->sofar);
      37                 :  *         if (-1 == got) { ... }
      38                 :  *         fp->sofar += got;
      39                 :  *
      40                 :  *         for (ix = 0; ix < sizeof arr/sizeof arr[0]; ++ix) { ... }
      41                 :  *
      42                 :  * and have it break and create a security problem when somebody later
      43                 :  * changes Foo to dynamically allocate buffer, viz,
      44                 :  *
      45                 :  * foo.h:  struct Foo { char *buffer; size_t sofar; ... };
      46                 :  *
      47                 :  * and now sizeof fp->buffer is 4 or 8, with size_t (type of sizeof)
      48                 :  * being unsigned, when fp->sofar is larger than 4 or 8, getting an
      49                 :  * enormous maximum read size being used.  Such bugs can remain
      50                 :  * undiscovered when conforming implementations of protocol engines
      51                 :  * are used where the actual amount sent is small and would never
      52                 :  * cause a buffer overflow, but an adversarial implementation would be
      53                 :  * able to clobber the heap.  The solution is to write:
      54                 :  *
      55                 :  * foo.c:  NACL_ASSERT_IS_ARRAY(fp->buffer);
      56                 :  *         got = read(d, fp->buffer + fp->sofar, sizeof fp->buffer - fp->sofar);
      57                 :  *         if (-1 == got) { ... }
      58                 :  *         fp->sofar += got;
      59                 :  *
      60                 :  *         for (ix = 0; ix < NACL_ARRAY_SIZE(arr); ++ix) { ... }
      61                 :  *
      62                 :  * and when foo.h is modified, it will generate a compile-time error
      63                 :  * alerting the engineer makin the change that the read code will need to
      64                 :  * be modified.
      65                 :  */
      66                 : 
      67                 : #ifdef __cplusplus
      68                 : /*
      69                 :  * C++ version is taken from chrome's basictypes.h, and renamed to
      70                 :  * avoid collision in case of multiple includes.  NACL_ARRAY_SIZE
      71                 :  * relies on template matching failure if the argument is not an
      72                 :  * array.
      73                 :  */
      74                 : template <typename T, size_t N>
      75                 : char (&NaClArraySizeHelper(T (&array)[N]))[N];
      76                 : 
      77                 : #ifndef _MSC_VER
      78                 : template <typename T, size_t N>
      79                 : char (&NaClArraySizeHelper(const T (&array)[N]))[N];
      80                 : #endif  /* _MSC_VER */
      81                 : 
      82                 : #define NACL_ARRAY_SIZE(array) (sizeof(NaClArraySizeHelper(array)))
      83                 : 
      84                 : /*
      85                 :  * Dead code elimination will get rid of this if there are no
      86                 :  * compile-time errors generated by ARRAY_SIZE.
      87                 :  */
      88                 : #define NACL_ASSERT_IS_ARRAY(array)                     \
      89                 :   do {                                                  \
      90                 :     char __array__[NACL_ARRAY_SIZE(array)];             \
      91                 :     if (0 == sizeof __array__) {                        \
      92                 :       abort();                                          \
      93                 :     }                                                   \
      94                 :   } while (0)
      95                 : 
      96                 : #else  /* __cplusplus */
      97                 : 
      98                 : /*
      99                 :  * The C version uses the fact that __builtin_types_compatible_p can
     100                 :  * be used to discriminate between T * and T *const.  (Note that this
     101                 :  * difference is not a top-level qualifier difference as mentioned in
     102                 :  * the gcc info node; that would apply to T * versus T const *.)  In
     103                 :  * the assertion statement version (NACL_ASSERT_IS_ARRAY), we use this
     104                 :  * to declare an array, and ISO C forbids a negative-sized array.
     105                 :  */
     106                 : # if __GNUC__
     107                 : 
     108                 : #  define NACL_ASSERT_IS_ARRAY_HELPER(arr)                                \
     109                 :   sizeof(char[1-2*__builtin_types_compatible_p(__typeof__(&arr[0]),       \
     110                 :                                                        __typeof__(arr))])
     111                 : 
     112                 : #  define NACL_ASSERT_IS_ARRAY(arr)         \
     113                 :   ((void) NACL_ASSERT_IS_ARRAY_HELPER(arr))
     114                 : 
     115                 : #  define NACL_ARRAY_SIZE(arr)                                         \
     116                 :   (NACL_ASSERT_IS_ARRAY_HELPER(arr) ? NACL_ARRAY_SIZE_UNSAFE(arr) : 0)
     117                 : 
     118                 : # else  /* __GNUC__ */
     119                 : 
     120                 : /*
     121                 :  * Not gcc.  So far, we only compile NaCl under gcc and visual studio,
     122                 :  * but if/when a new compiler is introduced that's capable of doing
     123                 :  * compile-time checking (or we figure out how to do it w/ visual
     124                 :  * studio), check for those compilers here, and enable the
     125                 :  * corresponding compile-failure tests in
     126                 :  * src/trusted/service_runtime/build.scons.
     127                 :  */
     128                 : 
     129                 : #  define NACL_ASSERT_IS_ARRAY(arr)
     130                 : #  define NACL_ARRAY_SIZE(arr) NACL_ARRAY_SIZE_UNSAFE(arr)
     131                 : # endif  /* __GNUC__ */
     132                 : #endif  /* __cplusplus */
     133                 : 
     134                 : /*
     135                 :  * NACL_ASSERT_IS_POINTER(arr) generates a somewhat opaque compile-time
     136                 :  * error if lvalue is not a pointer lvalue but is instead an actual
     137                 :  * array (which is a T * const object).  This is complementary to
     138                 :  * NACL_ASSERT_IS_ARRAY.
     139                 :  */
     140                 : #define NACL_ASSERT_IS_POINTER(ptr) do { if (0) { ++ptr; } } while (0)
     141                 : 
     142                 : /*
     143                 :  * NACL_ASSERT_SAME_SIZE(t1, t2) verifies that the two types have the same size
     144                 :  * (as reported by sizeof).  When the check fails it generates a somewhat
     145                 :  * opaque warning, mitigated by the variable's name.
     146                 :  *
     147                 :  * Examples:
     148                 :  *   NACL_ASSERT_SAME_SIZE(void *, char *);  // Likely to succeed!
     149                 :  *   NACL_ASSERT_SAME_SIZE(char, long);  // Unlikely to succeed
     150                 :  */
     151                 : #define NACL_ASSERT_SAME_SIZE(t1, t2) \
     152                 :   NACL_COMPILE_TIME_ASSERT(sizeof(t1) == sizeof(t2))
     153                 : 
     154                 : /*
     155                 :  * NACL_COMPILE_TIME_ASSERT(boolexp) verifies that the argument
     156                 :  * boolexp is true.  The check occurs at compile time.
     157                 :  *
     158                 :  * Example:
     159                 :  *
     160                 :  * NACL_COMPILE_TIME_ASSERT(NACL_MAX_VAL(int32_t) <= SIZE_T_MAX)
     161                 :  *
     162                 :  * to explicitly state the assumption that an int32_t expression -- if
     163                 :  * containing a non-negative number -- will fit in a size_t variable.
     164                 :  *
     165                 :  * We don't use an array type here because GCC supports variable-length
     166                 :  * arrays and so an expression that is not actually compile-time constant
     167                 :  * could be used and not get any compile-time error.  The size of a bitfield
     168                 :  * can never be anything but a compile-time constant, so we use that instead.
     169                 :  * MSVC doesn't support VLAs, so we use the array trick there.
     170                 :  */
     171                 : #if defined(OS_WIN)
     172                 : #define NACL_COMPILE_TIME_ASSERT(boolexp)               \
     173                 :   do {                                                  \
     174                 :     /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */             \
     175                 :     char compile_time_assert[(boolexp) ? 1 : -1];       \
     176                 :     (void) compile_time_assert;                         \
     177                 :   } while (0)
     178                 : #else /* !OS_WIN */
     179                 : #define NACL_COMPILE_TIME_ASSERT(boolexp)                       \
     180                 :   do {                                                          \
     181                 :     struct {                                                    \
     182                 :       unsigned int compile_time_assert: (boolexp) ? 1 : -1;     \
     183                 :     } compile_time_assert;                                      \
     184                 :     (void) compile_time_assert;                                 \
     185                 :   } while (0)
     186                 : #endif /* OS_WIN */
     187                 : 
     188                 : /*****************************************************************************
     189                 :  * MAX/MIN macros for integral types                                         *
     190                 :  ****************************************************************************/
     191                 : 
     192                 : /*
     193                 :  * For NACL_MAX_VAL, T must be a type where u ## T is the unsigned
     194                 :  * version of the type.
     195                 :  *
     196                 :  * These macros rely on -1 being signed extended to the width of T (or
     197                 :  * u ## T), and on two's complement representation of integers.
     198                 :  *
     199                 :  * Generally, stdint.h's INT16_MAX etc can be used, but these are
     200                 :  * useful for macros that take a type parameter and need the max or
     201                 :  * min value for the type, since then the macro would not have to also take
     202                 :  * the max or min value as additional parameter(s).
     203                 :  */
     204                 : #define NACL_UMAX_VAL(T)  ((T) -1)
     205                 : #define NACL_MAX_VAL(T)   ((T) (((u ## T) -1) >> 1))
     206                 : #define NACL_UMIN_VAL(T)  ((T) 0)
     207                 : #define NACL_MIN_VAL(T)   ((T) ~NACL_MAX_VAL(T))
     208                 : 
     209                 : 
     210                 : /*****************************************************************************
     211                 :  * Readability macros                                                        *
     212                 :  ****************************************************************************/
     213                 : 
     214                 : #define NACL_NANOS_PER_MICRO          (1000)
     215                 : #define NACL_100_NANOS_PER_MILLI      (10 * 1000)
     216                 : #define NACL_NANOS_PER_MILLI          (1000 * 1000)
     217                 : #define NACL_MICROS_PER_MILLI         (1000)
     218                 : #define NACL_NANOS_PER_UNIT           (1000 * 1000 * 1000)
     219                 : #define NACL_MICROS_PER_UNIT          (1000 * 1000)
     220                 : #define NACL_MILLIS_PER_UNIT          (1000)
     221                 : #define NACL_UNIT_CONVERT_ROUND(v, m) (((v) + (m) - 1)/(m))
     222                 : 
     223                 : #define NACL_NO_FILE_DESC             (-1)
     224                 : #define NACL_NO_URL                   ""
     225                 : #define NACL_NO_FILE_PATH             ""
     226                 : 
     227                 : #define NACL_HTTP_STATUS_OK           200
     228                 : 
     229                 : /*****************************************************************************
     230                 :  * C++ coding convention macros                                              *
     231                 :  ****************************************************************************/
     232                 : 
     233                 : #ifdef __cplusplus
     234                 : /*
     235                 :  * A macro to disallow the default constructor.
     236                 :  * This should be used in the private: declarations for a class
     237                 :  */
     238                 : #define NACL_DISALLOW_DEFAULT(TypeName) \
     239                 :     TypeName();
     240                 : 
     241                 : /*
     242                 :  * A macro to disallow the copy constructor and operator= functions.
     243                 :  * This should be used in the private: declarations for a class
     244                 :  */
     245                 : #define NACL_DISALLOW_COPY_AND_ASSIGN(TypeName) \
     246                 :     TypeName(const TypeName&);                  \
     247                 :     void operator=(const TypeName&)
     248                 : 
     249                 : /*
     250                 :  * A macro to disallow the default, copy constructor and operator= functions.
     251                 :  * This should be used in the private: declarations for a class
     252                 :  */
     253                 : #define NACL_DISALLOW_DEFAULT_COPY_AND_ASSIGN(TypeName) \
     254                 :     NACL_DISALLOW_DEFAULT(TypeName)                     \
     255                 :     NACL_DISALLOW_COPY_AND_ASSIGN(TypeName)
     256                 : 
     257                 : /* A macro to use in place of unimplemented sections of code. */
     258                 : #define NACL_UNIMPLEMENTED()                                       \
     259                 :     fprintf(stderr, "%s:%d: unimplemented\n", __FILE__, __LINE__); \
     260                 :     exit(1);
     261                 : 
     262                 : /* A macro to use to detect when control reaches a statement it should not. */
     263                 : #define NACL_NOTREACHED()                                                  \
     264                 :     fprintf(stderr, "%s:%d: should not reach here\n", __FILE__, __LINE__); \
     265                 :     exit(1);
     266                 : 
     267                 : /* A macro to mark code that has not been tested manually or automatically. */
     268                 : #define NACL_UNTESTED()                                                    \
     269                 :     fprintf(stderr, "%s:%d: reached untested code\n", __FILE__, __LINE__); \
     270                 :     exit(1);
     271                 : 
     272                 : // nacl_bit_cast<Dest,Source> is a template function that implements the
     273                 : // equivalent of "*reinterpret_cast<Dest*>(&source)".  We need this in
     274                 : // very low-level functions like the protobuf library and fast math
     275                 : // support.
     276                 : //
     277                 : //   float f = 3.14159265358979;
     278                 : //   int i = nacl_bit_cast<int32>(f);
     279                 : //   // i = 0x40490fdb
     280                 : //
     281                 : // The classical address-casting method is:
     282                 : //
     283                 : //   // WRONG
     284                 : //   float f = 3.14159265358979;            // WRONG
     285                 : //   int i = * reinterpret_cast<int*>(&f);  // WRONG
     286                 : //
     287                 : // The address-casting method actually produces undefined behavior
     288                 : // according to ISO C++ specification section 3.10 -15 -.  Roughly, this
     289                 : // section says: if an object in memory has one type, and a program
     290                 : // accesses it with a different type, then the result is undefined
     291                 : // behavior for most values of "different type".
     292                 : //
     293                 : // This is true for any cast syntax, either *(int*)&f or
     294                 : // *reinterpret_cast<int*>(&f).  And it is particularly true for
     295                 : // conversions betweeen integral lvalues and floating-point lvalues.
     296                 : //
     297                 : // The purpose of 3.10 -15- is to allow optimizing compilers to assume
     298                 : // that expressions with different types refer to different memory.  gcc
     299                 : // 4.0.1 has an optimizer that takes advantage of this.  So a
     300                 : // non-conforming program quietly produces wildly incorrect output.
     301                 : //
     302                 : // The problem is not the use of reinterpret_cast.  The problem is type
     303                 : // punning: holding an object in memory of one type and reading its bits
     304                 : // back using a different type.
     305                 : //
     306                 : // The C++ standard is more subtle and complex than this, but that
     307                 : // is the basic idea.
     308                 : //
     309                 : // Anyways ...
     310                 : //
     311                 : // nacl_bit_cast<> calls memcpy() which is blessed by the standard,
     312                 : // especially by the example in section 3.9 .  Also, of course,
     313                 : // nacl_bit_cast<> wraps up the nasty logic in one place.
     314                 : //
     315                 : // Fortunately memcpy() is very fast.  In optimized mode, with a
     316                 : // constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline
     317                 : // code with the minimal amount of data movement.  On a 32-bit system,
     318                 : // memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8)
     319                 : // compiles to two loads and two stores.
     320                 : //
     321                 : // I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1.
     322                 : //
     323                 : // WARNING: if Dest or Source is a non-POD type, the result of the memcpy
     324                 : // is likely to surprise you.
     325                 : 
     326                 : template <class Dest, class Source>
     327               0 : inline Dest nacl_bit_cast(const Source& source) {
     328                 :   // A compile error here means your Dest and Source have different sizes.
     329               0 :   NACL_ASSERT_SAME_SIZE(Dest, Source);
     330                 : 
     331                 :   Dest dest;
     332               0 :   memcpy(&dest, &source, sizeof(dest));
     333               0 :   return dest;
     334               0 : }
     335                 : 
     336                 : #endif  /* __cplusplus */
     337                 : 
     338                 : #endif  /* NATIVE_CLIENT_SRC_INCLUDE_NACL_MACROS_H_ */

Generated by: LCOV version 1.7