Skip to content

Autogeneration of zcbor encoded bstr does not report failure correctly #587

@GB6336

Description

@GB6336

Issue not all data was consumed in bstr .cbor X

map1 =
{
    "1": int
}

Pet = bstr .cbor map1

generates

static bool decode_Pet(
		zcbor_state_t *state, struct Pet *result)
{
	zcbor_log("%s\r\n", __func__);
	bool int_res;

	bool res = (((zcbor_bstr_start_decode(state, &(*result).Pet)
	&& (int_res = (((decode_map1(state, (&(*result).Pet_cbor))))), zcbor_bstr_end_decode(state), int_res))));

	log_result(state, res, __func__);
	return res;
}

NOTICE
if zcbor_bstr_end_decode(state) fails it does not result in an error

as such when

/*
 * Copyright (c) 2022 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zcbor_encode.h>
#include <stdio.h>
#include <stdint.h>
#include <pet_decode.h>
#include <pet_encode.h>


void testDecode(uint8_t * arr, size_t len)
{
	int err;
	struct Pet decoded_pet;
	size_t processedLen = 0;
	err = cbor_decode_Pet(arr, len, &decoded_pet, &processedLen);
	if (err != ZCBOR_SUCCESS) {
		printf("Decoding failed for pet1: %d\r\n", err);
		return;
	}
	else 
	{
		printf("SUCCESS %d %d\r\n", len, processedLen);
	}

}

/** First pet - from var in pet1.h. */
static void get_pet1(void)
{

	uint8_t mapLen1 = 0xa1;
	uint8_t strLen1 = 0x61;
	uint8_t zero = 0x0;
	uint8_t bstr0 = 0x40;


	#define MAP_1 mapLen1, strLen1, '1', zero
	// NOTE zero, zero, zero is inside bstr0
	uint8_t Pet[] = {bstr0 + 7, MAP_1, zero, zero, zero};
	testDecode(Pet, sizeof(Pet));
}

void main(void)
{
	get_pet1();
}

prints a processed length of less than the whole of the byte string

SUCCESS 8 5

This means that although the function return successfully

the payload and state are still inside the bstr decode state and are pointing to

	uint8_t Pet[] = {bstr0 + 7, MAP_1, 
                                              zero, // <- payload and state point here
                                        zero, zero};

and not to the end of the string, as one would expect if bstr has been decoded successfully

suggested fix: if zcbor_bstr_end_decode(state) fails return an error
Maybe also check you are in the bottom state when you finish decoding?

ISSUE 2 failed bstr .cbor X decode does not clean state up correctly

;
; Copyright (c) 2020 Nordic Semiconductor ASA
;
; SPDX-License-Identifier: Apache-2.0
;


map1 =
{
    "1": int
}

map2 =
{
    "2": int
}

Pet = {
        "1" :   (bstr .cbor map1 )/(bstr .cbor map2 )
}

See these 2 cases

/*
 * Copyright (c) 2022 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zcbor_encode.h>
#include <stdio.h>
#include <stdint.h>
#include <pet_decode.h>
#include <pet_encode.h>


void testDecode(uint8_t * arr, size_t len)
{
	int err;
	struct Pet decoded_pet;
	size_t processedLen = 0;
	err = cbor_decode_Pet(arr, len, &decoded_pet, &processedLen);
	if (err != ZCBOR_SUCCESS) {
		printf("Decoding failed for pet: %d\r\n", err);
		return;
	}
	else 
	{
		printf("pet SUCCESS\r\n");
	}

}

/** First pet - from var in pet1.h. */
static void get_pet1(void)
{

	uint8_t mapLen1 = 0xa1;
	uint8_t strLen1 = 0x61;
	uint8_t strLen0 = 0x60;
	uint8_t zero = 0x0;
	uint8_t bstr0 = 0x40;

		#define MAP_1 mapLen1, strLen1, '1', zero
		#define MAP_2 mapLen1, strLen1, '2', zero

		uint8_t map1[] = {mapLen1, strLen1, '1', bstr0 + 4,MAP_1};
		uint8_t map2[] = {mapLen1, strLen1, '1', bstr0 + 4,MAP_2};
		testDecode(map1, sizeof(map1));
		testDecode(map2, sizeof(map2));

}

void main(void)
{
	get_pet1();
}

output

pet SUCCESS
Decoding failed for pet: 10

test case map2 fails, because it is first parsed as map1

zcbor_bstr_start_decode(state, &(*result).map1_bstr)
	&& (int_res = (((decode_map1(state, (&(*result).map1_bstr_cbor))))), zcbor_bstr_end_decode(state), int_res)))

int_res is false,
so the state needs to be rewound

zcbor_bstr_end_decode(state) does not rewind the state because the payload is not fully consumed

Therefore the state is corrupted and won't be recoverd and decode fails

Suggested fix if (false == int_res) force zcbor_bstr_end_decode

Similarly

if zcbor_union_end_code returns an error is should be passed back up the chain

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions