@@ -47,21 +47,26 @@ static bool stackinit_range_contains(char *haystack_start, size_t haystack_size,
4747#define DO_NOTHING_TYPE_SCALAR (var_type ) var_type
4848#define DO_NOTHING_TYPE_STRING (var_type ) void
4949#define DO_NOTHING_TYPE_STRUCT (var_type ) void
50+ #define DO_NOTHING_TYPE_UNION (var_type ) void
5051
5152#define DO_NOTHING_RETURN_SCALAR (ptr ) *(ptr)
5253#define DO_NOTHING_RETURN_STRING (ptr ) /**/
5354#define DO_NOTHING_RETURN_STRUCT (ptr ) /**/
55+ #define DO_NOTHING_RETURN_UNION (ptr ) /**/
5456
5557#define DO_NOTHING_CALL_SCALAR (var , name ) \
5658 (var) = do_nothing_ ## name(&(var))
5759#define DO_NOTHING_CALL_STRING (var , name ) \
5860 do_nothing_ ## name(var)
5961#define DO_NOTHING_CALL_STRUCT (var , name ) \
6062 do_nothing_ ## name(&(var))
63+ #define DO_NOTHING_CALL_UNION (var , name ) \
64+ do_nothing_ ## name(&(var))
6165
6266#define FETCH_ARG_SCALAR (var ) &var
6367#define FETCH_ARG_STRING (var ) var
6468#define FETCH_ARG_STRUCT (var ) &var
69+ #define FETCH_ARG_UNION (var ) &var
6570
6671/*
6772 * On m68k, if the leaf function test variable is longer than 8 bytes,
@@ -77,6 +82,7 @@ static bool stackinit_range_contains(char *haystack_start, size_t haystack_size,
7782#define INIT_CLONE_SCALAR /**/
7883#define INIT_CLONE_STRING [FILL_SIZE_STRING]
7984#define INIT_CLONE_STRUCT /**/
85+ #define INIT_CLONE_UNION /**/
8086
8187#define ZERO_CLONE_SCALAR (zero ) memset(&(zero), 0x00, sizeof(zero))
8288#define ZERO_CLONE_STRING (zero ) memset(&(zero), 0x00, sizeof(zero))
@@ -92,6 +98,7 @@ static bool stackinit_range_contains(char *haystack_start, size_t haystack_size,
9298 zero.three = 0; \
9399 zero.four = 0; \
94100 } while (0)
101+ #define ZERO_CLONE_UNION (zero ) ZERO_CLONE_STRUCT(zero)
95102
96103#define INIT_SCALAR_none (var_type ) /**/
97104#define INIT_SCALAR_zero (var_type ) = 0
@@ -147,6 +154,34 @@ static bool stackinit_range_contains(char *haystack_start, size_t haystack_size,
147154#define INIT_STRUCT_assigned_copy (var_type ) \
148155 ; var = *(arg)
149156
157+ /* Union initialization is the same as structs. */
158+ #define INIT_UNION_none (var_type ) INIT_STRUCT_none(var_type)
159+ #define INIT_UNION_zero (var_type ) INIT_STRUCT_zero(var_type)
160+ #define INIT_UNION_old_zero (var_type ) INIT_STRUCT_old_zero(var_type)
161+
162+ #define INIT_UNION_static_partial (var_type ) \
163+ INIT_STRUCT_static_partial(var_type)
164+ #define INIT_UNION_static_all (var_type ) \
165+ INIT_STRUCT_static_all(var_type)
166+ #define INIT_UNION_dynamic_partial (var_type ) \
167+ INIT_STRUCT_dynamic_partial(var_type)
168+ #define INIT_UNION_dynamic_all (var_type ) \
169+ INIT_STRUCT_dynamic_all(var_type)
170+ #define INIT_UNION_runtime_partial (var_type ) \
171+ INIT_STRUCT_runtime_partial(var_type)
172+ #define INIT_UNION_runtime_all (var_type ) \
173+ INIT_STRUCT_runtime_all(var_type)
174+ #define INIT_UNION_assigned_static_partial (var_type ) \
175+ INIT_STRUCT_assigned_static_partial(var_type)
176+ #define INIT_UNION_assigned_static_all (var_type ) \
177+ INIT_STRUCT_assigned_static_all(var_type)
178+ #define INIT_UNION_assigned_dynamic_partial (var_type ) \
179+ INIT_STRUCT_assigned_dynamic_partial(var_type)
180+ #define INIT_UNION_assigned_dynamic_all (var_type ) \
181+ INIT_STRUCT_assigned_dynamic_all(var_type)
182+ #define INIT_UNION_assigned_copy (var_type ) \
183+ INIT_STRUCT_assigned_copy(var_type)
184+
150185/*
151186 * @name: unique string name for the test
152187 * @var_type: type to be tested for zeroing initialization
@@ -295,6 +330,33 @@ struct test_user {
295330 unsigned long four ;
296331};
297332
333+ /* No padding: all members are the same size. */
334+ union test_same_sizes {
335+ unsigned long one ;
336+ unsigned long two ;
337+ unsigned long three ;
338+ unsigned long four ;
339+ };
340+
341+ /* Mismatched sizes, with one and two being small */
342+ union test_small_start {
343+ char one :1 ;
344+ char two ;
345+ short three ;
346+ unsigned long four ;
347+ struct big_struct {
348+ unsigned long array [8 ];
349+ } big ;
350+ };
351+
352+ /* Mismatched sizes, with one and two being small */
353+ union test_small_end {
354+ short one ;
355+ unsigned long two ;
356+ char three :1 ;
357+ char four ;
358+ };
359+
298360#define ALWAYS_PASS WANT_SUCCESS
299361#define ALWAYS_FAIL XFAIL
300362
@@ -333,6 +395,11 @@ struct test_user {
333395 struct test_ ## name, STRUCT, init, \
334396 xfail)
335397
398+ #define DEFINE_UNION_TEST (name , init , xfail ) \
399+ DEFINE_TEST(name ## _ ## init, \
400+ union test_ ## name, STRUCT, init, \
401+ xfail)
402+
336403#define DEFINE_STRUCT_TESTS (init , xfail ) \
337404 DEFINE_STRUCT_TEST(small_hole, init, xfail); \
338405 DEFINE_STRUCT_TEST(big_hole, init, xfail); \
@@ -344,17 +411,35 @@ struct test_user {
344411 xfail); \
345412 DEFINE_STRUCT_TESTS(base ## _ ## all, xfail)
346413
414+ #define DEFINE_UNION_INITIALIZER_TESTS (base , xfail ) \
415+ DEFINE_UNION_TESTS(base ## _ ## partial, \
416+ xfail); \
417+ DEFINE_UNION_TESTS(base ## _ ## all, xfail)
418+
419+ #define DEFINE_UNION_TESTS (init , xfail ) \
420+ DEFINE_UNION_TEST(same_sizes, init, xfail); \
421+ DEFINE_UNION_TEST(small_start, init, xfail); \
422+ DEFINE_UNION_TEST(small_end, init, xfail);
423+
347424/* These should be fully initialized all the time! */
348425DEFINE_SCALAR_TESTS (zero , ALWAYS_PASS );
349426DEFINE_STRUCT_TESTS (zero , ALWAYS_PASS );
350427DEFINE_STRUCT_TESTS (old_zero , ALWAYS_PASS );
428+ DEFINE_UNION_TESTS (zero , ALWAYS_PASS );
429+ DEFINE_UNION_TESTS (old_zero , ALWAYS_PASS );
351430/* Struct initializers: padding may be left uninitialized. */
352431DEFINE_STRUCT_INITIALIZER_TESTS (static , STRONG_PASS );
353432DEFINE_STRUCT_INITIALIZER_TESTS (dynamic , STRONG_PASS );
354433DEFINE_STRUCT_INITIALIZER_TESTS (runtime , STRONG_PASS );
355434DEFINE_STRUCT_INITIALIZER_TESTS (assigned_static , STRONG_PASS );
356435DEFINE_STRUCT_INITIALIZER_TESTS (assigned_dynamic , STRONG_PASS );
357436DEFINE_STRUCT_TESTS (assigned_copy , ALWAYS_FAIL );
437+ DEFINE_UNION_INITIALIZER_TESTS (static , STRONG_PASS );
438+ DEFINE_UNION_INITIALIZER_TESTS (dynamic , STRONG_PASS );
439+ DEFINE_UNION_INITIALIZER_TESTS (runtime , STRONG_PASS );
440+ DEFINE_UNION_INITIALIZER_TESTS (assigned_static , STRONG_PASS );
441+ DEFINE_UNION_INITIALIZER_TESTS (assigned_dynamic , STRONG_PASS );
442+ DEFINE_UNION_TESTS (assigned_copy , ALWAYS_FAIL );
358443/* No initialization without compiler instrumentation. */
359444DEFINE_SCALAR_TESTS (none , STRONG_PASS );
360445DEFINE_STRUCT_TESTS (none , BYREF_PASS );
@@ -438,14 +523,23 @@ DEFINE_TEST_DRIVER(switch_2_none, uint64_t, SCALAR, ALWAYS_FAIL);
438523 KUNIT_CASE(test_trailing_hole_ ## init),\
439524 KUNIT_CASE(test_packed_ ## init) \
440525
526+ #define KUNIT_test_unions (init ) \
527+ KUNIT_CASE(test_same_sizes_ ## init), \
528+ KUNIT_CASE(test_small_start_ ## init), \
529+ KUNIT_CASE(test_small_end_ ## init) \
530+
441531static struct kunit_case stackinit_test_cases [] = {
442532 /* These are explicitly initialized and should always pass. */
443533 KUNIT_test_scalars (zero ),
444534 KUNIT_test_structs (zero ),
445535 KUNIT_test_structs (old_zero ),
536+ KUNIT_test_unions (zero ),
537+ KUNIT_test_unions (old_zero ),
446538 /* Padding here appears to be accidentally always initialized? */
447539 KUNIT_test_structs (dynamic_partial ),
448540 KUNIT_test_structs (assigned_dynamic_partial ),
541+ KUNIT_test_unions (dynamic_partial ),
542+ KUNIT_test_unions (assigned_dynamic_partial ),
449543 /* Padding initialization depends on compiler behaviors. */
450544 KUNIT_test_structs (static_partial ),
451545 KUNIT_test_structs (static_all ),
@@ -455,8 +549,17 @@ static struct kunit_case stackinit_test_cases[] = {
455549 KUNIT_test_structs (assigned_static_partial ),
456550 KUNIT_test_structs (assigned_static_all ),
457551 KUNIT_test_structs (assigned_dynamic_all ),
552+ KUNIT_test_unions (static_partial ),
553+ KUNIT_test_unions (static_all ),
554+ KUNIT_test_unions (dynamic_all ),
555+ KUNIT_test_unions (runtime_partial ),
556+ KUNIT_test_unions (runtime_all ),
557+ KUNIT_test_unions (assigned_static_partial ),
558+ KUNIT_test_unions (assigned_static_all ),
559+ KUNIT_test_unions (assigned_dynamic_all ),
458560 /* Everything fails this since it effectively performs a memcpy(). */
459561 KUNIT_test_structs (assigned_copy ),
562+ KUNIT_test_unions (assigned_copy ),
460563 /* STRUCTLEAK_BYREF_ALL should cover everything from here down. */
461564 KUNIT_test_scalars (none ),
462565 KUNIT_CASE (test_switch_1_none ),
0 commit comments