OSDN Git Service

util.h: add some math utilities
authorPeter Jones <pjones@redhat.com>
Fri, 5 Aug 2016 21:06:29 +0000 (17:06 -0400)
committerPeter Jones <pjones@redhat.com>
Tue, 9 Aug 2016 16:01:08 +0000 (12:01 -0400)
Signed-off-by: Peter Jones <pjones@redhat.com>
src/dp.c
src/util.h

index 4c45046..2c96a18 100644 (file)
--- a/src/dp.c
+++ b/src/dp.c
@@ -24,6 +24,7 @@
 
 #include <efivar.h>
 #include "dp.h"
+#include "util.h"
 
 static const efidp_header end_entire = {
        .type = EFIDP_END_TYPE,
@@ -60,7 +61,7 @@ static inline int
 efidp_duplicate_extra(const_efidp dp, efidp *out, size_t extra)
 {
        ssize_t sz;
-       size_t plus;
+       ssize_t plus;
 
        efidp new;
 
@@ -68,9 +69,8 @@ efidp_duplicate_extra(const_efidp dp, efidp *out, size_t extra)
        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;
        }
 
@@ -94,7 +94,7 @@ int
 __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;
 
@@ -132,10 +132,13 @@ efidp_append_path(const_efidp dp0, const_efidp dp1, efidp *out)
        }
 
        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);
@@ -148,17 +151,30 @@ int
 __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;
 
@@ -183,8 +199,6 @@ efidp_append_node(const_efidp dp, const_efidp dn, efidp *out)
                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;
                }
@@ -194,7 +208,12 @@ efidp_append_node(const_efidp dp, const_efidp dn, efidp *out)
                        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;
 
index 1de7bcb..80f5fab 100644 (file)
 #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)