]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
lib/adds.[ch]: Add addsl() and addsl3()
authorAlejandro Colomar <alx@kernel.org>
Wed, 20 Dec 2023 20:43:03 +0000 (21:43 +0100)
committerSerge Hallyn <serge@hallyn.com>
Fri, 5 Jan 2024 21:45:08 +0000 (15:45 -0600)
These functions add 2 or 3 longs, saturating to LONG_{MIN,MAX} instead
of overflowing.

Cc: Tobias Stoeckmann <tobias@stoeckmann.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
lib/Makefile.am
lib/adds.c [new file with mode: 0644]
lib/adds.h [new file with mode: 0644]

index cc79326b38321ee59b9e4c996c64b21978b57685..b437bbd397b902d6b6065324856005a75ba0162b 100644 (file)
@@ -23,6 +23,8 @@ libshadow_la_CFLAGS = $(LIBBSD_CFLAGS) $(LIBCRYPT_PAM) $(LIBSYSTEMD)
 
 libshadow_la_SOURCES = \
        addgrps.c \
+       adds.c \
+       adds.h \
        age.c \
        agetpass.c \
        agetpass.h \
diff --git a/lib/adds.c b/lib/adds.c
new file mode 100644 (file)
index 0000000..d442b75
--- /dev/null
@@ -0,0 +1,13 @@
+// SPDX-FileCopyrightText: 2023, Alejandro Colomar <alx@kernel.org>
+// SPDX-License-Identifier: BSD-3-Clause
+
+
+#include <config.h>
+
+#include "adds.h"
+
+
+extern inline long addsl(long a, long b);
+extern inline long addsl3(long a, long b, long c);
+
+extern inline int cmpl(const void *p1, const void *p2);
diff --git a/lib/adds.h b/lib/adds.h
new file mode 100644 (file)
index 0000000..dde5b5c
--- /dev/null
@@ -0,0 +1,72 @@
+// SPDX-FileCopyrightText: 2023, Alejandro Colomar <alx@kernel.org>
+// SPDX-License-Identifier: BSD-3-Clause
+
+
+#ifndef SHADOW_INCLUDE_LIB_ADDS_H_
+#define SHADOW_INCLUDE_LIB_ADDS_H_
+
+
+#include <config.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include "sizeof.h"
+
+
+inline long addsl(long a, long b);
+inline long addsl3(long a, long b, long c);
+
+inline int cmpl(const void *p1, const void *p2);
+
+
+inline long
+addsl(long a, long b)
+{
+       if (a > 0 && b > LONG_MAX - a) {
+               errno = EOVERFLOW;
+               return LONG_MAX;
+       }
+       if (a < 0 && b < LONG_MIN - a) {
+               errno = EOVERFLOW;
+               return LONG_MIN;
+       }
+       return a + b;
+}
+
+
+inline long
+addsl3(long a, long b, long c)
+{
+       int   e;
+       long  sum;
+       long  n[3] = {a, b, c};
+
+       e = errno;
+       qsort(n, NITEMS(n), sizeof(n[0]), cmpl);
+
+       errno = 0;
+       sum = addsl(n[0], n[2]);
+       if (errno == EOVERFLOW)
+               return sum;
+       errno = e;
+       return addsl(sum, n[1]);
+}
+
+
+inline int
+cmpl(const void *p1, const void *p2)
+{
+       const long  *l1 = p1;
+       const long  *l2 = p2;
+
+       if (*l1 < *l2)
+               return -1;
+       if (*l1 > *l2)
+               return +1;
+       return 0;
+}
+
+
+#endif  // include guard