Skip to content

Commit

Permalink
tidy up max size in bytes for decoder input and encoder output (#300)
Browse files Browse the repository at this point in the history
New #define QCBOR_SIZE_MAX that is the same max size for decoder input and encoder output

#define QCBOR_MAX_DECODE_INPUT_SIZE is deprecated

This cleans up a TODO: item for the largest size for encoded output


Co-authored-by: Laurence Lundblade <[email protected]>
  • Loading branch information
laurencelundblade and Laurence Lundblade authored Jan 22, 2025
1 parent 4cee345 commit aa7e30c
Show file tree
Hide file tree
Showing 10 changed files with 50 additions and 53 deletions.
12 changes: 9 additions & 3 deletions inc/qcbor/qcbor_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ typedef enum {
QCBOR_ERR_ENCODE_UNSUPPORTED = 2,

/** During encoding, the length of the encoded CBOR exceeded
* @ref QCBOR_MAX_ARRAY_OFFSET, which is slightly less than
* @ref QCBOR_MAX_SIZE, which is slightly less than
* @c UINT32_MAX. */
QCBOR_ERR_BUFFER_TOO_LARGE = 3,

Expand Down Expand Up @@ -361,7 +361,7 @@ typedef enum {
#define QCBOR_END_OF_NOT_WELL_FORMED_ERRORS 39

/** During decoding, the input is too large. It is greater than
* QCBOR_MAX_DECODE_INPUT_SIZE. This is an implementation limit.
* QCBOR_MAX_SIZE. This is an implementation limit.
* This error makes no further decoding possible. */
QCBOR_ERR_INPUT_TOO_LARGE = 40,

Expand Down Expand Up @@ -599,7 +599,13 @@ const char *
qcbor_err_to_str(QCBORError uErr);



/* The maximum size in bytes for input to decode or encoder output. */
/* It is slightly less than UINT32_MAX to accommodate
* QCBOR_NON_BOUNDED_OFFSET and so the limit can be tested on 32-bit
* machines. This will cause trouble where size_t is less than 32
* bits.
*/
#define QCBOR_MAX_SIZE (UINT32_MAX - 100)

/**
* The maximum nesting of arrays and maps when encoding or
Expand Down
17 changes: 9 additions & 8 deletions inc/qcbor/qcbor_main_decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* qcbor_main_decode.h -- The main CBOR decoder.
*
* Copyright (c) 2016-2018, The Linux Foundation.
* Copyright (c) 2018-2024, Laurence Lundblade.
* Copyright (c) 2018-2025, Laurence Lundblade.
* Copyright (c) 2021, Arm Limited.
* All rights reserved.
*
Expand Down Expand Up @@ -286,11 +286,6 @@ typedef enum {



/**
* The maximum size of input to the decoder. Slightly less than
* @c UINT32_MAX to make room for some special indicator values.
*/
#define QCBOR_MAX_DECODE_INPUT_SIZE (UINT32_MAX - 2)

/**
* The maximum number of tags that may occur on an individual nested
Expand Down Expand Up @@ -1397,6 +1392,12 @@ QCBORDecode_SetError(QCBORDecodeContext *pCtx, QCBORError uError);
* They just have been replaced by something better. *
* ========================================================================= */

/**
* @deprecated Use @ref QCBOR_MAX_SIZE instead.
*/
#define QCBOR_MAX_DECODE_INPUT_SIZE QCBOR_MAX_SIZE


/**
* @deprecated The v2 tag number behavior is more correct.
* @brief [Deprecated] Configure CBOR decoder context for QCBOR v1 compatibility.
Expand Down Expand Up @@ -1583,11 +1584,11 @@ QCBORDecode_Private_GetAndTell(QCBORDecodeContext *pMe, QCBORItem *Item, size_t


/* A few cross checks on size constants and special value lengths */
#if QCBOR_MAP_OFFSET_CACHE_INVALID < QCBOR_MAX_DECODE_INPUT_SIZE
#if QCBOR_MAP_OFFSET_CACHE_INVALID < QCBOR_MAX_SIZE
#error QCBOR_MAP_OFFSET_CACHE_INVALID is too large
#endif

#if QCBOR_NON_BOUNDED_OFFSET < QCBOR_MAX_DECODE_INPUT_SIZE
#if QCBOR_NON_BOUNDED_OFFSET < QCBOR_MAX_SIZE
#error QCBOR_NON_BOUNDED_OFFSET is too large
#endif

Expand Down
13 changes: 1 addition & 12 deletions inc/qcbor/qcbor_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* qcbor_private -- Non-public data structures for encding and decoding.
*
* Copyright (c) 2016-2018, The Linux Foundation.
* Copyright (c) 2018-2024, Laurence Lundblade.
* Copyright (c) 2018-2025, Laurence Lundblade.
* Copyright (c) 2021, Arm Limited.
* All rights reserved.
*
Expand Down Expand Up @@ -160,17 +160,6 @@ extern "C" {
#define CBOR_SIMPLEV_RESERVED_END CBOR_SIMPLE_BREAK


/* The largest offset to the start of an array or map. It is slightly
* less than UINT32_MAX so the error condition can be tested on 32-bit
* machines. UINT32_MAX comes from uStart in QCBORTrackNesting being
* a uin32_t.
*
* This will cause trouble on a machine where size_t is less than 32-bits.
*
* TODO: make this public?
*/
#define QCBOR_MAX_ARRAY_OFFSET (UINT32_MAX - 100)


/* The number of tags that are 16-bit or larger that can be handled
* in a decode.
Expand Down
6 changes: 3 additions & 3 deletions src/decode_nesting.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* decode_nesting.c -- All inline implementation of QCBORDecodeNesting
*
* Copyright (c) 2016-2018, The Linux Foundation.
* Copyright (c) 2018-2024, Laurence Lundblade.
* Copyright (c) 2018-2025, Laurence Lundblade.
* Copyright (c) 2021, Arm Limited.
* All rights reserved.
*
Expand Down Expand Up @@ -336,12 +336,12 @@ DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
* Have descended into this before this is called. The job here is
* just to mark it in bounded mode.
*
* Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
* Check against QCBOR_MAX_SIZE make sure that
* uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
*
* Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
*/
if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
if((uint32_t)uOffset >= QCBOR_MAX_SIZE) {
return QCBOR_ERR_INPUT_TOO_LARGE;
}

Expand Down
8 changes: 4 additions & 4 deletions src/qcbor_main_encode.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* ===========================================================================
* Copyright (c) 2016-2018, The Linux Foundation.
* Copyright (c) 2018-2024, Laurence Lundblade.
* Copyright (c) 2018-2025, Laurence Lundblade.
* Copyright (c) 2021, Arm Limited.
* All rights reserved.
*
Expand Down Expand Up @@ -644,13 +644,13 @@ QCBOREncode_Private_OpenMapOrArray(QCBOREncodeContext *pMe,
*/
size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));

/* QCBOR_MAX_ARRAY_OFFSET is slightly less than UINT32_MAX so this
/* QCBOR_MAX_SIZE is slightly less than UINT32_MAX so this
* code can run on a 32-bit machine and tests can pass on a 32-bit
* machine. If it was exactly UINT32_MAX, then this code would not
* compile or run on a 32-bit machine and an #ifdef or some machine
* size detection would be needed reducing portability.
* size detection would be needed, reducing portability.
*/
if(uEndPosition >= QCBOR_MAX_ARRAY_OFFSET) {
if(uEndPosition >= QCBOR_MAX_SIZE) {
pMe->uError = QCBOR_ERR_BUFFER_TOO_LARGE;

} else {
Expand Down
6 changes: 3 additions & 3 deletions src/qcbor_spiffy_decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* qcbor_spiffy_decode.c -- "Spiffy" QCBOR decoding
*
* Copyright (c) 2016-2018, The Linux Foundation.
* Copyright (c) 2018-2024, Laurence Lundblade.
* Copyright (c) 2018-2025, Laurence Lundblade.
* Copyright (c) 2021, Arm Limited.
* All rights reserved.
*
Expand Down Expand Up @@ -359,9 +359,9 @@ QCBORDecode_Private_MapSearch(QCBORDecodeContext *pMe,

// Check here makes sure that this won't accidentally be
// QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
// QCBOR_MAX_DECODE_INPUT_SIZE.
// QCBOR_MAX_SIZE.
// Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
if((uint32_t)uEndOffset >= QCBOR_MAX_SIZE) {
uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
goto Done;
}
Expand Down
6 changes: 3 additions & 3 deletions src/qcbor_tag_decode.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* ==========================================================================
* qcbor_tag_decode.c -- Tag content decoders
*
* Copyright (c) 2024, Laurence Lundblade. All rights reserved.
* Copyright (c) 2025, Laurence Lundblade. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
Expand Down Expand Up @@ -658,14 +658,14 @@ QCBORDecode_Private_EnterBstrWrapped(QCBORDecodeContext *pMe,

const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
/* This check makes the cast of uPreviousLength to uint32_t below safe. */
if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
if(uPreviousLength >= QCBOR_MAX_SIZE) {
uError = QCBOR_ERR_INPUT_TOO_LARGE;
goto Done;
}

const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf), pItem->val.string.ptr);
/* This check makes the cast of uStartOfBstr to uint32_t below safe. */
if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_SIZE) {
/* This should never happen because pItem->val.string.ptr should
* always be valid since it was just returned.
*/
Expand Down
29 changes: 15 additions & 14 deletions test/qcbor_decode_tests.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*==============================================================================
* Copyright (c) 2016-2018, The Linux Foundation.
* Copyright (c) 2018-2024, Laurence Lundblade.
* Copyright (c) 2018-2025, Laurence Lundblade.
* Copyright (c) 2021, Arm Limited.
* All rights reserved.
*
Expand Down Expand Up @@ -9210,19 +9210,20 @@ int32_t TooLargeInputTest(void)
QCBORError uErr;
UsefulBufC String;

// These tests require a build with QCBOR_MAX_DECODE_INPUT_SIZE set
// to 10 There's not really any way to test this error
// condition. The error condition is not complex, so setting
// QCBOR_MAX_DECODE_INPUT_SIZE gives an OK test.

// The input CBOR is only too large because the
// QCBOR_MAX_DECODE_INPUT_SIZE is 10.
//
// This test is disabled for the normal test runs because of the
// special build requirement.
/* These tests require a build with QCBOR_MAX_SIZE set
* to 10. There's not really any way to test this error
* condition. The error condition is not complex, so setting
* QCBOR_MAX_SIZE gives an OK test.
*
* The input CBOR is only too large because the
* QCBOR_MAX_SIZE is 10.
*
* This test is disabled for the normal test runs because of the
* special build requirement.
*/


// Tests the start of a map being too large
/* Tests the start of a map being too large */
QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTooLarge1), QCBOR_DECODE_MODE_NORMAL);
QCBORDecode_EnterArray(&DC, NULL);
QCBORDecode_GetTextString(&DC, &String);
Expand All @@ -9236,7 +9237,7 @@ int32_t TooLargeInputTest(void)
return 2;
}

// Tests the end of a map being too large
/* Tests the end of a map being too large */
QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTooLarge2), QCBOR_DECODE_MODE_NORMAL);
QCBORDecode_EnterArray(&DC, NULL);
QCBORDecode_EnterMap(&DC, NULL);
Expand All @@ -9250,7 +9251,7 @@ int32_t TooLargeInputTest(void)
return 4;
}

