Skip to content

Commit

Permalink
Testing near complete and passing
Browse files Browse the repository at this point in the history
  • Loading branch information
Laurence Lundblade committed May 7, 2024
1 parent 224c407 commit 1d5fd83
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 46 deletions.
24 changes: 11 additions & 13 deletions inc/qcbor/qcbor_decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ typedef enum {
} QCBORDecodeMode;

/**
* The maximum size of input to the decoder. Slightly less than UINT32_MAX
* 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)
Expand Down Expand Up @@ -1034,38 +1034,36 @@ QCBORError
QCBORDecode_PeekNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);



/**
* @brief Get the current traversal cursort offset in the input CBOR.
*
* @param[in] pCtx The decoder context.
* @param[in] pCtx The decoder context.
*
* @returns The traversal cursor offset or @c UINT32_MAX.
* The position returned is always the start of the next
* item that would be next decoded with QCBORDecode_VGetNext().
* If the cursor is at the end of the input, @c UINT32_MAX
* If the cursor is at the end of the input or in the error state, @c UINT32_MAX
* is returned.
*
* When decoding map items, the
* position returned is always of the label, never the
* value.
*
* For indefinite-length items, the CBOR break bytes are consumed
* when the last item in an indefinite length array or map is consumed
* For indefinite-length arrays and maps, the break byte is consumed
* when the last item in the array or map is consumed
* so the cursor is at the next item to be decoded as expected.
*
* There are some special rules for the traversal cursor when
* fetching map items by label. See the decription of @SpiffyDecode.
* fetching map items by label. See the description of @SpiffyDecode.
*
* There is no corresponding seek because it is too complicated
* There is no corresponding seek method because it is too complicated
* to restore the internal decoder state that tracks nesting.
*/
uint32_t
QCBORDecode_Tell(QCBORDecodeContext *pCtx);



/**
* @brief Returns the tag numbers for an item.
*
Expand All @@ -1092,7 +1090,7 @@ QCBORDecode_Tell(QCBORDecodeContext *pCtx);
* See also @ref CBORTags, @ref Tag-Usage and @ref Tags-Overview.
*
* To reduce memory used by a QCBORItem, tag numbers larger than
* UINT16_MAX are mapped so the tag numbers in @c uTags should be
* @c UINT16_MAX are mapped so the tag numbers in @c uTags should be
* accessed with this function rather than directly.
*
* This returns @ref CBOR_TAG_INVALID64 if any error occurred when
Expand Down Expand Up @@ -1305,8 +1303,8 @@ QCBORDecode_SetError(QCBORDecodeContext *pCtx, QCBORError uError);
* @return 0 on success -1 if not
*
* When decoding an integer, the CBOR decoder will return the value as
* an int64_t unless the integer is in the range of @c INT64_MAX and @c
* UINT64_MAX. That is, unless the value is so large that it can only be
* an int64_t unless the integer is in the range of @c INT64_MAX and
* @c UINT64_MAX. That is, unless the value is so large that it can only be
* represented as a @c uint64_t, it will be an @c int64_t.
*
* CBOR itself doesn't size the individual integers it carries at
Expand Down Expand Up @@ -1518,7 +1516,7 @@ QCBORDecode_IsTagged(QCBORDecodeContext *pCtx,
* been decoded.
*
* This is not backwards compatibile in two ways. First, it is limited
* to \ref QCBOR_MAX_TAGS_PER_ITEM items whereas previously it was
* to @ref QCBOR_MAX_TAGS_PER_ITEM items whereas previously it was
* unlimited. Second, it will not inlucde the tags that QCBOR decodes
* internally.
*
Expand Down
20 changes: 9 additions & 11 deletions src/qcbor_decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -3138,22 +3138,20 @@ QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
uint32_t
QCBORDecode_Tell(QCBORDecodeContext *pMe)
{
size_t xx;
size_t uCursorOffset;

xx = (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));

if(xx == UsefulInputBuf_GetBufferLength(&(pMe->InBuf))) {
if(pMe->uLastError != QCBOR_SUCCESS) {
return UINT32_MAX;
} else {
return (uint32_t)xx;
}

/*
uCursorOffset = UsefulInputBuf_Tell(&(pMe->InBuf));

Confirm position is as expected in maps and arrays for
- definite length
- indefinite lengths
*/
if(uCursorOffset == UsefulInputBuf_GetBufferLength(&(pMe->InBuf))) {
return UINT32_MAX;
} else {
/* Cast is safe because decoder input size is restricted. */
return (uint32_t)uCursorOffset;
}
}


