@@ -64,6 +64,46 @@ DEFINE_TLV_PARSER(THIRD_TAGS, common_handler, third_parser)
6464
6565DEFINE_TLV_PARSER (MANY_TAGS , NULL , many_parser )
6666
67+ /* clang-format off */
68+ /* Fifth parser with 33 tags to validate 64-bit flag support (index >= 32) */
69+ #define LARGE_TAGS (X ) \
70+ X(0x100, TAG_L00, NULL, ENFORCE_UNIQUE_TAG) \
71+ X(0x101, TAG_L01, NULL, ENFORCE_UNIQUE_TAG) \
72+ X(0x102, TAG_L02, NULL, ENFORCE_UNIQUE_TAG) \
73+ X(0x103, TAG_L03, NULL, ENFORCE_UNIQUE_TAG) \
74+ X(0x104, TAG_L04, NULL, ENFORCE_UNIQUE_TAG) \
75+ X(0x105, TAG_L05, NULL, ENFORCE_UNIQUE_TAG) \
76+ X(0x106, TAG_L06, NULL, ENFORCE_UNIQUE_TAG) \
77+ X(0x107, TAG_L07, NULL, ENFORCE_UNIQUE_TAG) \
78+ X(0x108, TAG_L08, NULL, ENFORCE_UNIQUE_TAG) \
79+ X(0x109, TAG_L09, NULL, ENFORCE_UNIQUE_TAG) \
80+ X(0x10A, TAG_L10, NULL, ENFORCE_UNIQUE_TAG) \
81+ X(0x10B, TAG_L11, NULL, ENFORCE_UNIQUE_TAG) \
82+ X(0x10C, TAG_L12, NULL, ENFORCE_UNIQUE_TAG) \
83+ X(0x10D, TAG_L13, NULL, ENFORCE_UNIQUE_TAG) \
84+ X(0x10E, TAG_L14, NULL, ENFORCE_UNIQUE_TAG) \
85+ X(0x10F, TAG_L15, NULL, ENFORCE_UNIQUE_TAG) \
86+ X(0x110, TAG_L16, NULL, ENFORCE_UNIQUE_TAG) \
87+ X(0x111, TAG_L17, NULL, ENFORCE_UNIQUE_TAG) \
88+ X(0x112, TAG_L18, NULL, ENFORCE_UNIQUE_TAG) \
89+ X(0x113, TAG_L19, NULL, ENFORCE_UNIQUE_TAG) \
90+ X(0x114, TAG_L20, NULL, ENFORCE_UNIQUE_TAG) \
91+ X(0x115, TAG_L21, NULL, ENFORCE_UNIQUE_TAG) \
92+ X(0x116, TAG_L22, NULL, ENFORCE_UNIQUE_TAG) \
93+ X(0x117, TAG_L23, NULL, ENFORCE_UNIQUE_TAG) \
94+ X(0x118, TAG_L24, NULL, ENFORCE_UNIQUE_TAG) \
95+ X(0x119, TAG_L25, NULL, ENFORCE_UNIQUE_TAG) \
96+ X(0x11A, TAG_L26, NULL, ENFORCE_UNIQUE_TAG) \
97+ X(0x11B, TAG_L27, NULL, ENFORCE_UNIQUE_TAG) \
98+ X(0x11C, TAG_L28, NULL, ENFORCE_UNIQUE_TAG) \
99+ X(0x11D, TAG_L29, NULL, ENFORCE_UNIQUE_TAG) \
100+ X(0x11E, TAG_L30, NULL, ENFORCE_UNIQUE_TAG) \
101+ X(0x11F, TAG_L31, NULL, ENFORCE_UNIQUE_TAG) \
102+ X(0x120, TAG_L32, NULL, ENFORCE_UNIQUE_TAG)
103+ /* clang-format on */
104+
105+ DEFINE_TLV_PARSER (LARGE_TAGS , NULL , large_parser )
106+
67107/* -------------------------------------------------------------------------- */
68108/* Dummy handler implementations */
69109/* -------------------------------------------------------------------------- */
@@ -169,10 +209,10 @@ static void test_tag_flag_values(void **state)
169209{
170210 (void ) state ;
171211
172- /* Test that TAG_FLAG macro correctly computes (1U << INDEX) */
173- assert_int_equal (TAG_ALPHA_FLAG , 1U << TAG_ALPHA_INDEX );
174- assert_int_equal (TAG_BETA_FLAG , 1U << TAG_BETA_INDEX );
175- assert_int_equal (TAG_GAMMA_FLAG , 1U << TAG_GAMMA_INDEX );
212+ /* Test that TAG_FLAG macro correctly computes ((TLV_flag_t)1 << INDEX) */
213+ assert_int_equal (TAG_ALPHA_FLAG , ( TLV_flag_t ) 1 << TAG_ALPHA_INDEX );
214+ assert_int_equal (TAG_BETA_FLAG , ( TLV_flag_t ) 1 << TAG_BETA_INDEX );
215+ assert_int_equal (TAG_GAMMA_FLAG , ( TLV_flag_t ) 1 << TAG_GAMMA_INDEX );
176216
177217 /* Verify specific flag values */
178218 assert_int_equal (TAG_ALPHA_FLAG , 0x01 ); /* 1 << 0 */
@@ -190,7 +230,7 @@ static void test_tag_flags_are_unique(void **state)
190230 assert_true ((TAG_BETA_FLAG & TAG_GAMMA_FLAG ) == 0 );
191231
192232 /* Verify OR combination creates unique patterns */
193- uint32_t combined = TAG_ALPHA_FLAG | TAG_BETA_FLAG ;
233+ TLV_flag_t combined = TAG_ALPHA_FLAG | TAG_BETA_FLAG ;
194234 assert_int_equal (combined , 0x03 );
195235
196236 combined = TAG_ALPHA_FLAG | TAG_GAMMA_FLAG ;
@@ -202,13 +242,13 @@ static void test_tag_flags_multiple_parsers(void **state)
202242 (void ) state ;
203243
204244 /* Test that flags from different parsers don't collide */
205- assert_int_equal (TAG_FOO_FLAG , 1U << TAG_FOO_INDEX );
206- assert_int_equal (TAG_BAR_FLAG , 1U << TAG_BAR_INDEX );
207- assert_int_equal (TAG_DELTA_FLAG , 1U << TAG_DELTA_INDEX );
245+ assert_int_equal (TAG_FOO_FLAG , ( TLV_flag_t ) 1 << TAG_FOO_INDEX );
246+ assert_int_equal (TAG_BAR_FLAG , ( TLV_flag_t ) 1 << TAG_BAR_INDEX );
247+ assert_int_equal (TAG_DELTA_FLAG , ( TLV_flag_t ) 1 << TAG_DELTA_INDEX );
208248
209249 /* Test many flags */
210- assert_int_equal (TAG_A0_FLAG , 1U << TAG_A0_INDEX );
211- assert_int_equal (TAG_A7_FLAG , 1U << TAG_A7_INDEX );
250+ assert_int_equal (TAG_A0_FLAG , ( TLV_flag_t ) 1 << TAG_A0_INDEX );
251+ assert_int_equal (TAG_A7_FLAG , ( TLV_flag_t ) 1 << TAG_A7_INDEX );
212252 assert_int_equal (TAG_A7_FLAG , 0x80 ); /* 1 << 7 */
213253}
214254
@@ -309,9 +349,9 @@ static void test_enum_consistency(void **state)
309349 assert_int_equal (TAG_BETA , 0x02 );
310350 assert_int_equal (TAG_GAMMA , 0x03 );
311351
312- assert_int_equal (TAG_ALPHA_FLAG , 1U << TAG_ALPHA_INDEX );
313- assert_int_equal (TAG_BETA_FLAG , 1U << TAG_BETA_INDEX );
314- assert_int_equal (TAG_GAMMA_FLAG , 1U << TAG_GAMMA_INDEX );
352+ assert_int_equal (TAG_ALPHA_FLAG , ( TLV_flag_t ) 1 << TAG_ALPHA_INDEX );
353+ assert_int_equal (TAG_BETA_FLAG , ( TLV_flag_t ) 1 << TAG_BETA_INDEX );
354+ assert_int_equal (TAG_GAMMA_FLAG , ( TLV_flag_t ) 1 << TAG_GAMMA_INDEX );
315355
316356 assert_int_equal (test_parser_TAG_COUNT , 3 );
317357}
@@ -339,7 +379,7 @@ static void test_all_flags_can_be_combined(void **state)
339379 (void ) state ;
340380
341381 /* Test that all flags can be OR'd together without collision */
342- uint32_t all_flags = TAG_ALPHA_FLAG | TAG_BETA_FLAG | TAG_GAMMA_FLAG ;
382+ TLV_flag_t all_flags = TAG_ALPHA_FLAG | TAG_BETA_FLAG | TAG_GAMMA_FLAG ;
343383 assert_int_equal (all_flags , 0x07 ); /* 0b111 */
344384
345385 /* Verify each flag is still distinguishable */
@@ -381,7 +421,7 @@ static void test_flag_computation_correctness(void **state)
381421
382422 /* Verify flag computation for various index values */
383423 for (int i = 0 ; i < 8 ; i ++ ) {
384- uint32_t expected_flag = 1U << i ;
424+ TLV_flag_t expected_flag = ( TLV_flag_t ) 1 << i ;
385425 /* We can't dynamically test this, but we verify the pattern */
386426 if (i == TAG_ALPHA_INDEX ) {
387427 assert_int_equal (TAG_ALPHA_FLAG , expected_flag );
@@ -395,6 +435,60 @@ static void test_flag_computation_correctness(void **state)
395435 }
396436}
397437
438+ /* -------------------------------------------------------------------------- */
439+ /* Tests for 64-bit flag support (tags at index >= 32) */
440+ /* -------------------------------------------------------------------------- */
441+
442+ static void test_large_parser_tag_count (void * * state )
443+ {
444+ (void ) state ;
445+ assert_int_equal (large_parser_TAG_COUNT , 33 );
446+ }
447+
448+ static void test_flag_above_32bit_boundary (void * * state )
449+ {
450+ (void ) state ;
451+
452+ /* TAG_L32 is at index 32 — this is the exact case that was broken with 1U << 32 */
453+ assert_int_equal (TAG_L32_INDEX , 32 );
454+ assert_true (TAG_L32_FLAG == ((TLV_flag_t ) 1 << 32 ));
455+ assert_true (TAG_L32_FLAG != 0 ); /* was 0 with the old 1U << 32 (UB) */
456+
457+ /* Verify a few lower indices are still correct */
458+ assert_true (TAG_L00_FLAG == ((TLV_flag_t ) 1 << 0 ));
459+ assert_true (TAG_L31_FLAG == ((TLV_flag_t ) 1 << 31 ));
460+ }
461+
462+ static void test_large_parser_flags_are_unique (void * * state )
463+ {
464+ (void ) state ;
465+
466+ /* Verify that no two flags in the large parser share bits */
467+ TLV_flag_t all = 0 ;
468+ TLV_flag_t flags [] = {
469+ TAG_L00_FLAG , TAG_L01_FLAG , TAG_L02_FLAG , TAG_L03_FLAG , TAG_L04_FLAG , TAG_L05_FLAG ,
470+ TAG_L06_FLAG , TAG_L07_FLAG , TAG_L08_FLAG , TAG_L09_FLAG , TAG_L10_FLAG , TAG_L11_FLAG ,
471+ TAG_L12_FLAG , TAG_L13_FLAG , TAG_L14_FLAG , TAG_L15_FLAG , TAG_L16_FLAG , TAG_L17_FLAG ,
472+ TAG_L18_FLAG , TAG_L19_FLAG , TAG_L20_FLAG , TAG_L21_FLAG , TAG_L22_FLAG , TAG_L23_FLAG ,
473+ TAG_L24_FLAG , TAG_L25_FLAG , TAG_L26_FLAG , TAG_L27_FLAG , TAG_L28_FLAG , TAG_L29_FLAG ,
474+ TAG_L30_FLAG , TAG_L31_FLAG , TAG_L32_FLAG ,
475+ };
476+ for (size_t i = 0 ; i < sizeof (flags ) / sizeof (flags [0 ]); i ++ ) {
477+ assert_true ((all & flags [i ]) == 0 ); /* no overlap */
478+ all |= flags [i ];
479+ }
480+ }
481+
482+ static void test_large_parser_tag_to_flag (void * * state )
483+ {
484+ (void ) state ;
485+
486+ assert_true (large_parser_tag_to_flag (TAG_L00 ) == TAG_L00_FLAG );
487+ assert_true (large_parser_tag_to_flag (TAG_L31 ) == TAG_L31_FLAG );
488+ assert_true (large_parser_tag_to_flag (TAG_L32 ) == TAG_L32_FLAG );
489+ assert_true (large_parser_tag_to_flag (0xFF ) == 0 );
490+ }
491+
398492/* -------------------------------------------------------------------------- */
399493/* Test suite entry point */
400494/* -------------------------------------------------------------------------- */
@@ -433,6 +527,12 @@ int main(int argc, char **argv)
433527 cmocka_unit_test (test_tag_values_are_preserved ),
434528 cmocka_unit_test (test_index_enumeration_starts_at_zero ),
435529 cmocka_unit_test (test_flag_computation_correctness ),
530+
531+ /* 64-bit flag support tests */
532+ cmocka_unit_test (test_large_parser_tag_count ),
533+ cmocka_unit_test (test_flag_above_32bit_boundary ),
534+ cmocka_unit_test (test_large_parser_flags_are_unique ),
535+ cmocka_unit_test (test_large_parser_tag_to_flag ),
436536 };
437537 return cmocka_run_group_tests (tests , NULL , NULL );
438538}
0 commit comments