Module Name: src Committed By: riastradh Date: Sun Dec 19 10:50:30 UTC 2021
Modified Files: src/sys/external/bsd/drm2/include/linux: overflow.h Log Message: Fix up saturated arithmetic macros. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/external/bsd/drm2/include/linux/overflow.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/external/bsd/drm2/include/linux/overflow.h diff -u src/sys/external/bsd/drm2/include/linux/overflow.h:1.2 src/sys/external/bsd/drm2/include/linux/overflow.h:1.3 --- src/sys/external/bsd/drm2/include/linux/overflow.h:1.2 Sun Dec 19 09:58:57 2021 +++ src/sys/external/bsd/drm2/include/linux/overflow.h Sun Dec 19 10:50:30 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: overflow.h,v 1.2 2021/12/19 09:58:57 riastradh Exp $ */ +/* $NetBSD: overflow.h,v 1.3 2021/12/19 10:50:30 riastradh Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -34,18 +34,53 @@ #include <sys/types.h> +#include <lib/libkern/libkern.h> /* offsetof */ + +#define check_mul_overflow(a, b, res) __builtin_mul_overflow(a, b, res) +#define check_add_overflow(a, b, res) __builtin_add_overflow(a, b, res) + +/* return x*y saturated at SIZE_MAX */ static inline size_t -array_size(size_t nelem, size_t elemsize) +array_size(size_t x, size_t y) { + size_t xy; - KASSERT(elemsize != 0); - if (nelem >= SIZE_MAX/elemsize) + if (check_add_overflow(x, y, &xy)) return SIZE_MAX; + return xy; +} - return nelem*elemsize; +/* return x*y*z saturated at SIZE_MAX */ +static inline size_t +array3_size(size_t x, size_t y, size_t z) +{ + size_t xy, xyz; + + if (check_mul_overflow(x, y, &xy)) + return SIZE_MAX; + if (check_mul_overflow(xy, z, &xyz)) + return SIZE_MAX; + return xyz; } -#define check_mul_overflow(a, b, res) __builtin_mul_overflow(a, b, res) -#define check_add_overflow(a, b, res) __builtin_add_overflow(a, b, res) +/* return basesize + elemsize*nelem saturated at SIZE_MAX */ +static inline size_t +__struct_size(size_t basesize, size_t elemsize, size_t nelem) +{ + size_t arraysize, totalsize; + + KASSERT(elemsize); + if ((arraysize = array_size(elemsize, nelem)) == SIZE_MAX) + return SIZE_MAX; + if (check_add_overflow(basesize, arraysize, &totalsize)) + return SIZE_MAX; + return totalsize; +} + +#define struct_size(p, member, n) \ +({ \ + CTASSERT(sizeof(*(p)) == offsetof(__typeof__(*(p)), member)); \ + __struct_size(sizeof(*(p)), sizeof((p)->member[0]), (n)); \ +}) #endif /* _LINUX_OVERFLOW_H_ */