// Tests the entire input CBOR being too large when processing bstr wrapping
/* Tests the entire input CBOR being too large when processing bstr wrapping */
QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTooLarge3), QCBOR_DECODE_MODE_NORMAL);
QCBORDecode_EnterBstrWrapped(&DC, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL);
uErr = QCBORDecode_GetError(&DC);
Expand Down
2 changes: 1 addition & 1 deletion test/qcbor_decode_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ int32_t DecodeTaggedTypeTests(void);

/*
Test the detection of input that is too large. Requires
a special build that makes QCBOR_MAX_DECODE_INPUT_SIZE small.
a special build that makes QCBOR_MAX_SIZE small.
*/
int32_t TooLargeInputTest(void);

Expand Down
4 changes: 2 additions & 2 deletions test/qcbor_encode_tests.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*==============================================================================
Copyright (c) 2016-2018, The Linux Foundation.
Copyright (c) 2018-2024, Laurence Lundblade.
Copyright (c) 2018-2025, Laurence Lundblade.
Copyright (c) 2022, Arm Limited. All rights reserved.
Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -2742,7 +2742,7 @@ int32_t EncodeErrorTests(void)
// Third, fit an array in exactly at max position allowed
QCBOREncode_Init(&EC, Buffer);
QCBOREncode_OpenArray(&EC);
QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, QCBOR_MAX_ARRAY_OFFSET-6});
QCBOREncode_AddBytes(&EC, (UsefulBufC){NULL, QCBOR_MAX_SIZE-6});
QCBOREncode_OpenArray(&EC);
QCBOREncode_CloseArray(&EC);
QCBOREncode_CloseArray(&EC);
Expand Down

0 comments on commit aa7e30c

Please sign in to comment.