]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Enforcing certain data structure explicit paddings.
authorMaria Matejka <mq@ucw.cz>
Thu, 14 Apr 2022 14:51:18 +0000 (16:51 +0200)
committerMaria Matejka <mq@ucw.cz>
Wed, 4 May 2022 13:37:41 +0000 (15:37 +0200)
Implicit paddings have undefined values in C. We want the eattr blocks
to be comparable by memcmp and eattrs settable directly by structrure
literals. This check ensures that all paddings in eattr and bval are
explicit and therefore zeroed in all literals.

aclocal.m4
configure.ac
lib/Makefile
lib/birdlib.h
lib/route.h
lib/type.h
lib/type_test.c [new file with mode: 0644]
nest/Makefile
nest/bird.h

index 1613d6803007d4cb9474672b2181be40294e3339..58c48791724f30218ecbe14faf46bc245cfc6bd0 100644 (file)
@@ -1,6 +1,32 @@
 dnl ** Additional Autoconf tests for BIRD configure script
 dnl ** (c) 1999 Martin Mares <mj@ucw.cz>
 
+AC_DEFUN([BIRD_CHECK_POINTER_ALIGNMENT],
+[
+  AC_CACHE_CHECK(
+    [how pointers are aligned],
+    [bird_cv_pointer_alignment],
+    AC_COMPILE_IFELSE([
+      AC_LANG_PROGRAM(
+       [
+         _Static_assert(_Alignof(void *) == 8, "bad");
+       ], []
+      )
+    ],
+    [bird_cv_pointer_alignment=8],
+    AC_COMPILE_IFELSE([
+      AC_LANG_PROGRAM(
+       [
+         _Static_assert(_Alignof(void *) == 4, "bad");
+       ], []
+      )
+    ],
+    [bird_cv_pointer_alignment=4],
+    [bird_cv_pointer_alignment=unknown]
+    ))
+  )
+])
+
 AC_DEFUN([BIRD_CHECK_THREAD_LOCAL],
 [
   AC_CACHE_CHECK(
index 64181d2972cad2b6dbe6e997b5562639f5487d86..321bed95a74ec8aa759d8770d447c0602a34dde6 100644 (file)
@@ -360,6 +360,13 @@ AC_C_BIGENDIAN(
   [AC_MSG_ERROR([Cannot determine CPU endianity.])]
 )
 
+BIRD_CHECK_POINTER_ALIGNMENT
+if test "$bird_cv_pointer_alignment" = "unknown" ; then
+  AC_MSG_ERROR([Couldn't determine pointer alignment])
+else
+  AC_DEFINE_UNQUOTED([CPU_POINTER_ALIGNMENT], [$bird_cv_pointer_alignment], [Pointer alignment for macro usage])
+fi
+
 BIRD_CHECK_ANDROID_GLOB
 if test "$bird_cv_lib_glob" = no ; then
   AC_MSG_ERROR([glob.h not found.])
index 853e0a22d8aec78a11e72930cce4fdf4f9976b3c..15f757d9d57da8e5fdc7e015464da65eac8c04cf 100644 (file)
@@ -2,6 +2,6 @@ src := a-path.c a-set.c bitmap.c bitops.c blake2s.c blake2b.c checksum.c event.c
 obj := $(src-o-files)
 $(all-daemon)
 
-tests_src := a-set_test.c a-path_test.c bitmap_test.c heap_test.c buffer_test.c event_test.c flowspec_test.c bitops_test.c patmatch_test.c fletcher16_test.c slist_test.c checksum_test.c lists_test.c mac_test.c ip_test.c hash_test.c printf_test.c slab_test.c
+tests_src := a-set_test.c a-path_test.c bitmap_test.c heap_test.c buffer_test.c event_test.c flowspec_test.c bitops_test.c patmatch_test.c fletcher16_test.c slist_test.c checksum_test.c lists_test.c mac_test.c ip_test.c hash_test.c printf_test.c slab_test.c type_test.c
 tests_targets := $(tests_targets) $(tests-target-files)
 tests_objs := $(tests_objs) $(src-o-files)
index 6f0bab963348c8a2775fefcd006bbed85bbb37f3..9b6e4a1691a33790ceefbcfcf31f1ecc7f3390cc 100644 (file)
@@ -9,18 +9,30 @@
 #ifndef _BIRD_BIRDLIB_H_
 #define _BIRD_BIRDLIB_H_
 
+#include "sysdep/config.h"
 #include "lib/alloca.h"
 
 /* Ugly structure offset handling macros */
 
-struct align_probe { char x; long int y; };
-
 #define OFFSETOF(s, i) ((size_t) &((s *)0)->i)
 #define SKIP_BACK(s, i, p) ((s *)((char *)p - OFFSETOF(s, i)))
 #define BIRD_ALIGN(s, a) (((s)+a-1)&~(a-1))
-#define CPU_STRUCT_ALIGN (sizeof(struct align_probe))
+#define CPU_STRUCT_ALIGN  (MAX_(_Alignof(void*), _Alignof(u64)))
 #define BIRD_CPU_ALIGN(s) BIRD_ALIGN((s), CPU_STRUCT_ALIGN)
 
+/* Structure item alignment macros */
+
+#define PADDING_NAME(id)       _padding_##id
+#define PADDING_(id, sz)       u8 PADDING_NAME(id)[sz]
+
+#if CPU_POINTER_ALIGNMENT == 4
+#define PADDING(id, n32, n64)  PADDING_(id, n32)
+#elif CPU_POINTER_ALIGNMENT == 8
+#define PADDING(id, n32, n64)  PADDING_(id, n64)
+#else
+#error "Strange CPU pointer alignment: " CPU_POINTER_ALIGNMENT
+#endif
+
 /* Utility macros */
 
 #define MIN_(a,b) (((a)<(b))?(a):(b))
index 431da4d80d804eca0db394517aad5d7b6118176d..ba7bab61e6de7c869e905b46756d0803a7f11917 100644 (file)
@@ -144,6 +144,8 @@ typedef struct eattr {
   byte fresh:1;                                /* An uncached attribute (e.g. modified in export filter) */
   byte undef:1;                                /* Explicitly undefined */
 
+  PADDING(unused, 0, 4);
+
   union bval u;
 } eattr;
 
index 6d19a2501d9de839a7f61c061e71eae6789c210e..e43389f38d8d81c96d70a969aa82ce40b76da98b 100644 (file)
 #include "lib/attrs.h"
 
 union bval {
-#define BVAL_ITEMS     \
-  u32 data;                    /* Integer type inherited from eattrs */                \
-  u32 i;                       /* Integer type inherited from filters */               \
+#define BVAL_ITEMS                                                                     \
+  struct {                                                                             \
+    u32 data;                  /* Integer type inherited from eattrs */                \
+    PADDING(data, 0, 4);       /* Must be padded on 64-bits */                         \
+  };                                                                                   \
+  struct {                                                                             \
+    u32 i;                     /* Integer type inherited from filters */               \
+    PADDING(i, 0, 4);          /* Must be padded on 64-bits */                         \
+  };                                                                                   \
   const struct adata *ptr;     /* Generic attribute data inherited from eattrs */      \
   const struct adata *ad;      /* Generic attribute data inherited from filters */     \
 
diff --git a/lib/type_test.c b/lib/type_test.c
new file mode 100644 (file)
index 0000000..20e7630
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ *     BIRD Library -- Data Type Alignment Tests
+ *
+ *     (c) 2022 Maria Matejka <mq@jmq.cz>
+ *
+ *     Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include "test/birdtest.h"
+#include "lib/type.h"
+#include "lib/route.h"
+
+#define CHECK_ONE(val) \
+  for (uint i=0; i<sizeof(val); i++) \
+    bt_assert(((const u8 *) &val)[i] == (u8) ~0);
+
+#define SET_PADDING(val, name) \
+  for (uint i=0; i<sizeof(val.PADDING_NAME(name)); i++) \
+    val.PADDING_NAME(name)[i] = ~0;
+
+
+static int
+t_bval(void)
+{
+  union bval v;
+
+  memset(&v, 0, sizeof(v));
+  v.data = ~0;
+  SET_PADDING(v, data);
+  CHECK_ONE(v);
+
+  memset(&v, 0, sizeof(v));
+  v.i = ~0;
+  SET_PADDING(v, i);
+  CHECK_ONE(v);
+
+  memset(&v, 0, sizeof(v));
+  v.ptr = (void *) ~0;
+  CHECK_ONE(v);
+
+  memset(&v, 0, sizeof(v));
+  v.ad = (void *) ~0;
+  CHECK_ONE(v);
+
+  return 1;
+}
+
+static int
+t_eattr(void)
+{
+  struct eattr e;
+  memset(&e, 0, sizeof(e));
+
+  e.id = ~0;
+  e.flags = ~0;
+  e.type = ~0;
+  e.originated = ~0;
+  e.fresh = ~0;
+  e.undef = ~0;
+  memset(&e.u, ~0, sizeof(e.u));  /* Assumes t_bval passed */
+
+  SET_PADDING(e, unused);
+
+  CHECK_ONE(e);
+
+  return 1;
+}
+
+
+int main(int argc, char *argv[])
+{
+  bt_init(argc, argv);
+
+  bt_test_suite(t_bval,          "Structure alignment test: bval");
+  bt_test_suite(t_eattr,  "Structure alignment test: eattr");
+
+  return bt_exit_value();
+}
index c07655304ac0505db14d75135d9e4b4b81855e35..0350c3b65e1558aa8f2ad519ed4146ba237dbd21 100644 (file)
@@ -6,7 +6,7 @@ $(call proto-build,dev_build)
 
 $(proto-build-c): $(lastword $(MAKEFILE_LIST))
        $(E)echo GEN $@
-       $(Q)echo "$(patsubst %,void %(void); ,$(PROTO_BUILD)) void protos_build_gen(void) { $(patsubst %,  %(); ,$(PROTO_BUILD))}" > $@
+       $(Q)echo "#include \"lib/birdlib.h\"\n$(patsubst %,void %(void);\n,$(PROTO_BUILD)) void protos_build_gen(void) { $(patsubst %,  %();\n,$(PROTO_BUILD))}" > $@
 
 tests_src :=
 tests_targets := $(tests_targets) $(tests-target-files)
index 55712abe82450c0d050846168f6f6a7a144bc976..931974a0e8f84a8bfe6422b1526656d871053f42 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _BIRD_BIRD_H_
 #define _BIRD_BIRD_H_
 
-#include "sysdep/config.h"
 #include "lib/birdlib.h"
 #include "lib/ip.h"
 #include "lib/net.h"