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