@@ -95,6 +95,10 @@ static bool range_contains(char *haystack_start, size_t haystack_size,
9595 return false;
9696}
9797
98+ /* Whether the test is expected to fail. */
99+ #define WANT_SUCCESS 0
100+ #define XFAIL 1
101+
98102#define DO_NOTHING_TYPE_SCALAR (var_type ) var_type
99103#define DO_NOTHING_TYPE_STRING (var_type ) void
100104#define DO_NOTHING_TYPE_STRUCT (var_type ) void
@@ -120,34 +124,74 @@ static bool range_contains(char *haystack_start, size_t haystack_size,
120124#define INIT_CLONE_STRING [FILL_SIZE_STRING]
121125#define INIT_CLONE_STRUCT /**/
122126
123- #define INIT_SCALAR_none /**/
124- #define INIT_SCALAR_zero = 0
127+ #define ZERO_CLONE_SCALAR (zero ) memset(&(zero), 0x00, sizeof(zero))
128+ #define ZERO_CLONE_STRING (zero ) memset(&(zero), 0x00, sizeof(zero))
129+ /*
130+ * For the struct, intentionally poison padding to see if it gets
131+ * copied out in direct assignments.
132+ * */
133+ #define ZERO_CLONE_STRUCT (zero ) \
134+ do { \
135+ memset(&(zero), 0xFF, sizeof(zero)); \
136+ zero.one = 0; \
137+ zero.two = 0; \
138+ zero.three = 0; \
139+ zero.four = 0; \
140+ } while (0)
141+
142+ #define INIT_SCALAR_none (var_type ) /**/
143+ #define INIT_SCALAR_zero (var_type ) = 0
125144
126- #define INIT_STRING_none [FILL_SIZE_STRING] /**/
127- #define INIT_STRING_zero [FILL_SIZE_STRING] = { }
145+ #define INIT_STRING_none ( var_type ) [FILL_SIZE_STRING] /**/
146+ #define INIT_STRING_zero ( var_type ) [FILL_SIZE_STRING] = { }
128147
129- #define INIT_STRUCT_none /**/
130- #define INIT_STRUCT_zero = { }
131- #define INIT_STRUCT_static_partial = { .two = 0, }
132- #define INIT_STRUCT_static_all = { .one = 0, \
133- .two = 0, \
134- .three = 0, \
135- .four = 0, \
148+ #define INIT_STRUCT_none (var_type ) /**/
149+ #define INIT_STRUCT_zero (var_type ) = { }
150+
151+
152+ #define __static_partial { .two = 0, }
153+ #define __static_all { .one = 0, \
154+ .two = 0, \
155+ .three = 0, \
156+ .four = 0, \
136157 }
137- #define INIT_STRUCT_dynamic_partial = { .two = arg->two, }
138- #define INIT_STRUCT_dynamic_all = { .one = arg->one, \
139- .two = arg->two, \
140- .three = arg->three, \
141- .four = arg->four, \
158+ #define __dynamic_partial { .two = arg->two, }
159+ #define __dynamic_all { .one = arg->one, \
160+ .two = arg->two, \
161+ .three = arg->three, \
162+ .four = arg->four, \
142163 }
143- #define INIT_STRUCT_runtime_partial ; \
144- var.two = 0
145- #define INIT_STRUCT_runtime_all ; \
146- var.one = 0; \
164+ #define __runtime_partial var.two = 0
165+ #define __runtime_all var.one = 0; \
147166 var.two = 0; \
148167 var.three = 0; \
149168 var.four = 0
150169
170+ #define INIT_STRUCT_static_partial (var_type ) \
171+ = __static_partial
172+ #define INIT_STRUCT_static_all (var_type ) \
173+ = __static_all
174+ #define INIT_STRUCT_dynamic_partial (var_type ) \
175+ = __dynamic_partial
176+ #define INIT_STRUCT_dynamic_all (var_type ) \
177+ = __dynamic_all
178+ #define INIT_STRUCT_runtime_partial (var_type ) \
179+ ; __runtime_partial
180+ #define INIT_STRUCT_runtime_all (var_type ) \
181+ ; __runtime_all
182+
183+ #define INIT_STRUCT_assigned_static_partial (var_type ) \
184+ ; var = (var_type)__static_partial
185+ #define INIT_STRUCT_assigned_static_all (var_type ) \
186+ ; var = (var_type)__static_all
187+ #define INIT_STRUCT_assigned_dynamic_partial (var_type ) \
188+ ; var = (var_type)__dynamic_partial
189+ #define INIT_STRUCT_assigned_dynamic_all (var_type ) \
190+ ; var = (var_type)__dynamic_all
191+
192+ #define INIT_STRUCT_assigned_copy (var_type ) \
193+ ; var = *(arg)
194+
151195/*
152196 * @name: unique string name for the test
153197 * @var_type: type to be tested for zeroing initialization
@@ -167,7 +211,7 @@ static noinline __init int test_ ## name (void) \
167211 BUILD_BUG_ON (sizeof (zero ) > MAX_VAR_SIZE ); \
168212 \
169213 /* Fill clone type with zero for per-field init. */ \
170- memset ( & zero , 0x00 , sizeof (zero )); \
214+ ZERO_CLONE_ # # which (zero); \
171215 /* Clear entire check buffer for 0xFF overlap test. */ \
172216 memset (check_buf , 0x00 , sizeof (check_buf )); \
173217 /* Fill stack with 0xFF. */ \
@@ -210,7 +254,7 @@ static noinline __init int test_ ## name (void) \
210254 return (xfail) ? 0 : 1; \
211255 } \
212256}
213- #define DEFINE_TEST (name , var_type , which , init_level ) \
257+ #define DEFINE_TEST (name , var_type , which , init_level , xfail ) \
214258/* no-op to force compiler into ignoring "uninitialized" vars */ \
215259static noinline __init DO_NOTHING_TYPE_ ## which(var_type) \
216260do_nothing_ ## name(var_type *ptr) \
@@ -226,7 +270,8 @@ static noinline __init int leaf_ ## name(unsigned long sp, \
226270 var_type *arg) \
227271{ \
228272 char buf[VAR_BUFFER]; \
229- var_type var INIT_ ## which ## _ ## init_level; \
273+ var_type var \
274+ INIT_ ## which ## _ ## init_level(var_type); \
230275 \
231276 target_start = &var; \
232277 target_size = sizeof(var); \
@@ -252,7 +297,7 @@ static noinline __init int leaf_ ## name(unsigned long sp, \
252297 \
253298 return (int )buf [0 ] | (int )buf [sizeof (buf ) - 1 ]; \
254299} \
255- DEFINE_TEST_DRIVER (name , var_type , which , 0 )
300+ DEFINE_TEST_DRIVER (name , var_type , which , xfail )
256301
257302/* Structure with no padding. */
258303struct test_packed {
@@ -296,42 +341,50 @@ struct test_user {
296341 unsigned long four ;
297342};
298343
299- #define DEFINE_SCALAR_TEST (name , init ) \
300- DEFINE_TEST(name ## _ ## init, name, SCALAR, init)
344+ #define DEFINE_SCALAR_TEST (name , init , xfail ) \
345+ DEFINE_TEST(name ## _ ## init, name, SCALAR, \
346+ init, xfail)
301347
302- #define DEFINE_SCALAR_TESTS (init ) \
303- DEFINE_SCALAR_TEST(u8, init); \
304- DEFINE_SCALAR_TEST(u16, init); \
305- DEFINE_SCALAR_TEST(u32, init); \
306- DEFINE_SCALAR_TEST(u64, init); \
307- DEFINE_TEST(char_array_ ## init, unsigned char, STRING, init)
348+ #define DEFINE_SCALAR_TESTS (init , xfail ) \
349+ DEFINE_SCALAR_TEST(u8, init, xfail); \
350+ DEFINE_SCALAR_TEST(u16, init, xfail); \
351+ DEFINE_SCALAR_TEST(u32, init, xfail); \
352+ DEFINE_SCALAR_TEST(u64, init, xfail); \
353+ DEFINE_TEST(char_array_ ## init, unsigned char, \
354+ STRING, init, xfail)
308355
309- #define DEFINE_STRUCT_TEST (name , init ) \
356+ #define DEFINE_STRUCT_TEST (name , init , xfail ) \
310357 DEFINE_TEST(name ## _ ## init, \
311- struct test_ ## name, STRUCT, init)
358+ struct test_ ## name, STRUCT, init, \
359+ xfail)
360+
361+ #define DEFINE_STRUCT_TESTS (init , xfail ) \
362+ DEFINE_STRUCT_TEST(small_hole, init, xfail); \
363+ DEFINE_STRUCT_TEST(big_hole, init, xfail); \
364+ DEFINE_STRUCT_TEST(trailing_hole, init, xfail); \
365+ DEFINE_STRUCT_TEST(packed, init, xfail)
312366
313- #define DEFINE_STRUCT_TESTS ( init ) \
314- DEFINE_STRUCT_TEST(small_hole, init); \
315- DEFINE_STRUCT_TEST(big_hole, init ); \
316- DEFINE_STRUCT_TEST(trailing_hole, init); \
317- DEFINE_STRUCT_TEST(packed, init )
367+ #define DEFINE_STRUCT_INITIALIZER_TESTS ( base ) \
368+ DEFINE_STRUCT_TESTS(base ## _ ## partial, \
369+ WANT_SUCCESS ); \
370+ DEFINE_STRUCT_TESTS(base ## _ ## all, \
371+ WANT_SUCCESS )
318372
319373/* These should be fully initialized all the time! */
320- DEFINE_SCALAR_TESTS (zero );
321- DEFINE_STRUCT_TESTS (zero );
322- /* Static initialization: padding may be left uninitialized. */
323- DEFINE_STRUCT_TESTS (static_partial );
324- DEFINE_STRUCT_TESTS (static_all );
325- /* Dynamic initialization: padding may be left uninitialized. */
326- DEFINE_STRUCT_TESTS (dynamic_partial );
327- DEFINE_STRUCT_TESTS (dynamic_all );
328- /* Runtime initialization: padding may be left uninitialized. */
329- DEFINE_STRUCT_TESTS (runtime_partial );
330- DEFINE_STRUCT_TESTS (runtime_all );
374+ DEFINE_SCALAR_TESTS (zero , WANT_SUCCESS );
375+ DEFINE_STRUCT_TESTS (zero , WANT_SUCCESS );
376+ /* Struct initializers: padding may be left uninitialized. */
377+ DEFINE_STRUCT_INITIALIZER_TESTS (static );
378+ DEFINE_STRUCT_INITIALIZER_TESTS (dynamic );
379+ DEFINE_STRUCT_INITIALIZER_TESTS (runtime );
380+ DEFINE_STRUCT_INITIALIZER_TESTS (assigned_static );
381+ DEFINE_STRUCT_INITIALIZER_TESTS (assigned_dynamic );
382+ DEFINE_STRUCT_TESTS (assigned_copy , XFAIL );
331383/* No initialization without compiler instrumentation. */
332- DEFINE_SCALAR_TESTS (none );
333- DEFINE_STRUCT_TESTS (none );
334- DEFINE_TEST (user , struct test_user , STRUCT , none );
384+ DEFINE_SCALAR_TESTS (none , WANT_SUCCESS );
385+ DEFINE_STRUCT_TESTS (none , WANT_SUCCESS );
386+ /* Initialization of members with __user attribute. */
387+ DEFINE_TEST (user , struct test_user , STRUCT , none , WANT_SUCCESS );
335388
336389/*
337390 * Check two uses through a variable declaration outside either path,
@@ -394,8 +447,8 @@ static noinline __init int leaf_switch_2_none(unsigned long sp, bool fill,
394447 * non-code areas (i.e. in a switch statement before the first "case").
395448 * https://bugs.llvm.org/show_bug.cgi?id=44916
396449 */
397- DEFINE_TEST_DRIVER (switch_1_none , uint64_t , SCALAR , 1 );
398- DEFINE_TEST_DRIVER (switch_2_none , uint64_t , SCALAR , 1 );
450+ DEFINE_TEST_DRIVER (switch_1_none , uint64_t , SCALAR , XFAIL );
451+ DEFINE_TEST_DRIVER (switch_2_none , uint64_t , SCALAR , XFAIL );
399452
400453static int __init test_stackinit_init (void )
401454{
@@ -421,12 +474,18 @@ static int __init test_stackinit_init(void)
421474 test_structs (zero );
422475 /* Padding here appears to be accidentally always initialized? */
423476 test_structs (dynamic_partial );
477+ test_structs (assigned_dynamic_partial );
424478 /* Padding initialization depends on compiler behaviors. */
425479 test_structs (static_partial );
426480 test_structs (static_all );
427481 test_structs (dynamic_all );
428482 test_structs (runtime_partial );
429483 test_structs (runtime_all );
484+ test_structs (assigned_static_partial );
485+ test_structs (assigned_static_all );
486+ test_structs (assigned_dynamic_all );
487+ /* Everything fails this since it effectively performs a memcpy(). */
488+ test_structs (assigned_copy );
430489
431490 /* STRUCTLEAK_BYREF_ALL should cover everything from here down. */
432491 test_scalars (none );
0 commit comments