Skip to content

Commit 2c4d6e9

Browse files
committed
enumeration BUGFIX enums are not sorted when compiled
Properly detect the highest enum value. Fixes #2462
1 parent 7dcf6b1 commit 2c4d6e9

2 files changed

Lines changed: 88 additions & 16 deletions

File tree

src/plugins_types/enumeration.c

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,26 +37,29 @@
3737
* | fixed for a specific type | yes | `int32 *` | assigned little-endian value of the enum |
3838
*/
3939

40-
#define ENUM_FIXED_SIZE_BITS(type) \
41-
lyplg_type_get_highest_set_bit_pos(\
42-
((struct lysc_type_enum *)type)->enums[LY_ARRAY_COUNT(((struct lysc_type_enum *)type)->enums) - 1].value)
43-
4440
static void
4541
lyplg_type_lyb_size_enum(const struct lysc_type *type, enum lyplg_lyb_size_type *size_type, uint32_t *fixed_size_bits)
4642
{
4743
const struct lysc_type_enum *type_enum = (struct lysc_type_enum *)type;
48-
uint32_t max_value;
49-
50-
*size_type = LYPLG_LYB_SIZE_FIXED_BITS;
44+
LY_ARRAY_COUNT_TYPE u;
45+
uint32_t max_value = 0;
5146

52-
if (type_enum->enums[0].value < 0) {
53-
/* we need the full 4 bytes */
54-
*fixed_size_bits = 32;
55-
return;
47+
if (size_type) {
48+
*size_type = LYPLG_LYB_SIZE_FIXED_BITS;
5649
}
5750

58-
/* value of the last enum, sorted */
59-
max_value = type_enum->enums[LY_ARRAY_COUNT(type_enum->enums) - 1].value;
51+
/* learn the max value of enums */
52+
LY_ARRAY_FOR(type_enum->enums, u) {
53+
if (type_enum->enums[u].value < 0) {
54+
/* we need the full 4 bytes */
55+
*fixed_size_bits = 32;
56+
return;
57+
}
58+
59+
if ((unsigned)type_enum->enums[u].value > max_value) {
60+
max_value = type_enum->enums[u].value;
61+
}
62+
}
6063

6164
/* learn the position of the highest set bit, the least amount of bits that can hold the number */
6265
*fixed_size_bits = lyplg_type_get_highest_set_bit_pos(max_value);
@@ -71,6 +74,7 @@ lyplg_type_store_enum(const struct ly_ctx *ctx, const struct lysc_type *type, co
7174
struct lysc_type_enum *type_enum = (struct lysc_type_enum *)type;
7275
LY_ERR ret = LY_SUCCESS;
7376
LY_ARRAY_COUNT_TYPE u;
77+
uint32_t fixed_size_bits;
7478
ly_bool found = 0;
7579
uint32_t value_size;
7680
int64_t num = 0;
@@ -81,8 +85,9 @@ lyplg_type_store_enum(const struct ly_ctx *ctx, const struct lysc_type *type, co
8185
storage->realtype = type;
8286

8387
/* check value length */
88+
lyplg_type_lyb_size_enum(type, NULL, &fixed_size_bits);
8489
ret = lyplg_type_check_value_size("enumeration", format, value_size_bits, LYPLG_LYB_SIZE_FIXED_BITS,
85-
ENUM_FIXED_SIZE_BITS(type), &value_size, err);
90+
fixed_size_bits, &value_size, err);
8691
LY_CHECK_GOTO(ret, cleanup);
8792

8893
if (format == LY_VALUE_LYB) {
@@ -176,17 +181,20 @@ static const void *
176181
lyplg_type_print_enum(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *value, LY_VALUE_FORMAT format,
177182
void *UNUSED(prefix_data), ly_bool *dynamic, uint32_t *value_size_bits)
178183
{
184+
uint32_t fixed_size_bits;
179185
int64_t prev_num = 0, num = 0;
180186
void *buf;
181187

182188
if (format == LY_VALUE_LYB) {
189+
lyplg_type_lyb_size_enum(value->realtype, NULL, &fixed_size_bits);
190+
183191
prev_num = num = value->enum_item->value;
184192
num = htole64(num);
185193
if (num == prev_num) {
186194
/* values are equal, little-endian */
187195
*dynamic = 0;
188196
if (value_size_bits) {
189-
*value_size_bits = ENUM_FIXED_SIZE_BITS(value->realtype);
197+
*value_size_bits = fixed_size_bits;
190198
}
191199
return &value->enum_item->value;
192200
} else {
@@ -196,7 +204,7 @@ lyplg_type_print_enum(const struct ly_ctx *UNUSED(ctx), const struct lyd_value *
196204

197205
*dynamic = 1;
198206
if (value_size_bits) {
199-
*value_size_bits = ENUM_FIXED_SIZE_BITS(value->realtype);
207+
*value_size_bits = fixed_size_bits;
200208
}
201209
memcpy(buf, &num, 4);
202210
return buf;

tests/utests/data/test_lyb.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2571,6 +2571,68 @@ test_shrink(void **state)
25712571
lyd_free_all(tree1);
25722572
}
25732573

2574+
static void
2575+
test_enumeration(void **state)
2576+
{
2577+
const char *mod;
2578+
const char *data_xml;
2579+
2580+
mod =
2581+
"module enum { namespace \"urn:enum\"; prefix e;"
2582+
" container cont {"
2583+
" presence \"\";"
2584+
" leaf test-value {"
2585+
" type enumeration {"
2586+
" enum value-1 { value 1; }"
2587+
" enum value-56 { value 56; }"
2588+
" enum value-25 { value 25; }"
2589+
" enum value-39 { value 39; }"
2590+
" enum value-32 { value 32; }"
2591+
" enum value-31 { value 31; }"
2592+
" }"
2593+
" }"
2594+
" }"
2595+
"}";
2596+
UTEST_ADD_MODULE(mod, LYS_IN_YANG, NULL, NULL);
2597+
2598+
data_xml =
2599+
"<cont xmlns=\"urn:enum\">\n"
2600+
"<test-value>value-56</test-value>\n"
2601+
"</cont>\n";
2602+
check_print_parse(state, data_xml);
2603+
}
2604+
2605+
static void
2606+
test_bits(void **state)
2607+
{
2608+
const char *mod;
2609+
const char *data_xml;
2610+
2611+
mod =
2612+
"module bits { namespace \"urn:bits\"; prefix b;"
2613+
" container cont {"
2614+
" presence \"\";"
2615+
" leaf test-value {"
2616+
" type bits {"
2617+
" bit bit-1 { position 1; }"
2618+
" bit bit-56 { position 56; }"
2619+
" bit bit-25 { position 25; }"
2620+
" bit bit-39 { position 39; }"
2621+
" bit bit-32 { position 32; }"
2622+
" bit bit-31 { position 31; }"
2623+
" }"
2624+
" }"
2625+
" }"
2626+
"}";
2627+
UTEST_ADD_MODULE(mod, LYS_IN_YANG, NULL, NULL);
2628+
2629+
data_xml =
2630+
"<cont xmlns=\"urn:bits\">\n"
2631+
"<test-value>bit-56</test-value>\n"
2632+
"</cont>\n";
2633+
check_print_parse(state, data_xml);
2634+
}
2635+
25742636
int
25752637
main(void)
25762638
{
@@ -2584,6 +2646,8 @@ main(void)
25842646
UTEST(test_opaq, setup),
25852647
UTEST(test_collisions, setup),
25862648
UTEST(test_shrink, setup),
2649+
UTEST(test_enumeration, setup),
2650+
UTEST(test_bits, setup),
25872651
};
25882652

25892653
return cmocka_run_group_tests(tests, NULL, NULL);

0 commit comments

Comments
 (0)