Skip to content

Commit

Permalink
Merge branch 'master' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
Laurence Lundblade committed Mar 11, 2024
2 parents ea3e57c + f00b8be commit 5c79a49
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 8 deletions.
9 changes: 8 additions & 1 deletion inc/qcbor/qcbor_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -534,8 +534,15 @@ typedef enum {
/* Trying to encode something that is discouraged (e.g., 65-bit
* negative integer) without allowing it by calling
* QCBOREncode_Allow() */
QCBOR_ERR_NOT_ALLOWED = 80
QCBOR_ERR_NOT_ALLOWED = 80,

/** A range of error codes that can be made use of by the
* caller. QCBOR internally does nothing with these except notice
* that they are not QCBOR_SUCCESS. See QCBORDecode_SetError(). */
QCBOR_ERR_FIRST_USER_DEFINED = 128,

/** See \ref QCBOR_ERR_FIRST_USER_DEFINED */
QCBOR_ERR_LAST_USER_DEFINED = 255

/* This is stored in uint8_t; never add values > 255 */
} QCBORError;
Expand Down
50 changes: 43 additions & 7 deletions inc/qcbor/qcbor_decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,11 @@ extern "C" {
* call QCBORDecode_GetError() to know the earlier items were
* successfully decoded before examining their value or type.
*
* The internal decode error state is reset only by re initializing the
* decoder or calling QCBORDecode_GetErrorAndReset().
* The internal decode error state can be reset by reinitializing the
* decoder or calling QCBORDecode_GetErrorAndReset(). Code calling
* QCBOR may take advantage of the internal error state to halt
* futher decoding and propagate errors it detects using
* QCBORDecode_SetError().
*
* It is only useful to reset the error state by calling
* QCBORDecode_GetErrorAndReset() on recoverable errors. Examples of
Expand Down Expand Up @@ -900,9 +903,10 @@ QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx,
*
* See [Decode Error Overview](#Decode-Errors-Overview).
*
* If a decoding error occurs, \c uDataType and \c uLabelType will be set
* to @ref QCBOR_TYPE_NONE. If there is no need to know the specific
* error, it is sufficient to check for @ref QCBOR_TYPE_NONE.
* If a decoding error occurs or previously occured, \c uDataType and
* \c uLabelType will be set to @ref QCBOR_TYPE_NONE. If there is no
* need to know the specific error, it is sufficient to check for @ref
* QCBOR_TYPE_NONE.
*
* Errors fall in several categories:
*
Expand Down Expand Up @@ -1212,7 +1216,7 @@ QCBORDecode_GetAndResetError(QCBORDecodeContext *pCtx);
/**
* @brief Whether an error indicates non-well-formed CBOR.
*
* @param[in] uErr The decoder context.
* @param[in] uErr The QCBOR error code.
* @return @c true if the error code indicates non-well-formed CBOR.
*/
static bool
Expand All @@ -1222,7 +1226,7 @@ QCBORDecode_IsNotWellFormedError(QCBORError uErr);
/**
* @brief Whether a decoding error is recoverable.
*
* @param[in] uErr The decoder context.
* @param[in] uErr The QCBOR error code.
* @return @c true if the error code indicates and uncrecoverable error.
*
* When an error is unrecoverable, no further decoding of the input is
Expand All @@ -1242,6 +1246,30 @@ static bool
QCBORDecode_IsUnrecoverableError(QCBORError uErr);


/**
* @brief Manually set error condition, or set user-defined error.
*
* @param[in] pCtx The decoder context.
* @param[in] uError The error code to set.
*
* Once set, none of the QCBORDecode methods will do anything and the
* error code set will stay until cleared with
* QCBORDecode_GetAndResetError(). A user-defined error can be set
* deep in some decoding layers to short-circuit further decoding
* and propagate up.
*
* When the error condition is set, QCBORDecode_VGetNext() will always
* return an item with data and label type as \ref QCBOR_TYPE_NONE.
*
* The main intent of this is to set a user-defined error code in the
* range of \ref QCBOR_ERR_FIRST_USER_DEFINED to
* \ref QCBOR_ERR_LAST_USER_DEFINED, but it is OK to set QCBOR-defined
* error codes too.
*/
static void
QCBORDecode_SetError(QCBORDecodeContext *pCtx, QCBORError uError);




/**
Expand Down Expand Up @@ -1530,6 +1558,14 @@ QCBORDecode_IsUnrecoverableError(const QCBORError uErr)
}
}


static inline void
QCBORDecode_SetError(QCBORDecodeContext *pMe, QCBORError uError)
{
pMe->uLastError = (uint8_t)uError;
}


/* A few cross checks on size constants and special value lengths */
#if QCBOR_MAP_OFFSET_CACHE_INVALID < QCBOR_MAX_DECODE_INPUT_SIZE
#error QCBOR_MAP_OFFSET_CACHE_INVALID is too large
Expand Down
4 changes: 4 additions & 0 deletions src/qcbor_decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2658,6 +2658,8 @@ void
QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
{
if(pMe->uLastError != QCBOR_SUCCESS) {
pDecodedItem->uDataType = QCBOR_TYPE_NONE;
pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
return;
}

Expand All @@ -2672,6 +2674,8 @@ void
QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
{
if(pMe->uLastError != QCBOR_SUCCESS) {
pDecodedItem->uDataType = QCBOR_TYPE_NONE;
pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
return;
}

Expand Down
82 changes: 82 additions & 0 deletions test/qcbor_decode_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -8830,3 +8830,85 @@ int32_t BoolTest(void)

return 0;
}


int32_t
ErrorHandlingTests(void)
{
QCBORDecodeContext DCtx;
QCBORItem Item;
QCBORError uError;
int64_t integer;

/* Test QCBORDecode_SetError() */
QCBORDecode_Init(&DCtx,
UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded),
QCBOR_DECODE_MODE_NORMAL);

QCBORDecode_SetError(&DCtx, QCBOR_ERR_FIRST_USER_DEFINED);

QCBORDecode_VGetNext(&DCtx, &Item);

uError = QCBORDecode_GetError(&DCtx);

if(uError != QCBOR_ERR_FIRST_USER_DEFINED) {
return -1;
}

if(Item.uLabelType != QCBOR_TYPE_NONE ||
Item.uDataType != QCBOR_TYPE_NONE) {
return -2;
}


/* Test data type returned from previous error */
QCBORDecode_Init(&DCtx,
UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded),
QCBOR_DECODE_MODE_NORMAL);
QCBORDecode_GetInt64(&DCtx, &integer);
uError = QCBORDecode_GetError(&DCtx);
if(uError != QCBOR_ERR_UNEXPECTED_TYPE) {
return -3;
}

QCBORDecode_VGetNext(&DCtx, &Item);
if(Item.uLabelType != QCBOR_TYPE_NONE ||
Item.uDataType != QCBOR_TYPE_NONE) {
return -2;
}
uError = QCBORDecode_GetError(&DCtx);
if(uError != QCBOR_ERR_UNEXPECTED_TYPE) {
return -3;
}


/* Test error classification functions */

if(!QCBORDecode_IsUnrecoverableError(QCBOR_ERR_INDEFINITE_STRING_CHUNK)) {
return -10;
}
if(QCBORDecode_IsUnrecoverableError(QCBOR_SUCCESS)) {
return -11;
}
if(!QCBORDecode_IsUnrecoverableError(QCBOR_ERR_INDEFINITE_STRING_CHUNK)) {
return -12;
}
if(QCBORDecode_IsUnrecoverableError(QCBOR_ERR_DUPLICATE_LABEL)) {
return -13;
}

if(!QCBORDecode_IsNotWellFormedError(QCBOR_ERR_BAD_TYPE_7)) {
return -20;
}
if(!QCBORDecode_IsNotWellFormedError(QCBOR_ERR_BAD_BREAK)) {
return -21;
}
if(QCBORDecode_IsNotWellFormedError(QCBOR_SUCCESS)) {
return -22;
}
if(QCBORDecode_IsNotWellFormedError(QCBOR_ERR_ARRAY_DECODE_TOO_LONG)) {
return -23;
}

return 0;
}
5 changes: 5 additions & 0 deletions test/qcbor_decode_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,4 +318,9 @@ Test GitHub issue #134: decode an indefinite-length string with a zero-length fi
*/
int32_t CBORTestIssue134(void);



int32_t ErrorHandlingTests(void);


#endif /* defined(__QCBOR__qcbort_decode_tests__) */
1 change: 1 addition & 0 deletions test/run_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ static test_entry2 s_tests2[] = {


static test_entry s_tests[] = {
TEST_ENTRY(ErrorHandlingTests),
TEST_ENTRY(OpenCloseBytesTest),
TEST_ENTRY(EnterBstrTest),
TEST_ENTRY(IntegerConvertTest),
Expand Down

0 comments on commit 5c79a49

Please sign in to comment.