fix(core): Fix encoding of the structure with optional fields (#5513)

* fix(core): Fix calculating the size of the structure with dynamic-sized scalar optional fields

* fix(core): Fix array allocations

* fix(core): Fix encodingMask calculation
This commit is contained in:
Anže Škerjanc 2022-12-18 14:33:22 +01:00 committed by GitHub
parent 8142b26f8d
commit e72d11497a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 79 additions and 41 deletions

View File

@ -1336,9 +1336,10 @@ encodeBinaryStructWithOptFields(const void *src, const UA_DataType *type, Ctx *c
encodingMask |= (UA_UInt32) 1 << optFieldCounter;
ptr += sizeof(void *);
optFieldCounter++;
} else if (m->isArray) {
ptr += sizeof(size_t);
ptr += sizeof(void *);
} else {
if(m->isArray)
ptr += sizeof(size_t);
ptr += mt->memSize;
}
}
@ -1953,8 +1954,13 @@ calcSizeBinaryStructureWithOptFields(const void *p, const UA_DataType *type) {
continue;
}
/* Scalar */
s += calcSizeBinaryJumpTable[membertype->typeKind]((const void*)ptr, membertype);
member->isOptional ? (ptr += sizeof(void *)) : (ptr += membertype->memSize);
if (member->isOptional) {
s += calcSizeBinaryJumpTable[membertype->typeKind](*(void* const*)ptr, membertype);
ptr += sizeof(void *);
} else {
s += calcSizeBinaryJumpTable[membertype->typeKind]((const void*)ptr, membertype);
ptr += membertype->memSize;
}
}
return s;
}

View File

