#include <efivar.h>
#include "dp.h"
+#include "util.h"
static const efidp_header end_entire = {
.type = EFIDP_END_TYPE,
efidp_duplicate_extra(const_efidp dp, efidp *out, size_t extra)
{
ssize_t sz;
- size_t plus;
+ ssize_t plus;
efidp new;
if (sz < 0)
return sz;
- plus = (size_t)sz + extra;
- if (plus < (size_t)sz || plus < extra) {
- errno = ENOSPC;
+ if (add(sz, extra, &plus)) {
+ errno = EOVERFLOW;
return -1;
}
__attribute__((__visibility__ ("default")))
efidp_append_path(const_efidp dp0, const_efidp dp1, efidp *out)
{
- ssize_t lsz, rsz;
+ ssize_t lsz, rsz, newsz = 0;
const_efidp le;
int rc;
}
efidp new;
- new = malloc(lsz + rsz);
+ if (add(lsz, rsz, &newsz)) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ new = malloc(newsz);
if (!new)
return -1;
-
*out = new;
memcpy(new, dp0, lsz);
__attribute__((__visibility__ ("default")))
efidp_append_node(const_efidp dp, const_efidp dn, efidp *out)
{
- ssize_t lsz, rsz;
+ ssize_t lsz, rsz, newsz;
int rc;
if (!dp && !dn)
return efidp_duplicate_path((const_efidp)(const efidp_header * const)&end_entire, out);
+ lsz = efidp_size(dp);
+ if (lsz < 0)
+ return -1;
+
+
if (dp && !dn)
return efidp_duplicate_path(dp, out);
+ rsz = efidp_node_size(dn);
+ if (rsz < 0)
+ return -1;
+
if (!dp && dn) {
- efidp new = malloc(efidp_node_size(dn) + sizeof (end_entire));
+ if (add(rsz, sizeof(end_entire), &newsz)) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ efidp new = malloc(rsz + sizeof (end_entire));
if (!new)
return -1;
if (efidp_type(le) == EFIDP_END_TYPE &&
efidp_subtype(le) == EFIDP_END_ENTIRE) {
ssize_t lesz = efidp_size(le);
- if (lesz < 0)
- return -1;
lsz -= lesz;
break;
}
return -1;
}
- efidp new = malloc(lsz + rsz + sizeof (end_entire));
+ if (add(lsz, rsz, &newsz) || add(newsz, sizeof(end_entire), &newsz)) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+
+ efidp new = malloc(newsz);
if (!new)
return -1;
#define EFIVAR_UTIL_H 1
#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
+#include <tgmath.h>
#include <unistd.h>
+/*
+ * I'm not actually sure when these appear, but they're present in the
+ * version in front of me.
+ */
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+#if __GNUC__ >= 5 && __GNUC_MINOR__ >= 1
+#define long_add(a, b, c) __builtin_add_overflow(a, b, c)
+#define long_mult(a, b, c) __builtin_mul_overflow(a, b, c)
+#define ulong_add(a, b, c) __builtin_add_overflow(a, b, c)
+#define ulong_mult(a, b, c) __builtin_mul_overflow(a, b, c)
+#endif
+#endif
+#ifndef long_add
+#define long_add(a, b, c) ({ \
+ const long _limit = LONG_MAX; \
+ int _ret; \
+ _ret = _limit - (a) > (b); \
+ if (!_ret) \
+ *(c) = ((a) + (b)); \
+ _ret; \
+ })
+#endif
+#ifndef long_mult
+#define long_mult(a, b, c) ({ \
+ const long _limit = LONG_MAX; \
+ int _ret = 1; \
+ if ((a) == 0 || (b) == 0) \
+ _ret = 0; \
+ else \
+ _ret = _limit / (a) < (b); \
+ if (!_ret) \
+ *(c) = ((a) * (b)); \
+ _ret; \
+ })
+#endif
+#ifndef ulong_add
+#define ulong_add(a, b, c) ({ \
+ const unsigned long _limit = ULONG_MAX; \
+ int _ret; \
+ _ret = _limit - (a) > (b); \
+ if (!_ret) \
+ *(c) = ((a) + (b)); \
+ _ret; \
+ })
+#endif
+#ifndef ulong_mult
+#define ulong_mult(a, b, c) ({ \
+ const unsigned long _limit = ULONG_MAX; \
+ int _ret = 1; \
+ if ((a) == 0 || (b) == 0) \
+ _ret = 0; \
+ else \
+ _ret = _limit / (a) < (b); \
+ if (!_ret) \
+ *(c) = ((a) * (b)); \
+ _ret; \
+ })
+#endif
+
+#define add(a, b, c) _Generic((c), \
+ long *: long_add(a,b,c), \
+ unsigned long *: ulong_add(a,b,c))
+
+#define mult(a, b, c) _Generic((c), \
+ long *: long_mult(a,b,c), \
+ unsigned long *: ulong_mult(a,b,c))
+
static inline int
__attribute__((unused))
read_file(int fd, uint8_t **buf, size_t *bufsize)