Skip to content

Commit 335aaac

Browse files
authored
Merge pull request #678 from sanpeqf/refactor-overflow
Refactor overflow
2 parents 3c4d4f0 + 87db8c2 commit 335aaac

File tree

10 files changed

+153
-9
lines changed

10 files changed

+153
-9
lines changed

examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ add_subdirectory(matrix)
3535
add_subdirectory(mpi)
3636
add_subdirectory(notifier)
3737
add_subdirectory(once)
38+
add_subdirectory(overflow)
3839
add_subdirectory(prandom)
3940
add_subdirectory(radix)
4041
add_subdirectory(ratelimit)

examples/overflow/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# SPDX-License-Identifier: GPL-2.0-or-later
2+
/overflow-simple

examples/overflow/CMakeLists.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# SPDX-License-Identifier: GPL-2.0-or-later
2+
#
3+
# Copyright(c) 2023 ffashion <helloworldffashion@gmail.com>
4+
#
5+
6+
add_executable(overflow-simple simple.c)
7+
target_link_libraries(overflow-simple bfdev)
8+
add_test(overflow-simple overflow-simple)
9+
10+
if(${CMAKE_PROJECT_NAME} STREQUAL "bfdev")
11+
install(FILES
12+
simple.c
13+
DESTINATION
14+
${CMAKE_INSTALL_DOCDIR}/examples/overflow
15+
)
16+
17+
install(TARGETS
18+
overflow-simple
19+
DESTINATION
20+
${CMAKE_INSTALL_DOCDIR}/bin
21+
)
22+
endif()

examples/overflow/simple.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
/*
3+
* Copyright(c) 2023 John Sanpe <sanpeqf@gmail.com>
4+
*/
5+
6+
#define MODULE_NAME "overflow-simple"
7+
#define bfdev_log_fmt(fmt) MODULE_NAME ": " fmt
8+
9+
#include <bfdev/log.h>
10+
#include <bfdev/overflow.h>
11+
12+
int
13+
main(int argc, const char *argv[])
14+
{
15+
bfdev_log_info("(signed char)127 + 1 = %d\n",
16+
bfdev_overflow_add((signed char)127, 1));
17+
18+
bfdev_log_info("(unsigned char)255 + 1 = %d\n",
19+
bfdev_overflow_add((unsigned char)255, 1));
20+
21+
bfdev_log_info("(signed char)-128 - 1 = %d\n",
22+
bfdev_overflow_sub((signed char)-128, 1));
23+
24+
bfdev_log_info("(unsigned char)0 - 1 = %d\n",
25+
bfdev_overflow_sub((unsigned char)0, 1));
26+
27+
return 0;
28+
}

include/bfdev/compiler.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ BFDEV_BEGIN_DECLS
3838
#define bfdev_is_signed(type) (((type)(-1)) < (type)1)
3939
#define bfdev_is_unsigned(type) (!bfdev_is_signed(type))
4040

41+
#define bfdev_type_half_max(type) \
42+
((type)1 << (8 * sizeof(type) - 1 - bfdev_is_signed(type)))
43+
44+
#define bfdev_type_max(type) \
45+
((type)((bfdev_type_half_max(type) - 1) + bfdev_type_half_max(type)))
46+
47+
#define bfdev_type_min(type) \
48+
(((type)((type)-bfdev_type_max(type) - (type)1)))
49+
4150
/* Not-quite-unique ID. */
4251
#ifndef __BFDEV_UNIQUE_ID
4352
# define __BFDEV_UNIQUE_ID(prefix) __BFDEV_PASTE(__BFDEV_PASTE(__UNIQUE_ID_, prefix), __LINE__)

include/bfdev/overflow.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <bfdev/config.h>
1010
#include <bfdev/types.h>
1111
#include <bfdev/stddef.h>
12+
#include <bfdev/limits.h>
1213

1314
BFDEV_BEGIN_DECLS
1415

