From 8e6c2fecfd633171250b7f09ef4aa0328bd5b698 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 27 Sep 2018 09:09:50 +0930 Subject: [PATCH 1/1] structeq: fix case where we mark padding as unknown. And change semantics: a negative number means "up to this much padding". Signed-off-by: Rusty Russell --- ccan/structeq/structeq.h | 9 +++-- .../test/compile_fail-expect-any-padding.c | 5 ++- ...compile_fail-unexpected-negative-padding.c | 20 ++++++++++ ccan/structeq/test/run-with-unknown-padding.c | 39 +++++++++++++++++++ 4 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 ccan/structeq/test/compile_fail-unexpected-negative-padding.c create mode 100644 ccan/structeq/test/run-with-unknown-padding.c diff --git a/ccan/structeq/structeq.h b/ccan/structeq/structeq.h index 6b90754c..81799539 100644 --- a/ccan/structeq/structeq.h +++ b/ccan/structeq/structeq.h @@ -9,14 +9,15 @@ /** * STRUCTEQ_DEF - define an ..._eq function to compare two structures. * @sname: name of the structure, and function (_eq) to define. - * @padbytes: number of bytes of expected padding, or -1 if unknown. + * @padbytes: number of bytes of expected padding, or negative "max". * @...: name of every member of the structure. * * This generates a single memcmp() call in the common case where the * structure contains no padding. Since it can't tell the difference between * padding and a missing member, @padbytes can be used to assert that - * there isn't any, or how many we expect. -1 means "expect some", since - * it can be platform dependent. + * there isn't any, or how many we expect. A negative number means + * "up to or equal to that amount of padding", as padding can be + * platform dependent. */ #define STRUCTEQ_DEF(sname, padbytes, ...) \ static inline bool CPPMAGIC_GLUE2(sname, _eq)(const struct sname *_a, \ @@ -25,7 +26,7 @@ static inline bool CPPMAGIC_GLUE2(sname, _eq)(const struct sname *_a, \ BUILD_ASSERT(((padbytes) < 0 && \ CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, \ __VA_ARGS__)) \ - > sizeof(*_a)) \ + - (padbytes) >= sizeof(*_a)) \ || CPPMAGIC_JOIN(+, CPPMAGIC_MAP(STRUCTEQ_MEMBER_SIZE_, \ __VA_ARGS__)) \ + (padbytes) == sizeof(*_a)); \ diff --git a/ccan/structeq/test/compile_fail-expect-any-padding.c b/ccan/structeq/test/compile_fail-expect-any-padding.c index 321aef3a..182c8607 100644 --- a/ccan/structeq/test/compile_fail-expect-any-padding.c +++ b/ccan/structeq/test/compile_fail-expect-any-padding.c @@ -2,11 +2,12 @@ struct mydata { int start, end; + int pad; }; #ifdef FAIL -#define PADDING -1 +#define PADDING -1 /* We have more than 1 byte padding */ #else -#define PADDING 0 +#define PADDING sizeof(int) #endif STRUCTEQ_DEF(mydata, PADDING, start, end); diff --git a/ccan/structeq/test/compile_fail-unexpected-negative-padding.c b/ccan/structeq/test/compile_fail-unexpected-negative-padding.c new file mode 100644 index 00000000..2c63b23d --- /dev/null +++ b/ccan/structeq/test/compile_fail-unexpected-negative-padding.c @@ -0,0 +1,20 @@ +#include + +struct mydata { + int start, end; + int pad; +}; +#ifdef FAIL +#define PADDING -1 +#else +#define PADDING -(int)sizeof(int) +#endif + +STRUCTEQ_DEF(mydata, PADDING, start, end); + +int main(void) +{ + struct mydata a = { 0, 100 }; + + return mydata_eq(&a, &a); +} diff --git a/ccan/structeq/test/run-with-unknown-padding.c b/ccan/structeq/test/run-with-unknown-padding.c new file mode 100644 index 00000000..c803e722 --- /dev/null +++ b/ccan/structeq/test/run-with-unknown-padding.c @@ -0,0 +1,39 @@ +#include +#include + +/* In theory, this could be generated without padding, if alignof(int) were 0, + * and test would fail. Call me when that happens. */ +struct mydata { + char start; + int end; +}; + +STRUCTEQ_DEF(mydata, -3, start, end); + +struct mydata2 { + char start; + int end; +}; + +STRUCTEQ_DEF(mydata2, -4, start, end); + +int main(void) +{ + struct mydata a, b; + + /* This is how many tests you plan to run */ + plan_tests(3); + + a.start = 0; + a.end = 100; + ok1(mydata_eq(&a, &a)); + + b = a; + ok1(mydata_eq(&a, &b)); + + b.end++; + ok1(!mydata_eq(&a, &b)); + + /* This exits depending on whether all tests passed */ + return exit_status(); +} -- 2.39.2