Expand Down
186 changes: 164 additions & 22 deletions test/qcbor_decode_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -8929,8 +8929,8 @@ int32_t TellTests(void)
QCBORDecodeContext DCtx;
QCBORItem Item;
uint32_t uPosition;
int i;
int64_t n;
int nIndex;
int64_t nDecodedInt;

static const uint32_t aPos[] =
{0, 1, 17, 42, 50, 58, 72, 85, 98, 112, UINT32_MAX};
Expand All @@ -8943,10 +8943,10 @@ int32_t TellTests(void)
0);


for(i = 0; ; i++) {
for(nIndex = 0; ; nIndex++) {
uPosition = QCBORDecode_Tell(&DCtx);
if(uPosition != aPos[i]) {
return i;
if(uPosition != aPos[nIndex]) {
return nIndex;
}

if(uPosition == UINT32_MAX) {
Expand All @@ -8960,10 +8960,10 @@ int32_t TellTests(void)
UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapIndefEncoded),
0);

for(i = 0; ; i++) {
for(nIndex = 0; ; nIndex++) {
uPosition = QCBORDecode_Tell(&DCtx);
if(uPosition != aPosIndef[i]) {
return i + 100;
if(uPosition != aPosIndef[nIndex]) {
return nIndex + 100;
}

if(uPosition == UINT32_MAX) {
Expand All @@ -8979,45 +8979,187 @@ int32_t TellTests(void)
0);
QCBORDecode_EnterMap(&DCtx, &Item);
if(QCBORDecode_Tell(&DCtx) != 1) {
return 200;
return 1001;
}
QCBORDecode_GetInt64InMapSZ(&DCtx, "first integer", &n);
QCBORDecode_GetInt64InMapSZ(&DCtx, "first integer", &nDecodedInt);
if(QCBORDecode_Tell(&DCtx) != 1) {
return 200;
return 1002;
}
QCBORDecode_EnterMapFromMapSZ(&DCtx, "map in a map");
if(QCBORDecode_Tell(&DCtx) != 72) {
return 201;
return 1003;
}

QCBORDecode_GetInt64InMapSZ(&DCtx, "another int", &n);
if(n != 98) {
return 99;
QCBORDecode_GetInt64InMapSZ(&DCtx, "another int", &nDecodedInt);
if(nDecodedInt != 98) {
return 1004;
}
/* Getting non-aggregate types doesn't affect cursor position. */
if(QCBORDecode_Tell(&DCtx) != 72) {
return 200;
return 1005;
}
QCBORDecode_VGetNext(&DCtx, &Item);
if(QCBORDecode_Tell(&DCtx) != 85) {
return 202;
return 1006;
}
QCBORDecode_GetInt64InMapSZ(&DCtx, "another int", &n);
if(n != 98) {
return 99;
QCBORDecode_GetInt64InMapSZ(&DCtx, "another int", &nDecodedInt);
if(nDecodedInt != 98) {
return 1007;
}
/* Getting non-aggregate types doesn't affect cursor position. */
if(QCBORDecode_Tell(&DCtx) != 85) {
return 200;
return 1008;
}

QCBORDecode_ExitMap(&DCtx);
if(QCBORDecode_Tell(&DCtx) != UINT32_MAX) {
return 203;
return 1009;
}
if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_NO_MORE_ITEMS) {
return 1010;
}


/* Next, some tests with entered maps and arrays */
QCBORDecode_Init(&DCtx,
UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapIndefEncoded),
0);
QCBORDecode_EnterMap(&DCtx, &Item);
if(QCBORDecode_Tell(&DCtx) != 1) {
return 2000;
}
QCBORDecode_GetInt64InMapSZ(&DCtx, "first integer", &nDecodedInt);
if(QCBORDecode_Tell(&DCtx) != 1) {
return 2001;
}
QCBORDecode_EnterMapFromMapSZ(&DCtx, "map in a map");
if(QCBORDecode_Tell(&DCtx) != 73) {
return 2002;
}

QCBORDecode_GetInt64InMapSZ(&DCtx, "another int", &nDecodedInt);
if(nDecodedInt != 98) {
return 2003;
}
/* Getting non-aggregate types doesn't affect cursor position. */
if(QCBORDecode_Tell(&DCtx) != 73) {
return 2004;
}
QCBORDecode_VGetNext(&DCtx, &Item);
if(QCBORDecode_Tell(&DCtx) != 86) {
return 2005;
}
QCBORDecode_GetInt64InMapSZ(&DCtx, "another int", &nDecodedInt);
if(nDecodedInt != 98) {
return 2006;
}
/* Getting non-aggregate types doesn't affect cursor position. */
if(QCBORDecode_Tell(&DCtx) != 86) {
return 2007;
}

QCBORDecode_ExitMap(&DCtx);
if(QCBORDecode_Tell(&DCtx) != UINT32_MAX) {
return 2008;
}
if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_NO_MORE_ITEMS) {
return 2010;
}


/* Error state test */
QCBORDecode_Init(&DCtx,
UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded),
0);
/* Cause an error */
QCBORDecode_GetInt64InMapSZ(&DCtx, "another int", &nDecodedInt);
if(QCBORDecode_Tell(&DCtx) != UINT32_MAX) {
return 3000;
}

/* Empties tests */
const uint8_t pMinimalCBOR[] = {0xa0}; // One empty map
QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pMinimalCBOR),0);
if(QCBORDecode_Tell(&DCtx) != 0) {
return 4000;
}
QCBORDecode_EnterMap(&DCtx, &Item);
if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
return 4001;
}
if(QCBORDecode_Tell(&DCtx) != UINT32_MAX) {
return 4002;
}
QCBORDecode_ExitMap(&DCtx);
if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
return 4001;
}
if(QCBORDecode_Tell(&DCtx) != UINT32_MAX) {
return 4002;
}
if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_NO_MORE_ITEMS) {
return 4010;
}

