]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
lib:util add pointer overflow checks
authorGary Lockyer <gary@catalyst.net.nz>
Tue, 26 May 2026 23:00:30 +0000 (11:00 +1200)
committerStefan Metzmacher <metze@samba.org>
Thu, 28 May 2026 17:39:48 +0000 (17:39 +0000)
The wrapping of pointer arithmetic is undefined behaviour.  Clang from version
20 onwards will treat checks like:
   ptr + offset < ptr
As always evaluating to true.

This commit adds the macros:
   offset_outside_range
   ptr_overflow

BUG: https://bugzilla.samba.org/show_bug.cgi?id=16092

Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
lib/util/overflow.h [new file with mode: 0644]
lib/util/tests/test_overflow.c [new file with mode: 0644]
lib/util/wscript_build

diff --git a/lib/util/overflow.h b/lib/util/overflow.h
new file mode 100644 (file)
index 0000000..ec9ac17
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Samba utility functions
+ *
+ * Copyright (C) Gary Lockyer 2026
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LIB_UTIL_OVERFLOW_H__
+#define __LIB_UTIL_OVERFLOW_H__
+
+#include <stdint.h>
+/**
+* Will adding offset to base pointer, result in a pointer that points
+* past end, or overflow
+*
+* @param base   The pointer to the start of the range
+* @param end    The pointer to the end of the range
+* @param offset The offset being added to base
+*
+* @return True  resulting pointer is between base and end
+*         False resulting pointer is after end
+*/
+#define offset_outside_range(base, end, offset) \
+       (((end) - (base)) < (offset))
+
+/**
+* Will adding offset to base pointer, result in overflow.
+* Pointer arithmetic overflow is undefined behaviour and some compilers
+* (i.e. Clang from version 20) will treat an overflow check like the following:
+*    (ptr + offset) < ptr
+* as always evaluating to false
+*
+* @param ptr    The pointer to check
+* @param offset The offset being added to ptr
+* @param type   Type being pointed to by pointer
+*               needed to cast INTPTR_MAX to the correct type
+*
+* @return True  pointer would over flow
+*         False pointer would not overflow
+*/
+#define ptr_overflow(ptr, offset, type) \
+       offset_outside_range((ptr), ((type*)INTPTR_MAX), (offset))
+
+#endif
diff --git a/lib/util/tests/test_overflow.c b/lib/util/tests/test_overflow.c
new file mode 100644 (file)
index 0000000..437374d
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * cmocka unit tests for the overflow macros
+ *
+ *  Copyright (C) Gary Lockyer 2026 <gary@catalyst.net.nz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ * from cmocka.c:
+ * These headers or their equivalents should be included prior to
+ * including
+ * this header file.
+ *
+ * #include <stdarg.h>
+ * #include <stddef.h>
+ * #include <setjmp.h>
+ *
+ * This allows test applications to use custom definitions of C standard
+ * library functions and types.
+ *
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+
+#include "lib/util/overflow.h"
+
+static void test_ptr_overflow_true(void **state)
+{
+       char *ptr = (char *)INTPTR_MAX;
+       assert_true(ptr_overflow(ptr, 1, char));
+}
+
+static void test_ptr_overflow_false(void **state)
+{
+       char *ptr = (char *)(INTPTR_MAX- 1);
+       assert_false(ptr_overflow(ptr, 1, char));
+}
+
+static void test_outside_range_false(void **state)
+{
+       char base[] = "1234";
+       char *end  = base + 5;
+       assert_false(offset_outside_range(base, end, 5));
+}
+
+static void test_outside_range_true(void **state)
+{
+       char base[] = "1234";
+       char *end  = base + 5;
+       assert_true(offset_outside_range(base, end, 6));
+}
+
+int main(int argc, const char **argv)
+{
+       const struct CMUnitTest tests[] = {
+               cmocka_unit_test( test_ptr_overflow_true),
+               cmocka_unit_test( test_ptr_overflow_false),
+               cmocka_unit_test( test_outside_range_false),
+               cmocka_unit_test( test_outside_range_true),
+       };
+
+       cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
+
+       return cmocka_run_group_tests(tests, NULL, NULL);
+
+}
index 9b43d05960b6c402cdc7f133c77d55e9485aa88b..549a58701cb4d237fc90d999976f93c54b88e44c 100644 (file)
@@ -405,6 +405,12 @@ else:
                      local_include=False,
                      for_selftest=True)
 
+    bld.SAMBA_BINARY('test_overflow',
+                     source='tests/test_overflow.c',
+                     deps='cmocka',
+                     local_include=False,
+                     for_selftest=True)
+
     bld.SAMBA_BINARY('test_s4_logging',
                      source='tests/test_logging.c',
                      deps=' '.join(['CMDLINE_S4',