Skip to content

Commit 11d72fa

Browse files
Merge pull request #1466 from LedgerHQ/auto_update_API_LEVEL_26
[AUTO_UPDATE] Branch API_LEVEL_26
2 parents 6fc5e86 + 90db105 commit 11d72fa

3 files changed

Lines changed: 120 additions & 16 deletions

File tree

lib_tlv/tlv_internals.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@
4141
* @brief Internal macro — creates a flag enum for mapping tags to their reception flag.
4242
* @note Do not use directly.
4343
*/
44-
#define __X_DEFINE_TLV__TAG_FLAG(value, name, callback, unicity) name##_FLAG = (1U << name##_INDEX),
44+
#define __X_DEFINE_TLV__TAG_FLAG(value, name, callback, unicity) \
45+
name##_FLAG = ((TLV_flag_t) 1 << name##_INDEX),
4546

4647
/**
4748
* @brief Internal macro — expands to a switch case that maps a tag to its flag.

lib_tlv/tlv_library.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ TAG_LIST(X) \
153153
PARSE_FUNCTION_NAME##_TAG_COUNT, \
154154
}; \
155155
\
156+
_Static_assert(PARSE_FUNCTION_NAME##_TAG_COUNT <= sizeof(TLV_flag_t) * 8, \
157+
"Too many tags: exceeds the number of bits in TLV_flag_t"); \
158+
\
156159
/* Create an enum associating tags with their flags (for internal use). */ \
157160
enum { \
158161
TAG_LIST(__X_DEFINE_TLV__TAG_FLAG) \

unit-tests/lib_tlv/test_tlv_macros.c

Lines changed: 115 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,46 @@ DEFINE_TLV_PARSER(THIRD_TAGS, common_handler, third_parser)
6464

6565
DEFINE_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

Comments
 (0)