Files
shadow/lib/adds.h
Alejandro Colomar 89e5a32966 lib/adds.[ch]: Add addsl() and addsl3()
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>
2024-01-05 15:45:08 -06:00

73 lines
1.1 KiB
C

// 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