rewinding wrapped byte strings works, but needs more tests
diff --git a/inc/qcbor/UsefulBuf.h b/inc/qcbor/UsefulBuf.h
index 6fe33a1..2e63e65 100644
--- a/inc/qcbor/UsefulBuf.h
+++ b/inc/qcbor/UsefulBuf.h
@@ -1,6 +1,6 @@
/*============================================================================
Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2020, Laurence Lundblade.
+ Copyright (c) 2018-2021, Laurence Lundblade.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -41,6 +41,7 @@
when who what, where, why
-------- ---- --------------------------------------------------
+ 2/17/2021 llundblade Method to go from a pointer to an offset.
1/25/2020 llundblade Add some casts so static anlyzers don't complain.
5/21/2019 llundblade #define configs for efficient endianness handling.
5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
@@ -589,6 +590,18 @@
size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
+/**
+@brief Convert a pointer to an offset with bounds checking.
+
+@param[in] UB Pointer to the UsefulInputBuf.
+@param[in] p Pointer to convert to offet.
+
+@return SIZE_MAX if @c p is out of range, offset if not.
+*/
+// TODO: test this
+static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
+
+
#if 1 // NOT_DEPRECATED
/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
#define SZLiteralToUsefulBufC(szString) \
@@ -1332,6 +1345,17 @@
/**
+@brief Convert a pointer to an offset with bounds checking.
+
+@param[in] pUInBuf Pointer to the UsefulInputBuf.
+@param[in] p Pointer to convert to offet.
+
+@return SIZE_MAX if @c p is out of range.
+*/
+static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
+
+
+/**
@brief Get pointer to bytes out of the input buffer.
@param[in] pUInBuf Pointer to the UsefulInputBuf.
@@ -1626,6 +1650,23 @@
}
+static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
+{
+ if(p < UB.ptr) {
+ /* given pointer is before start of buffer */
+ return SIZE_MAX;
+ }
+
+ ptrdiff_t nOffset = (uint8_t *)p - (uint8_t *)UB.ptr;
+
+ if(nOffset < 0) {
+ /* given pointer is of the end of the buffer */
+ return SIZE_MAX;
+ }
+
+ return (size_t)nOffset;
+}
+
static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
{
@@ -1993,6 +2034,12 @@
}
+static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
+{
+ return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
+}
+
+
static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
{
const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 2ad00b0..19c6a97 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -3522,8 +3522,14 @@
uError = QCBOR_ERR_INPUT_TOO_LARGE;
goto Done;
}
- const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
- const size_t uStartOfBstr = uEndOfBstr - pItem->val.string.len;
+ const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf), pItem->val.string.ptr);
+
+ if(uStartOfBstr == SIZE_MAX) {
+ uError = QCBOR_ERR_INPUT_TOO_LARGE;
+ goto Done;
+ }
+
+ const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index bce459d..62184a3 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -6984,10 +6984,38 @@
#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+/*
+An array of an integer and an array. The second array contains a bstr-wrapped map.
+
+ [7, [h'A36D666972737420696E7465676572182A77616E206172726179206F662074776F20737472696E67738267737472696E673167737472696E67326C6D617020696E2061206D6170A467627974657320314478787878676279746573203244797979796B616E6F7468657220696E74186266746578742032781E6C6965732C2064616D6E206C69657320616E642073746174697374696373']]
+
+ {"first integer": 42, "an array of two strings": ["string1", "string2"], "map in a map": {"bytes 1": h'78787878', "bytes 2": h'79797979', "another int": 98, "text 2": "lies, damn lies and statistics"}}
+ */
static const uint8_t pValidWrappedMapEncoded[] = {
- 0x82, 0x00, 0x81, 0x58, 0x97,
- // 0x9f, 0x00, 0x9f, 0x58, 0x97,
+0x82, 0x07, 0x81, 0x58, 0x97,
+0xa3, 0x6d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69, 0x6e,
+0x74, 0x65, 0x67, 0x65, 0x72, 0x18, 0x2a, 0x77, 0x61, 0x6e,
+0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20,
+0x74, 0x77, 0x6f, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+0x73, 0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31,
+0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x32, 0x6c, 0x6d,
+0x61, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x6d, 0x61,
+0x70, 0xa4, 0x67, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x31,
+0x44, 0x78, 0x78, 0x78, 0x78, 0x67, 0x62, 0x79, 0x74, 0x65,
+0x73, 0x20, 0x32, 0x44, 0x79, 0x79, 0x79, 0x79, 0x6b, 0x61,
+0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x74,
+0x18, 0x62, 0x66, 0x74, 0x65, 0x78, 0x74, 0x20, 0x32, 0x78,
+0x1e, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x6d,
+0x6e, 0x20, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64,
+0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63,
+0x73
+};
+
+
+/* As above, but the arrays are indefinite length */
+static const uint8_t pValidIndefWrappedMapEncoded[] = {
+0x9f, 0x07, 0x9f, 0x58, 0x97,
0xa3, 0x6d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69, 0x6e,
0x74, 0x65, 0x67, 0x65, 0x72, 0x18, 0x2a, 0x77, 0x61, 0x6e,
@@ -7464,5 +7492,35 @@
return 600;
}
+
+
+
+ QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidIndefWrappedMapEncoded), 0);
+
+ QCBORDecode_EnterArray(&DCtx, NULL);
+
+ QCBORDecode_GetUInt64(&DCtx, &i);
+
+ QCBORDecode_EnterArray(&DCtx, NULL);
+
+ QCBORDecode_EnterBstrWrapped(&DCtx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL);
+
+ if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+ return (int32_t)nCBORError;
+ }
+ if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 3) {
+ return 600;
+ }
+
+ QCBORDecode_Rewind(&DCtx);
+
+
+ if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+ return (int32_t)nCBORError;
+ }
+ if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 3) {
+ return 600;
+ }
+
return 0;
}