@@ -18,7 +19,7 @@ BFDEV_BEGIN_DECLS
1819
* @b: second addend.
1920
* @d: pointer to store sum.
2021
*
21-
* Returns 0 on success.
22+
* Returns true on wrap-around, false otherwise.
2223
*/
2324
#define bfdev_overflow_check_add(a, b, d) \
2425
bfdev_overflow_check(({ \
@@ -36,7 +37,7 @@ bfdev_overflow_check(({ \
3637
* @b: subtrahend; value to subtract from @a.
3738
* @d: pointer to store difference.
3839
*
39-
* Returns 0 on success.
40+
* Returns true on wrap-around, false otherwise.
4041
*/
4142
#define bfdev_overflow_check_sub(a, b, d) \
4243
bfdev_overflow_check(({ \
@@ -54,7 +55,7 @@ bfdev_overflow_check(({ \
5455
* @b: second factor.
5556
* @d: pointer to store product.
5657
*
57-
* Returns 0 on success.
58+
* Returns true on wrap-around, false otherwise.
5859
*/
5960
#define bfdev_overflow_check_mul(a, b, d) \
6061
bfdev_overflow_check(({ \
@@ -71,23 +72,23 @@ bfdev_overflow_check(({ \
7172
type __b = (type)(b); \
7273
type __d; \
7374
bfdev_overflow_check_add(__a, __b, &__d) \
74-
? (type)~0ULL : __d; \
75+
? bfdev_type_max(type) : __d; \
7576
})
7677

7778
#define bfdev_overflow_sub_type(type, a, b) ({ \
7879
type __a = (type)(a); \
7980
type __b = (type)(b); \
8081
type __d; \
8182
bfdev_overflow_check_sub(__a, __b, &__d) \
82-
? (type)~0ULL : __d; \
83+
? bfdev_type_min(type) : __d; \
8384
})
8485

8586
#define bfdev_overflow_mul_type(type, a, b) ({ \
8687
type __a = (type)(a); \
8788
type __b = (type)(b); \
8889
type __d; \
8990
bfdev_overflow_check_mul(__a, __b, &__d) \
90-
? (type)~0ULL : __d; \
91+
? bfdev_type_max(type) : __d; \
9192
})
9293

9394
static inline __bfdev_must_check bfdev_bool
@@ -101,7 +102,8 @@ bfdev_overflow_check(bfdev_bool overflow)
101102
* @a: first addend.
102103
* @b: second addend.
103104
*
104-
* Returns (type)~0ULL on failed.
105+
* Returns: calculate @a + @b, any overflow causing the
106+
* return value to be bfdev_type_max(type).
105107
*/
106108
#define bfdev_overflow_add(a, b) \
107109
bfdev_overflow_add_type(typeof(a), a, b)
@@ -111,7 +113,8 @@ bfdev_overflow_check(bfdev_bool overflow)
111113
* @a: minuend; value to subtract from.
112114
* @b: subtrahend; value to subtract from @a.
113115
*
114-
* Returns (type)~0ULL on failed.
116+
* Returns: calculate @a - @b, any overflow causing the
117+
* return value to be bfdev_type_min(type).
115118
*/
116119
#define bfdev_overflow_sub(a, b) \
117120
bfdev_overflow_sub_type(typeof(a), a, b)
@@ -121,7 +124,8 @@ bfdev_overflow_check(bfdev_bool overflow)
121124
* @a: first factor.
122125
* @b: second factor.
123126
*
124-
* Returns (type)~0ULL on failed.
127+
* Returns: calculate @a * @b, any overflow causing the
128+
* return value to be bfdev_type_max(type).
125129
*/
126130
#define bfdev_overflow_mul(a, b) \
127131
bfdev_overflow_mul_type(typeof(a), a, b)

testsuite/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ add_subdirectory(libc)
1515
add_subdirectory(list)
1616
add_subdirectory(memalloc)
1717
add_subdirectory(mpi)
18+
add_subdirectory(overflow)
1819
add_subdirectory(slist)

testsuite/overflow/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# SPDX-License-Identifier: GPL-2.0-or-later
2+
/overflow-selftest

testsuite/overflow/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# SPDX-License-Identifier: GPL-2.0-or-later
2+
#
3+
# Copyright(c) 2025 John Sanpe <sanpeqf@gmail.com>
4+
#
5+
6+
add_executable(overflow-selftest selftest.c)
7+
target_link_libraries(overflow-selftest bfdev testsuite)
8+
add_test(overflow-selftest overflow-selftest)
9+
10+
if(${CMAKE_PROJECT_NAME} STREQUAL "bfdev")
11+
install(TARGETS
12+
overflow-selftest
13+
DESTINATION
14+
${CMAKE_INSTALL_DOCDIR}/testsuite
15+
)
16+
endif()

testsuite/overflow/selftest.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
/*
3+
* Copyright(c) 2023 John Sanpe <sanpeqf@gmail.com>
4+
*/
5+
6+
#define MODULE_NAME "overflow-simple"
7+
#define bfdev_log_fmt(fmt) MODULE_NAME ": " fmt
8+
9+
#include <stddef.h>
10+
#include <limits.h>
11+
#include <stdbool.h>
12+
#include <bfdev/log.h>
13+
#include <bfdev/overflow.h>
14+
#include <testsuite.h>
15+
16+
#define TEST(calculate, limit) ({ \
17+
bool cond; \
18+
cond = bfdev_overflow_##calculate((limit), 1) == (limit); \
19+
if (!cond) \
20+
failed = true; \
21+
cond ? "okay" : "failed"; \
22+
})
23+
24+
TESTSUITE(
25+
"overflow:selftest", NULL, NULL,
26+
"overflow selftest"
27+
) {
28+
bool failed;
29+
30+
failed = false;
31+
bfdev_log_info("add char: %s\n", TEST(add, (signed char)SCHAR_MAX));
32+
bfdev_log_info("add short: %s\n", TEST(add, (signed short)SHRT_MAX));
33+
bfdev_log_info("add int: %s\n", TEST(add, (signed int)INT_MAX));
34+
bfdev_log_info("add long: %s\n", TEST(add, (signed long)LONG_MAX));
35+
bfdev_log_info("add long long: %s\n", TEST(add, (signed long long)LLONG_MAX));
36+
37+
bfdev_log_info("add unsigned char: %s\n", TEST(add, (unsigned char)UCHAR_MAX));
38+
bfdev_log_info("add unsigned short: %s\n", TEST(add, (unsigned short)USHRT_MAX));
39+
bfdev_log_info("add unsigned int: %s\n", TEST(add, (unsigned int)UINT_MAX));
40+
bfdev_log_info("add unsigned long: %s\n", TEST(add, (unsigned long)ULONG_MAX));
41+
bfdev_log_info("add unsigned long long: %s\n", TEST(add, (unsigned long long)ULLONG_MAX));
42+
43+
bfdev_log_info("sub char: %s\n", TEST(sub, (signed char)SCHAR_MIN));
44+
bfdev_log_info("sub short: %s\n", TEST(sub, (signed short)SHRT_MIN));
45+
bfdev_log_info("sub int: %s\n", TEST(sub, (signed int)INT_MIN));
46+
bfdev_log_info("sub long: %s\n", TEST(sub, (signed long)LONG_MIN));
47+
bfdev_log_info("sub long long: %s\n", TEST(sub, (signed long long)LLONG_MIN));
48+
49+
bfdev_log_info("sub unsigned char: %s\n", TEST(sub, (unsigned char)0));
50+
bfdev_log_info("sub unsigned short: %s\n", TEST(sub, (unsigned short)0));
51+
bfdev_log_info("sub unsigned int: %s\n", TEST(sub, (unsigned int)0));
52+
bfdev_log_info("sub unsigned long: %s\n", TEST(sub, (unsigned long)0));
53+
bfdev_log_info("sub unsigned long long: %s\n", TEST(sub, (unsigned long long)0));
54+
55+
if (failed)
56+
return -BFDEV_EFAULT;
57+
58+
return -BFDEV_ENOERR;
59+
}

0 commit comments

Comments
 (0)