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>
nacl_bit_cast(const Source & source)327 inline Dest nacl_bit_cast(const Source& source) {
328   // A compile error here means your Dest and Source have different sizes.
329   NACL_ASSERT_SAME_SIZE(Dest, Source);
330 
331   Dest dest;
332   memcpy(&dest, &source, sizeof(dest));
333   return dest;
334 }
335 
336 #endif  /* __cplusplus */
337 
338 #endif  /* NATIVE_CLIENT_SRC_INCLUDE_NACL_MACROS_H_ */
339