const uint8_t pMinimalIndefCBOR[] = {0xbf, 0xff}; // One empty map
QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pMinimalIndefCBOR),0);
if(QCBORDecode_Tell(&DCtx) != 0) {
return 4100;
}
QCBORDecode_EnterMap(&DCtx, &Item);
if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
return 4101;
}
if(QCBORDecode_Tell(&DCtx) != UINT32_MAX) {
return 4102;
}
QCBORDecode_ExitMap(&DCtx);
if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
return 4101;
}
if(QCBORDecode_Tell(&DCtx) != UINT32_MAX) {
return 4102;
}
if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_NO_MORE_ITEMS) {
return 4110;
}

/* Test on a CBOR sequence */
QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSequenceTestInput),0);
if(QCBORDecode_Tell(&DCtx) != 0) {
return 5000;
}
QCBORDecode_VGetNext(&DCtx, &Item);
if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
return 5001;
}
if(QCBORDecode_Tell(&DCtx) != 11) {
return 5002;
}
QCBORDecode_VGetNext(&DCtx, &Item);
if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
return 5003;
}
if(QCBORDecode_Tell(&DCtx) != 12) {
return 5004;
}
QCBORDecode_VGetNext(&DCtx, &Item);
if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
return 5005;
}
if(QCBORDecode_Tell(&DCtx) != 17) {
return 5006;
}
QCBORDecode_VGetNext(&DCtx, &Item);
if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
return 5007;
}
if(QCBORDecode_Tell(&DCtx) != UINT32_MAX) {
return 5008;
}
if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_NO_MORE_ITEMS) {
return 5010;
}

return 0;
}

0 comments on commit 1d5fd83

Please sign in to comment.