44
55#include <linux/compiler.h>
66#include <linux/limits.h>
7+ #include <linux/const.h>
78
89/*
910 * We need to compute the minimum and maximum values representable in a given
@@ -118,81 +119,94 @@ static inline bool __must_check __must_check_overflow(bool overflow)
118119}))
119120
120121/**
121- * array_size() - Calculate size of 2-dimensional array.
122- *
123- * @a: dimension one
124- * @b: dimension two
122+ * size_mul() - Calculate size_t multiplication with saturation at SIZE_MAX
125123 *
126- * Calculates size of 2-dimensional array: @a * @b.
124+ * @factor1: first factor
125+ * @factor2: second factor
127126 *
128- * Returns: number of bytes needed to represent the array or SIZE_MAX on
129- * overflow.
127+ * Returns: calculate @factor1 * @factor2, both promoted to size_t,
128+ * with any overflow causing the return value to be SIZE_MAX. The
129+ * lvalue must be size_t to avoid implicit type conversion.
130130 */
131- static inline __must_check size_t array_size (size_t a , size_t b )
131+ static inline size_t __must_check size_mul (size_t factor1 , size_t factor2 )
132132{
133133 size_t bytes ;
134134
135- if (check_mul_overflow (a , b , & bytes ))
135+ if (check_mul_overflow (factor1 , factor2 , & bytes ))
136136 return SIZE_MAX ;
137137
138138 return bytes ;
139139}
140140
141141/**
142- * array3_size () - Calculate size of 3-dimensional array.
142+ * size_add () - Calculate size_t addition with saturation at SIZE_MAX
143143 *
144- * @a: dimension one
145- * @b: dimension two
146- * @c: dimension three
147- *
148- * Calculates size of 3-dimensional array: @a * @b * @c.
144+ * @addend1: first addend
145+ * @addend2: second addend
149146 *
150- * Returns: number of bytes needed to represent the array or SIZE_MAX on
151- * overflow.
147+ * Returns: calculate @addend1 + @addend2, both promoted to size_t,
148+ * with any overflow causing the return value to be SIZE_MAX. The
149+ * lvalue must be size_t to avoid implicit type conversion.
152150 */
153- static inline __must_check size_t array3_size (size_t a , size_t b , size_t c )
151+ static inline size_t __must_check size_add (size_t addend1 , size_t addend2 )
154152{
155153 size_t bytes ;
156154
157- if (check_mul_overflow (a , b , & bytes ))
158- return SIZE_MAX ;
159- if (check_mul_overflow (bytes , c , & bytes ))
155+ if (check_add_overflow (addend1 , addend2 , & bytes ))
160156 return SIZE_MAX ;
161157
162158 return bytes ;
163159}
164160
165- /*
166- * Compute a*b+c, returning SIZE_MAX on overflow. Internal helper for
167- * struct_size() below.
161+ /**
162+ * size_sub() - Calculate size_t subtraction with saturation at SIZE_MAX
163+ *
164+ * @minuend: value to subtract from
165+ * @subtrahend: value to subtract from @minuend
166+ *
167+ * Returns: calculate @minuend - @subtrahend, both promoted to size_t,
168+ * with any overflow causing the return value to be SIZE_MAX. For
169+ * composition with the size_add() and size_mul() helpers, neither
170+ * argument may be SIZE_MAX (or the result with be forced to SIZE_MAX).
171+ * The lvalue must be size_t to avoid implicit type conversion.
168172 */
169- static inline __must_check size_t __ab_c_size (size_t a , size_t b , size_t c )
173+ static inline size_t __must_check size_sub (size_t minuend , size_t subtrahend )
170174{
171175 size_t bytes ;
172176
173- if (check_mul_overflow (a , b , & bytes ))
174- return SIZE_MAX ;
175- if (check_add_overflow (bytes , c , & bytes ))
177+ if (minuend == SIZE_MAX || subtrahend == SIZE_MAX ||
178+ check_sub_overflow (minuend , subtrahend , & bytes ))
176179 return SIZE_MAX ;
177180
178181 return bytes ;
179182}
180183
181184/**
182- * struct_size() - Calculate size of structure with trailing array.
183- * @p: Pointer to the structure.
184- * @member: Name of the array member.
185- * @count: Number of elements in the array.
185+ * array_size() - Calculate size of 2-dimensional array.
186186 *
187- * Calculates size of memory needed for structure @p followed by an
188- * array of @count number of @member elements.
187+ * @a: dimension one
188+ * @b: dimension two
189189 *
190- * Return: number of bytes needed or SIZE_MAX on overflow.
190+ * Calculates size of 2-dimensional array: @a * @b.
191+ *
192+ * Returns: number of bytes needed to represent the array or SIZE_MAX on
193+ * overflow.
191194 */
192- #define struct_size (p , member , count ) \
193- __ab_c_size(count, \
194- sizeof(*(p)->member) + __must_be_array((p)->member),\
195- sizeof(*(p)))
195+ #define array_size (a , b ) size_mul(a, b)
196+
197+ /**
198+ * array3_size() - Calculate size of 3-dimensional array.
199+ *
200+ * @a: dimension one
201+ * @b: dimension two
202+ * @c: dimension three
203+ *
204+ * Calculates size of 3-dimensional array: @a * @b * @c.
205+ *
206+ * Returns: number of bytes needed to represent the array or SIZE_MAX on
207+ * overflow.
208+ */
209+ #define array3_size (a , b , c ) size_mul(size_mul(a, b), c)
196210
197211/**
198212 * flex_array_size() - Calculate size of a flexible array member
@@ -208,7 +222,25 @@ static inline __must_check size_t __ab_c_size(size_t a, size_t b, size_t c)
208222 * Return: number of bytes needed or SIZE_MAX on overflow.
209223 */
210224#define flex_array_size (p , member , count ) \
211- array_size(count, \
212- sizeof(*(p)->member) + __must_be_array((p)->member))
225+ __builtin_choose_expr(__is_constexpr(count), \
226+ (count) * sizeof(*(p)->member) + __must_be_array((p)->member), \
227+ size_mul(count, sizeof(*(p)->member) + __must_be_array((p)->member)))
228+
229+ /**
230+ * struct_size() - Calculate size of structure with trailing flexible array.
231+ *
232+ * @p: Pointer to the structure.
233+ * @member: Name of the array member.
234+ * @count: Number of elements in the array.
235+ *
236+ * Calculates size of memory needed for structure @p followed by an
237+ * array of @count number of @member elements.
238+ *
239+ * Return: number of bytes needed or SIZE_MAX on overflow.
240+ */
241+ #define struct_size (p , member , count ) \
242+ __builtin_choose_expr(__is_constexpr(count), \
243+ sizeof(*(p)) + flex_array_size(p, member, count), \
244+ size_add(sizeof(*(p)), flex_array_size(p, member, count)))
213245
214246#endif /* __LINUX_OVERFLOW_H */
0 commit comments