@ -85,9 +85,10 @@ typedef struct {
UA_Int16 a;
UA_Float *b;
UA_Float *c;
UA_String *d;
} Opt;
static UA_DataTypeMember Opt_members[3] = {
static UA_DataTypeMember Opt_members[4] = {
/* a */
{
UA_TYPENAME("a") /* .memberName */
@ -111,6 +112,14 @@ static UA_DataTypeMember Opt_members[3] = {
offsetof(Opt,c) - offsetof(Opt,b) - sizeof(void *),
false,
true /* b is an optional field */
},
/* d */
{
UA_TYPENAME("d")
&UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(Opt,d) - offsetof(Opt,c) - sizeof(void *),
false,
true /* d is an optional field */
}
};
@ -125,7 +134,7 @@ static const UA_DataType OptType = {
false, /* .pointerFree */
false, /* .overlayable (depends on endianness and
the absence of padding) */
3, /* .membersSize */
4, /* .membersSize */
Opt_members
};
@ -134,12 +143,14 @@ const UA_DataTypeArray customDataTypesOptStruct = {&customDataTypes, 2, &OptType
typedef struct {
UA_String description;
size_t bSize;
UA_Float *b;
UA_String *b;
size_t cSize;
UA_Float *c;
size_t dSize;
UA_Float *d;
} OptArray;
static UA_DataTypeMember ArrayOptStruct_members[3] = {
static UA_DataTypeMember ArrayOptStruct_members[4] = {
{
UA_TYPENAME("Measurement description") /* .memberName */
&UA_TYPES[UA_TYPES_STRING], /* .memberType */
@ -149,16 +160,23 @@ static UA_DataTypeMember ArrayOptStruct_members[3] = {
},
{
UA_TYPENAME("TestArray1") /* .memberName */
&UA_TYPES[UA_TYPES_FLOAT], /* .memberType */
&UA_TYPES[UA_TYPES_STRING], /* .memberType */
offsetof(OptArray, bSize) - offsetof(OptArray, description) - sizeof(UA_String), /* .padding */
true, /* .isArray */
true
false
},
{
UA_TYPENAME("TestArray2") /* .memberName */
&UA_TYPES[UA_TYPES_FLOAT], /* .memberType */
offsetof(OptArray, cSize) - offsetof(OptArray, b) - sizeof(void *), /* .padding */
true, /* .isArray */
true
},
{
UA_TYPENAME("TestArray3") /* .memberName */
&UA_TYPES[UA_TYPES_FLOAT], /* .memberType */
offsetof(OptArray, dSize) - offsetof(OptArray, c) - sizeof(void *), /* .padding */
true, /* .isArray */
false
}
};
@ -174,7 +192,7 @@ static const UA_DataType ArrayOptType = {
false, /* .pointerFree */
false, /* .overlayable (depends on endianness and
the absence of padding) */
3, /* .membersSize */
4, /* .membersSize */
ArrayOptStruct_members
};
@ -399,6 +417,8 @@ START_TEST(parseCustomStructureWithOptionalFields) {
o.b = NULL;
o.c = UA_Float_new();
*o.c = (UA_Float) 10.10;
o.d = UA_String_new();
*o.d = UA_STRING_ALLOC("Test");
UA_Variant var;
UA_Variant_init(&var);
@ -432,12 +452,15 @@ START_TEST(parseCustomStructureWithOptionalFields) {
START_TEST(parseCustomStructureWithOptionalFieldsWithArrayNotContained) {
OptArray oa;
oa.description = UA_STRING_ALLOC("TestDesc");
oa.b = NULL;
oa.cSize = 3;
oa.c = (UA_Float *) UA_Array_new(oa.cSize, &ArrayOptType);
oa.c[0] = (UA_Float)1.1;
oa.c[1] = (UA_Float)1.2;
oa.c[2] = (UA_Float)1.3;
oa.bSize = 1;
oa.b = (UA_String *)UA_Array_new(oa.bSize, &UA_TYPES[UA_TYPES_STRING]);
oa.b[0] = UA_STRING_ALLOC("Test");
oa.c = NULL;
oa.dSize = 3;
oa.d = (UA_Float *) UA_Array_new(oa.dSize, &UA_TYPES[UA_TYPES_FLOAT]);
oa.d[0] = (UA_Float)1.1;
oa.d[1] = (UA_Float)1.2;
oa.d[2] = (UA_Float)1.3;
UA_StatusCode retval;
UA_Variant var;
@ -449,7 +472,7 @@ START_TEST(parseCustomStructureWithOptionalFieldsWithArrayNotContained) {
retval = UA_ByteString_allocBuffer(&buf, buflen);
ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
size_t binSize = UA_calcSizeBinary(&oa, &ArrayOptType);
ck_assert_uint_eq(binSize, 32);
ck_assert_uint_eq(binSize, 44);
UA_Byte *pos = buf.data;
const UA_Byte *end = &buf.data[buf.length];
retval = UA_encodeBinaryInternal(&var, &UA_TYPES[UA_TYPES_VARIANT],
@ -464,12 +487,15 @@ START_TEST(parseCustomStructureWithOptionalFieldsWithArrayNotContained) {
OptArray *optStruct2 = (OptArray *) var2.data;
UA_String compare = UA_STRING("TestDesc");
ck_assert(UA_String_equal(&optStruct2->description, &compare));
ck_assert(optStruct2->bSize == 0);
ck_assert(optStruct2->b == NULL);
ck_assert(optStruct2->cSize == 3);
ck_assert((fabs(optStruct2->c[0] - 1.1)) < 0.005);
ck_assert((fabs(optStruct2->c[1] - 1.2)) < 0.005);
ck_assert((fabs(optStruct2->c[2] - 1.3)) < 0.005);
ck_assert(optStruct2->bSize == 1);
compare = UA_STRING("Test");
ck_assert(UA_String_equal(&optStruct2->b[0], &compare));
ck_assert(optStruct2->cSize == 0);
ck_assert(optStruct2->c == NULL);
ck_assert(optStruct2->dSize == 3);
ck_assert((fabs(optStruct2->d[0] - 1.1)) < 0.005);
ck_assert((fabs(optStruct2->d[1] - 1.2)) < 0.005);
ck_assert((fabs(optStruct2->d[2] - 1.3)) < 0.005);
UA_clear(&oa, &ArrayOptType);
UA_Variant_clear(&var);
@ -480,16 +506,19 @@ START_TEST(parseCustomStructureWithOptionalFieldsWithArrayNotContained) {
START_TEST(parseCustomStructureWithOptionalFieldsWithArrayContained) {
OptArray oa;
oa.description = UA_STRING_ALLOC("TestDesc");
oa.bSize = 3;
oa.b = (UA_Float *) UA_Array_new(oa.bSize, &ArrayOptType);
oa.b[0] = (UA_Float)1.1;
oa.b[1] = (UA_Float)1.2;
oa.b[2] = (UA_Float)1.3;
oa.bSize = 1;
oa.b = (UA_String *)UA_Array_new(oa.bSize, &UA_TYPES[UA_TYPES_STRING]);
oa.b[0] = UA_STRING_ALLOC("Test");
oa.cSize = 3;
oa.c = (UA_Float *) UA_Array_new(oa.cSize, &ArrayOptType);
oa.c[0] = (UA_Float)2.1;
oa.c[1] = (UA_Float)2.2;
oa.c[2] = (UA_Float)2.3;
oa.c = (UA_Float *) UA_Array_new(oa.cSize, &UA_TYPES[UA_TYPES_FLOAT]);
oa.c[0] = (UA_Float)1.1;
oa.c[1] = (UA_Float)1.2;
oa.c[2] = (UA_Float)1.3;
oa.dSize = 3;
oa.d = (UA_Float *)UA_Array_new(oa.dSize, &UA_TYPES[UA_TYPES_FLOAT]);
oa.d[0] = (UA_Float)2.1;
oa.d[1] = (UA_Float)2.2;
oa.d[2] = (UA_Float)2.3;
UA_StatusCode retval;
UA_Variant var;
@ -501,7 +530,7 @@ START_TEST(parseCustomStructureWithOptionalFieldsWithArrayContained) {
retval = UA_ByteString_allocBuffer(&buf, buflen);
ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
size_t binSize = UA_calcSizeBinary(&oa, &ArrayOptType);
ck_assert_uint_eq(binSize, 48);
ck_assert_uint_eq(binSize, 60);
UA_Byte *pos = buf.data;
const UA_Byte *end = &buf.data[buf.length];
retval = UA_encodeBinaryInternal(&var, &UA_TYPES[UA_TYPES_VARIANT],
@ -516,14 +545,17 @@ START_TEST(parseCustomStructureWithOptionalFieldsWithArrayContained) {
OptArray *optStruct2 = (OptArray *) var2.data;
UA_String compare = UA_STRING("TestDesc");
ck_assert(UA_String_equal(&optStruct2->description, &compare));
ck_assert(optStruct2->bSize == 3);
ck_assert((fabs(optStruct2->b[0] - 1.1)) < 0.005);
ck_assert((fabs(optStruct2->b[1] - 1.2)) < 0.005);
ck_assert((fabs(optStruct2->b[2] - 1.3)) < 0.005);
ck_assert(optStruct2->bSize == 1);
compare = UA_STRING("Test");
ck_assert(UA_String_equal(&optStruct2->b[0], &compare));
ck_assert(optStruct2->cSize == 3);
ck_assert((fabs(optStruct2->c[0] - 2.1)) < 0.005);
ck_assert((fabs(optStruct2->c[1] - 2.2)) < 0.005);
ck_assert((fabs(optStruct2->c[2] - 2.3)) < 0.005);
ck_assert((fabs(optStruct2->c[0] - 1.1)) < 0.005);
ck_assert((fabs(optStruct2->c[1] - 1.2)) < 0.005);
ck_assert((fabs(optStruct2->c[2] - 1.3)) < 0.005);
ck_assert(optStruct2->dSize == 3);
ck_assert((fabs(optStruct2->d[0] - 2.1)) < 0.005);
ck_assert((fabs(optStruct2->d[1] - 2.2)) < 0.005);
ck_assert((fabs(optStruct2->d[2] - 2.3)) < 0.005);
UA_clear(&oa, &ArrayOptType);
UA_Variant_clear(&var);