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