History

tools: bpf: make use of reallocarray

reallocarray() is a safer variant of realloc which checks for multiplication overflow in case of array allocation. Since it's not available in Glibc < 2.26 import kernel's overflow.h and add a static inline implementation when needed. Use feature detection to probe for existence of reallocarray.

Jakub Kicinski committed 8 years ago

Commit 531b0141 parent 8d1340610 files · +334 −9Browse files

Showing the changes to tools/include/linux (2 of 10 files). Show all

Unified · Split

2 files
  1. tools/include/linux/compiler-gcc.h +4 −0
  2. tools/include/linux/overflow.h +278 −0
tools/include/linux/compiler-gcc.h+4−0
@@ -36,3 +36,7 @@ · 35 unmodified lines
3636 #endif
3737 #define __printf(a, b) __attribute__((format(printf, a, b)))
3838 #define __scanf(a, b) __attribute__((format(scanf, a, b)))
39+
40+#if GCC_VERSION >= 50100
41+#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
42+#endif
tools/include/linux/overflow.h+278−0
@@ -0,0 +1,278 @@
1+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
2+#ifndef __LINUX_OVERFLOW_H
3+#define __LINUX_OVERFLOW_H
4+
5+#include <linux/compiler.h>
6+
7+/*
8+ * In the fallback code below, we need to compute the minimum and
9+ * maximum values representable in a given type. These macros may also
10+ * be useful elsewhere, so we provide them outside the
11+ * COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW block.
12+ *
13+ * It would seem more obvious to do something like
14+ *
15+ * #define type_min(T) (T)(is_signed_type(T) ? (T)1 << (8*sizeof(T)-1) : 0)
16+ * #define type_max(T) (T)(is_signed_type(T) ? ((T)1 << (8*sizeof(T)-1)) - 1 : ~(T)0)
17+ *
18+ * Unfortunately, the middle expressions, strictly speaking, have
19+ * undefined behaviour, and at least some versions of gcc warn about
20+ * the type_max expression (but not if -fsanitize=undefined is in
21+ * effect; in that case, the warning is deferred to runtime...).
22+ *
23+ * The slightly excessive casting in type_min is to make sure the
24+ * macros also produce sensible values for the exotic type _Bool. [The
25+ * overflow checkers only almost work for _Bool, but that's
26+ * a-feature-not-a-bug, since people shouldn't be doing arithmetic on
27+ * _Bools. Besides, the gcc builtins don't allow _Bool* as third
28+ * argument.]
29+ *
30+ * Idea stolen from
31+ * https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html -
32+ * credit to Christian Biere.
33+ */
34+#define is_signed_type(type) (((type)(-1)) < (type)1)
35+#define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
36+#define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
37+#define type_min(T) ((T)((T)-type_max(T)-(T)1))
38+
39+
40+#ifdef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW
41+/*
42+ * For simplicity and code hygiene, the fallback code below insists on
43+ * a, b and *d having the same type (similar to the min() and max()
44+ * macros), whereas gcc's type-generic overflow checkers accept
45+ * different types. Hence we don't just make check_add_overflow an
46+ * alias for __builtin_add_overflow, but add type checks similar to
47+ * below.
48+ */
49+#define check_add_overflow(a, b, d) ({ \
50+ typeof(a) __a = (a); \
51+ typeof(b) __b = (b); \
52+ typeof(d) __d = (d); \
53+ (void) (&__a == &__b); \
54+ (void) (&__a == __d); \
55+ __builtin_add_overflow(__a, __b, __d); \
56+})
57+
58+#define check_sub_overflow(a, b, d) ({ \
59+ typeof(a) __a = (a); \
60+ typeof(b) __b = (b); \
61+ typeof(d) __d = (d); \
62+ (void) (&__a == &__b); \
63+ (void) (&__a == __d); \
64+ __builtin_sub_overflow(__a, __b, __d); \
65+})
66+
67+#define check_mul_overflow(a, b, d) ({ \
68+ typeof(a) __a = (a); \
69+ typeof(b) __b = (b); \
70+ typeof(d) __d = (d); \
71+ (void) (&__a == &__b); \
72+ (void) (&__a == __d); \
73+ __builtin_mul_overflow(__a, __b, __d); \
74+})
75+
76+#else
77+
78+
79+/* Checking for unsigned overflow is relatively easy without causing UB. */
80+#define __unsigned_add_overflow(a, b, d) ({ \
81+ typeof(a) __a = (a); \
82+ typeof(b) __b = (b); \
83+ typeof(d) __d = (d); \
84+ (void) (&__a == &__b); \
85+ (void) (&__a == __d); \
86+ *__d = __a + __b; \
87+ *__d < __a; \
88+})
89+#define __unsigned_sub_overflow(a, b, d) ({ \
90+ typeof(a) __a = (a); \
91+ typeof(b) __b = (b); \
92+ typeof(d) __d = (d); \
93+ (void) (&__a == &__b); \
94+ (void) (&__a == __d); \
95+ *__d = __a - __b; \
96+ __a < __b; \
97+})
98+/*
99+ * If one of a or b is a compile-time constant, this avoids a division.
100+ */
101+#define __unsigned_mul_overflow(a, b, d) ({ \
102+ typeof(a) __a = (a); \
103+ typeof(b) __b = (b); \
104+ typeof(d) __d = (d); \
105+ (void) (&__a == &__b); \
106+ (void) (&__a == __d); \
107+ *__d = __a * __b; \
108+ __builtin_constant_p(__b) ? \
109+ __b > 0 && __a > type_max(typeof(__a)) / __b : \
110+ __a > 0 && __b > type_max(typeof(__b)) / __a; \
111+})
112+
113+/*
114+ * For signed types, detecting overflow is much harder, especially if
115+ * we want to avoid UB. But the interface of these macros is such that
116+ * we must provide a result in *d, and in fact we must produce the
117+ * result promised by gcc's builtins, which is simply the possibly
118+ * wrapped-around value. Fortunately, we can just formally do the
119+ * operations in the widest relevant unsigned type (u64) and then
120+ * truncate the result - gcc is smart enough to generate the same code
121+ * with and without the (u64) casts.
122+ */
123+
124+/*
125+ * Adding two signed integers can overflow only if they have the same
126+ * sign, and overflow has happened iff the result has the opposite
127+ * sign.
128+ */
129+#define __signed_add_overflow(a, b, d) ({ \
130+ typeof(a) __a = (a); \
131+ typeof(b) __b = (b); \
132+ typeof(d) __d = (d); \
133+ (void) (&__a == &__b); \
134+ (void) (&__a == __d); \
135+ *__d = (u64)__a + (u64)__b; \
136+ (((~(__a ^ __b)) & (*__d ^ __a)) \
137+ & type_min(typeof(__a))) != 0; \
138+})
139+
140+/*
141+ * Subtraction is similar, except that overflow can now happen only
142+ * when the signs are opposite. In this case, overflow has happened if
143+ * the result has the opposite sign of a.
144+ */
145+#define __signed_sub_overflow(a, b, d) ({ \
146+ typeof(a) __a = (a); \
147+ typeof(b) __b = (b); \
148+ typeof(d) __d = (d); \
149+ (void) (&__a == &__b); \
150+ (void) (&__a == __d); \
151+ *__d = (u64)__a - (u64)__b; \
152+ ((((__a ^ __b)) & (*__d ^ __a)) \
153+ & type_min(typeof(__a))) != 0; \
154+})
155+
156+/*
157+ * Signed multiplication is rather hard. gcc always follows C99, so
158+ * division is truncated towards 0. This means that we can write the
159+ * overflow check like this:
160+ *
161+ * (a > 0 && (b > MAX/a || b < MIN/a)) ||
162+ * (a < -1 && (b > MIN/a || b < MAX/a) ||
163+ * (a == -1 && b == MIN)
164+ *
165+ * The redundant casts of -1 are to silence an annoying -Wtype-limits
166+ * (included in -Wextra) warning: When the type is u8 or u16, the
167+ * __b_c_e in check_mul_overflow obviously selects
168+ * __unsigned_mul_overflow, but unfortunately gcc still parses this
169+ * code and warns about the limited range of __b.
170+ */
171+
172+#define __signed_mul_overflow(a, b, d) ({ \
173+ typeof(a) __a = (a); \
174+ typeof(b) __b = (b); \
175+ typeof(d) __d = (d); \
176+ typeof(a) __tmax = type_max(typeof(a)); \
177+ typeof(a) __tmin = type_min(typeof(a)); \
178+ (void) (&__a == &__b); \
179+ (void) (&__a == __d); \
180+ *__d = (u64)__a * (u64)__b; \
181+ (__b > 0 && (__a > __tmax/__b || __a < __tmin/__b)) || \
182+ (__b < (typeof(__b))-1 && (__a > __tmin/__b || __a < __tmax/__b)) || \
183+ (__b == (typeof(__b))-1 && __a == __tmin); \
184+})
185+
186+
187+#define check_add_overflow(a, b, d) \
188+ __builtin_choose_expr(is_signed_type(typeof(a)), \
189+ __signed_add_overflow(a, b, d), \
190+ __unsigned_add_overflow(a, b, d))
191+
192+#define check_sub_overflow(a, b, d) \
193+ __builtin_choose_expr(is_signed_type(typeof(a)), \
194+ __signed_sub_overflow(a, b, d), \
195+ __unsigned_sub_overflow(a, b, d))
196+
197+#define check_mul_overflow(a, b, d) \
198+ __builtin_choose_expr(is_signed_type(typeof(a)), \
199+ __signed_mul_overflow(a, b, d), \
200+ __unsigned_mul_overflow(a, b, d))
201+
202+
203+#endif /* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */
204+
205+/**
206+ * array_size() - Calculate size of 2-dimensional array.
207+ *
208+ * @a: dimension one
209+ * @b: dimension two
210+ *
211+ * Calculates size of 2-dimensional array: @a * @b.
212+ *
213+ * Returns: number of bytes needed to represent the array or SIZE_MAX on
214+ * overflow.
215+ */
216+static inline __must_check size_t array_size(size_t a, size_t b)
217+{
218+ size_t bytes;
219+
220+ if (check_mul_overflow(a, b, &bytes))
221+ return SIZE_MAX;
222+
223+ return bytes;
224+}
225+
226+/**
227+ * array3_size() - Calculate size of 3-dimensional array.
228+ *
229+ * @a: dimension one
230+ * @b: dimension two
231+ * @c: dimension three
232+ *
233+ * Calculates size of 3-dimensional array: @a * @b * @c.
234+ *
235+ * Returns: number of bytes needed to represent the array or SIZE_MAX on
236+ * overflow.
237+ */
238+static inline __must_check size_t array3_size(size_t a, size_t b, size_t c)
239+{
240+ size_t bytes;
241+
242+ if (check_mul_overflow(a, b, &bytes))
243+ return SIZE_MAX;
244+ if (check_mul_overflow(bytes, c, &bytes))
245+ return SIZE_MAX;
246+
247+ return bytes;
248+}
249+
250+static inline __must_check size_t __ab_c_size(size_t n, size_t size, size_t c)
251+{
252+ size_t bytes;
253+
254+ if (check_mul_overflow(n, size, &bytes))
255+ return SIZE_MAX;
256+ if (check_add_overflow(bytes, c, &bytes))
257+ return SIZE_MAX;
258+
259+ return bytes;
260+}
261+
262+/**
263+ * struct_size() - Calculate size of structure with trailing array.
264+ * @p: Pointer to the structure.
265+ * @member: Name of the array member.
266+ * @n: Number of elements in the array.
267+ *
268+ * Calculates size of memory needed for structure @p followed by an
269+ * array of @n @member elements.
270+ *
271+ * Return: number of bytes needed or SIZE_MAX on overflow.
272+ */
273+#define struct_size(p, member, n) \
274+ __ab_c_size(n, \
275+ sizeof(*(p)->member) + __must_be_array((p)->member),\
276+ sizeof(*(p)))
277+
278+#endif /* __LINUX_OVERFLOW_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t