diff --git a/3rdparty/exported/QCBOR/CMakeLists.txt b/3rdparty/exported/QCBOR/CMakeLists.txt index f0b67b95531f..486946ce9e65 100644 --- a/3rdparty/exported/QCBOR/CMakeLists.txt +++ b/3rdparty/exported/QCBOR/CMakeLists.txt @@ -1,19 +1,77 @@ -cmake_minimum_required(VERSION 3.10.2) +#------------------------------------------------------------------------------- +# Copyright (c) 2022-2023, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# See BSD-3-Clause license in README.md +#------------------------------------------------------------------------------- + +cmake_minimum_required(VERSION 3.15) + project(qcbor - DESCRIPTION "QCBOR" - LANGUAGES C - VERSION 1.0.0) + DESCRIPTION "QCBOR" + LANGUAGES C + VERSION 1.1.0 +) + +set(BUILD_QCBOR_TEST "OFF" CACHE STRING "Build QCBOR test suite [OFF, LIB, APP]") +set(BUILD_QCBOR_WARN OFF CACHE BOOL "Compile with the warning flags used in the QCBOR release process") +# BUILD_SHARED_LIBS is a built-in global CMake flag +# The shared library is not made by default because of platform +# variability For example MacOS and Linux behave differently and some +# IoT OS's don't support them at all. +set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries instead of static ones") + +# Configuration: +# Floating-point support (see README.md for more information) +set(QCBOR_OPT_DISABLE_FLOAT_HW_USE OFF CACHE BOOL "Eliminate dependency on FP hardware and FP instructions") +set(QCBOR_OPT_DISABLE_FLOAT_PREFERRED OFF CACHE BOOL "Eliminate support for half-precision and CBOR preferred serialization") +set(QCBOR_OPT_DISABLE_FLOAT_ALL OFF CACHE BOOL "Eliminate floating-point support completely") + +if (BUILD_QCBOR_WARN) + # Compile options applying to all targets in current directory and below + add_compile_options(-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wcast-qual) +endif() + +add_library(qcbor) + +target_sources(qcbor + PRIVATE + src/ieee754.c + src/qcbor_decode.c + src/qcbor_encode.c + src/qcbor_err_to_str.c + src/UsefulBuf.c +) + +target_include_directories(qcbor + PUBLIC + inc + PRIVATE + src +) -set(CMAKE_C_FLAGS "-pedantic -Wall -O3 -ffunction-sections") +target_compile_definitions(qcbor + PRIVATE + $<$:QCBOR_DISABLE_FLOAT_HW_USE> + $<$:QCBOR_DISABLE_PREFERRED_FLOAT> + $<$:USEFULBUF_DISABLE_ALL_FLOAT> +) -set(SOURCE - src/ieee754.c - src/qcbor_decode.c - src/qcbor_encode.c - src/qcbor_err_to_str.c - src/UsefulBuf.c -) +if (BUILD_SHARED_LIBS) + target_compile_options(qcbor PRIVATE -Os -fPIC) +endif() -add_library(qcbor ${SOURCE}) +# The math library is needed for floating-point support. +# To avoid need for it #define QCBOR_DISABLE_FLOAT_HW_USE +if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + # Using GCC + target_link_libraries(qcbor + PRIVATE + $<$>:m> + ) +endif() -target_include_directories(qcbor PUBLIC inc) +if (NOT BUILD_QCBOR_TEST STREQUAL "OFF") + add_subdirectory(test) +endif() diff --git a/3rdparty/exported/QCBOR/Makefile b/3rdparty/exported/QCBOR/Makefile index a4fe2b5f65a2..d5d359b7121c 100644 --- a/3rdparty/exported/QCBOR/Makefile +++ b/3rdparty/exported/QCBOR/Makefile @@ -19,8 +19,8 @@ LIBS=-lm # The $(CMD_LINE) variable allows passing in extra flags. This is # used on the stringent build script that is in # https://github.com/laurencelundblade/qdv. This script is used -# before pushes to master (though not yet through and automated build -# process) +# before pushes to master (though not yet through an automated build +# process). See "warn:" below. CFLAGS=$(CMD_LINE) -I inc -I test -Os -fPIC @@ -30,7 +30,7 @@ TEST_OBJ=test/UsefulBuf_Tests.o test/qcbor_encode_tests.o \ test/qcbor_decode_tests.o test/run_tests.o \ test/float_tests.o test/half_to_double_from_rfc7049.o example.o ub-example.o -.PHONY: all so install uninstall clean +.PHONY: all so install uninstall clean warn all: qcbortest libqcbor.a @@ -42,6 +42,11 @@ qcbortest: libqcbor.a $(TEST_OBJ) cmd_line_main.o libqcbor.a: $(QCBOR_OBJ) ar -r $@ $^ +# run "make warn" as a handy way to compile with the warning flags +# used in the QCBOR release process. See CFLAGS above. +warn: + make CMD_LINE="-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wcast-qual" + # The shared library is not made by default because of platform # variability For example MacOS and Linux behave differently and some diff --git a/3rdparty/exported/QCBOR/README.md b/3rdparty/exported/QCBOR/README.md index d26c56c6f2f7..673e940e1469 100644 --- a/3rdparty/exported/QCBOR/README.md +++ b/3rdparty/exported/QCBOR/README.md @@ -12,7 +12,7 @@ Replaced by RFC 8949. ## QCBOR Characteristics -**Implemented in C with minimal dependency** – Dependent only +**Implemented in C with minimal dependency** – Dependent only on C99, , , and making it highly portable. and are used too, but their use can disabled. No #ifdefs or compiler options need to be set for @@ -34,7 +34,7 @@ Replaced by RFC 8949. encoded CBOR and encode/decode contexts so caller has full control of memory usage making it good for embedded implementations that have to run in small fixed memory. - + **Easy decoding of maps** – The "spiffy decode" functions allow fetching map items directly by label. Detection of duplicate map items is automatically performed. This makes decoding of complex @@ -93,7 +93,7 @@ implementations as seen in the following example. QCBOREncode_AddInt64ToMap(&EncodeCtx, "Horsepower", pE->uHorsePower); QCBOREncode_CloseMap(&EncodeCtx); uErr = QCBOREncode_Finish(&EncodeCtx, &EncodedEngine); - + /* Decode */ QCBORDecode_Init(&DecodeCtx, EncodedEngine, QCBOR_DECODE_MODE_NORMAL); QCBORDecode_EnterMap(&DecodeCtx); @@ -172,7 +172,7 @@ The current version is v1.1, a small feature addition and bug fix release over QCBOR 1.0. Code has been stable for over a year. The last major change was in -fall of 2020. +fall of 2020. QCBOR was originally developed by Qualcomm. It was [open sourced through CAF](https://source.codeaurora.org/quic/QCBOR/QCBOR/) with a @@ -181,7 +181,8 @@ permissive Linux license, September 2018 (thanks Qualcomm!). ## Building There is a simple makefile for the UNIX style command line binary that -compiles everything to run the tests. +compiles everything to run the tests. CMake is also available, please read +the "Building with CMake" section for more information. These eleven files, the contents of the src and inc directories, make up the entire implementation. @@ -213,14 +214,55 @@ RunTests() to invoke them all. While this code will run fine without configuration, there are several C pre processor macros that can be #defined in order to: - * use a more efficient implementation + * use a more efficient implementation * to reduce code size * to improve performance (a little) * remove features to reduce code size -See the comment sections on "Configuration" in inc/UsefulBuf.h and +See the comment sections on "Configuration" in inc/UsefulBuf.h and the pre processor defines that start with QCBOR_DISABLE_XXX. +### Building with CMake + +CMake can also be used to build QCBOR and the test application. Having the root +`CMakeLists.txt` file, QCBOR can be easily integrated with your project's +existing CMake environment. The result of the build process is a static library, +to build a shared library instead you must add the +`-DBUILD_SHARED_LIBS=ON` option at the CMake configuration step. +The tests can be built into a simple command line application to run them as it +was mentioned before; or it can be built as a library to be integrated with your +development environment. +The `BUILD_QCBOR_TEST` CMake option can be used for building the tests, it can +have three values: `APP`, `LIB` or `OFF` (default, test are not included in the +build). + +Building the QCBOR library: + +```bash +cd +# Configuring the project and generating a native build system +cmake -S . -B +# Building the project +cmake --build +``` + +Building and running the QCBOR test app: +```bash +cd +# Configuring the project and generating a native build system +cmake -S . -B -DBUILD_QCBOR_TEST=APP +# Building the project +cmake --build +# Running the test app +./test/qcbortest +``` + +To enable all the compiler warnings that are used in the QCBOR release process +you can use the `BUILD_QCBOR_WARN` option at the CMake configuration step: +```bash +cmake -S . -B -DBUILD_QCBOR_WARN=ON +``` + ### Floating Point Support & Configuration By default, all QCBOR floating-point features are enabled: @@ -238,7 +280,7 @@ used to reduce object code size and dependency. See discussion in qcbor_encode.h for other details. -### #define QCBOR_DISABLE_FLOAT_HW_USE +#### #define QCBOR_DISABLE_FLOAT_HW_USE This removes dependency on: @@ -278,7 +320,7 @@ This saves only a small amount of object code. The primary purpose for defining this is to remove dependency on floating point hardware and libraries. -#### #define QCBOR_DISABLE_PREFERRED_FLOAT +#### #define QCBOR_DISABLE_PREFERRED_FLOAT This eliminates support for half-precision and CBOR preferred serialization by disabling @@ -287,9 +329,9 @@ half-precision floating-point. With this defined, single and double-precision floating-point numbers can still be encoded and decoded. Conversion -of floating-point to and from integers, big numbers and +of floating-point to and from integers, big numbers and such is also supported. Floating-point dates are still -supported. +supported. The primary reason to define this is to save object code. Roughly 900 bytes are saved, though about half of this @@ -311,49 +353,61 @@ it is usually possible to give options to the compiler to avoid all floating-point hardware and instructions, to use software and replacement libraries instead. These are usually bigger and slower, but these options may still be useful -in getting QCBOR to run in some environments in +in getting QCBOR to run in some environments in combination with `QCBOR_DISABLE_FLOAT_HW_USE`. -In particular, `-mfloat-abi=soft`, disables use of +In particular, `-mfloat-abi=soft`, disables use of hardware instructions for the float and double - types in C for some architectures. + types in C for some architectures. + +#### CMake options + +If you are using CMake, it can also be used to configure the floating-point +support. These options can be enabled by adding them to the CMake configuration +step and setting their value to 'ON' (True). The following table shows the +available options and the associated #defines. + | CMake option | #define | + |-----------------------------------|-------------------------------| + | QCBOR_OPT_DISABLE_FLOAT_HW_USE | QCBOR_DISABLE_FLOAT_HW_USE | + | QCBOR_OPT_DISABLE_FLOAT_PREFERRED | QCBOR_DISABLE_PREFERRED_FLOAT | + | QCBOR_OPT_DISABLE_FLOAT_ALL | USEFULBUF_DISABLE_ALL_FLOAT | ## Code Size These are approximate sizes on a 64-bit x86 CPU with the -Os optimization. - | | smallest | largest | + | | smallest | largest | |---------------|----------|---------| - | encode only | 850 | 2100 | - | decode only | 2000 | 13300 | - | combined | 2850 | 15500 | - + | encode only | 900 | 2100 | + | decode only | 1550 | 13300 | + | combined | 2450 | 15500 | + From the table above, one can see that the amount of code pulled in from the QCBOR library varies a lot, ranging from 1KB to 15KB. The main factor is in this is the number of QCBOR functions called and which ones they are. QCBOR is constructed with less internal interdependency so only code necessary for the called functions is brought in. - + Encoding is simpler and smaller. An encode-only implementation may bring in only 1KB of code. - + Encoding of floating-point brings in a little more code as does encoding of tagged types and encoding of bstr wrapping. - + Basic decoding using QCBORDecode_GetNext() brings in 3KB. - + Use of the supplied MemPool by calling QCBORDecode_SetMemPool() to setup to decode indefinite-length strings adds 0.5KB. - + Basic use of spiffy decode to brings in about 3KB. Using more spiffy decode functions, such as those for tagged types bstr wrapping brings in more code. - + Finally, use of all of the integer conversion functions will bring in about 5KB, though you can use the simpler ones like QCBORDecode_GetInt64() without bringing in very much code. - + In addition to using fewer QCBOR functions, the following are some ways to make the code smaller. @@ -366,22 +420,23 @@ These are approximate sizes on a 64-bit x86 CPU with the -Os optimization. If QCBOR is installed as a shared library, then of course only one copy of the code is in memory no matter how many applications use it. - + ### Disabling Features Here's the list of all features that can be disabled to save object code. The amount saved is an approximation. - | #define | Saves | - | ----------------------------------------| ------| - | QCBOR_DISABLE_ENCODE_USAGE_GUARDS | 150 | - | QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS | 400 | - | QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS | 200 | - | QCBOR_DISABLE_UNCOMMON_TAGS | 100 | - | QCBOR_DISABLE_EXP_AND_MANTISSA | 400 | - | QCBOR_DISABLE_PREFERRED_FLOAT | 900 | - | QCBOR_DISABLE_FLOAT_HW_USE | 50 | - | USEFULBUF_DISABLE_ALL_FLOAT | 950 | + | #define | Saves | + | ----------------------------------------| ------| + | QCBOR_DISABLE_ENCODE_USAGE_GUARDS | 150 | + | QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS | 400 | + | QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS | 200 | + | QCBOR_DISABLE_UNCOMMON_TAGS | 100 | + | QCBOR_DISABLE_EXP_AND_MANTISSA | 400 | + | QCBOR_DISABLE_PREFERRED_FLOAT | 900 | + | QCBOR_DISABLE_FLOAT_HW_USE | 50 | + | QCBOR_DISABLE_TAGS | 400 | + | USEFULBUF_DISABLE_ALL_FLOAT | 950 | QCBOR_DISABLE_ENCODE_USAGE_GUARDS affects encoding only. It doesn't disable any encoding features, just some error checking. Disable it @@ -409,20 +464,25 @@ QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS which will result in an error when an indefinite-length map or array arrives for decoding. QCBOR_DISABLE_UNCOMMON_TAGS disables the decoding of explicit tags for -base 64, regex, UUID and MIME data. This just disabled the automatic +base 64, regex, UUID and MIME data. This just disables the automatic recognition of these from a major type 6 tag. QCBOR_DISABLE_EXP_AND_MANTISSA disables the decoding of decimal fractions and big floats. +QCBOR_DISABLE_TAGS disables all decoding of CBOR tags. If the input has +a single tag, the error is unrecoverable so it is suitable only for protocols that +have no tags. "Borrowed" tag content formats (e.g. an epoch-based date +without the tag number), can still be processed. + See the discussion above on floating-point. ### Size of spiffy decode - + When creating a decode implementation, there is a choice of whether or not to use spiffy decode features or to just use QCBORDecode_GetNext(). - + The implementation using spiffy decode will be simpler resulting in the calling code being smaller, but the amount of code brought in from the QCBOR library will be larger. Basic use of spiffy decode @@ -430,7 +490,7 @@ See the discussion above on floating-point. concern, then it is probably better to use spiffy decode because it is less work, there is less complexity and less testing to worry about. - + If code size is a concern, then use of QCBORDecode_GetNext() will probably result in smaller overall code size for simpler CBOR protocols. However, if the CBOR protocol is complex then use of @@ -440,13 +500,13 @@ See the discussion above on floating-point. because the general purpose spiffy decode map processor is the one used for all the maps. - + ## Other Software Using QCBOR * [t_cose](https://github.com/laurencelundblade/t_cose) implements enough of [COSE, RFC 8152](https://tools.ietf.org/html/rfc8152) to support [CBOR Web Token (CWT)](https://tools.ietf.org/html/rfc8392) and -[Entity Attestation Token (EAT)](https://tools.ietf.org/html/draft-ietf-rats-eat-06). +[Entity Attestation Token (EAT)](https://tools.ietf.org/html/draft-ietf-rats-eat-06). Specifically it supports signing and verification of the COSE_Sign1 message. * [ctoken](https://github.com/laurencelundblade/ctoken) is an implementation of @@ -504,4 +564,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ### Copyright for this README Copyright (c) 2018-2021, Laurence Lundblade. All rights reserved. -Copyright (c) 2021, Arm Limited. All rights reserved. +Copyright (c) 2021-2023, Arm Limited. All rights reserved. diff --git a/3rdparty/exported/QCBOR/example.c b/3rdparty/exported/QCBOR/example.c index 80b21494d554..d580c78f0056 100644 --- a/3rdparty/exported/QCBOR/example.c +++ b/3rdparty/exported/QCBOR/example.c @@ -307,7 +307,7 @@ EngineDecodeErrors DecodeEngineSpiffy(UsefulBufC EncodedEngine, CarEngine *pE) } -int32_t RunQCborExample() +int32_t RunQCborExample(void) { CarEngine InitialEngine; CarEngine DecodedEngine; diff --git a/3rdparty/exported/QCBOR/qcbor/UsefulBuf.h b/3rdparty/exported/QCBOR/qcbor/UsefulBuf.h index 8a101fd473cf..aa245070299a 100644 --- a/3rdparty/exported/QCBOR/qcbor/UsefulBuf.h +++ b/3rdparty/exported/QCBOR/qcbor/UsefulBuf.h @@ -42,6 +42,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. when who what, where, why -------- ---- -------------------------------------------------- + 19/12/2022 llundblade Document that adding empty data is allowed. 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf. 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions @@ -673,15 +674,8 @@ static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC) { UsefulBuf UB; - // See UsefulBuf_Unconst() implementation for comment on pragmas -#ifndef _MSC_VER -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif - UB.ptr = (void *)UBC.ptr; -#ifndef _MSC_VER -#pragma GCC diagnostic pop -#endif + // See UsefulBuf_Unconst() implementation for comment + UB.ptr = (void *)(uintptr_t)UBC.ptr; UB.len = UBC.len; @@ -954,6 +948,8 @@ static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf); * Overlapping buffers are OK. @c NewData can point to data in the * output buffer. * + * NewData.len may be 0 in which case nothing will be inserted. + * * If an error occurs, an error state is set in the @ref * UsefulOutBuf. No error is returned. All subsequent attempts to add * data will do nothing. @@ -1759,16 +1755,9 @@ static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC) UsefulBuf UB; /* -Wcast-qual is a good warning flag to use in general. This is - * the one place in UsefulBuf where it needs to be quieted. Since - * clang supports GCC pragmas, this works for clang too. */ -#ifndef _MSC_VER -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif - UB.ptr = (void *)UBC.ptr; -#ifndef _MSC_VER -#pragma GCC diagnostic pop -#endif + * the one place in UsefulBuf where it needs to be quieted. + */ + UB.ptr = (void *)(uintptr_t)UBC.ptr; UB.len = UBC.len; diff --git a/3rdparty/exported/QCBOR/qcbor/qcbor_common.h b/3rdparty/exported/QCBOR/qcbor/qcbor_common.h index e9f9a7c97b5c..127537d85322 100644 --- a/3rdparty/exported/QCBOR/qcbor/qcbor_common.h +++ b/3rdparty/exported/QCBOR/qcbor/qcbor_common.h @@ -468,6 +468,10 @@ typedef enum { indefinite length map or array in the input CBOR. */ QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED = 50, + /** All decoding of tags (major type 6) has been disabled and a tag + occurred in the decode input. */ + QCBOR_ERR_TAGS_DISABLED = 51, + #define QCBOR_END_OF_UNRECOVERABLE_DECODE_ERRORS 59 /** More than @ref QCBOR_MAX_TAGS_PER_ITEM tags encountered for a diff --git a/3rdparty/exported/QCBOR/qcbor/qcbor_decode.h b/3rdparty/exported/QCBOR/qcbor/qcbor_decode.h index 65eff4ca8d23..bf30e6ded32d 100644 --- a/3rdparty/exported/QCBOR/qcbor/qcbor_decode.h +++ b/3rdparty/exported/QCBOR/qcbor/qcbor_decode.h @@ -162,6 +162,23 @@ extern "C" { * item being sought, in which case the unrecoverable error will be * returned. Unrecoverable errors are those indicated by * QCBORDecode_IsUnrecoverableError(). + * + * @anchor Disabilng-Tag-Decoding + * # Disabilng Tag Decoding + * + * If QCBOR_DISABLE_TAGS is defined, all code for decoding tags will + * be omitted reducing the core decoder, QCBORDecode_VGetNext(), by + * about 400 bytes. If a tag number is encountered in the decoder + * input the unrecoverable error @ref QCBOR_ERR_TAGS_DISABLED will be + * returned. No input with tags can be decoded. + * + * Decode functions like QCBORDecode_GetEpochDate() and + * QCBORDecode_GetDecimalFraction() that can decode the tag content + * even if the tag number is absent are still available. Typically + * they won't be linked in because of dead stripping. The + * @c uTagRequirement parameter has no effect, but if it is + * @ref QCBOR_TAG_REQUIREMENT_TAG, @ref QCBOR_ERR_TAGS_DISABLED + * will be set. */ /** @@ -481,6 +498,7 @@ typedef struct _QCBORItem { uint64_t uint64; } label; +#ifndef QCBOR_DISABLE_TAGS /** * The tags numbers for which the item is the tag content. Tags * nest, so index 0 in the array is the tag on the data item @@ -502,6 +520,7 @@ typedef struct _QCBORItem { * having to reference this array. Also see @ref Tags-Overview. */ uint16_t uTags[QCBOR_MAX_TAGS_PER_ITEM]; +#endif } QCBORItem; diff --git a/3rdparty/exported/QCBOR/qcbor/qcbor_spiffy_decode.h b/3rdparty/exported/QCBOR/qcbor/qcbor_spiffy_decode.h index 91037822bcb9..0faddc386307 100644 --- a/3rdparty/exported/QCBOR/qcbor/qcbor_spiffy_decode.h +++ b/3rdparty/exported/QCBOR/qcbor/qcbor_spiffy_decode.h @@ -88,7 +88,7 @@ extern "C" { ## Tag Usage Data types beyond the basic CBOR types of numbers, strings, maps and - arrays are called tags. The main registry of these new types is in in + arrays are called tags. The main registry of these new types is in the IANA CBOR tags registry. These new types may be simple such a number that is to be interpreted as a date, or of moderate complexity such as defining a decimal fraction that is an array containing a @@ -296,6 +296,12 @@ static void QCBORDecode_GetInt64ConvertInMapSZ(QCBORDecodeContext *pCtx, See also QCBORDecode_GetInt64ConvertAll() which does some of these conversions, but links in much less object code. See also QCBORDecode_GetUInt64ConvertAll(). + + This relies on CBOR tags to identify big numbers, decimal fractions + and big floats. It will not attempt to decode non-tag CBOR that might + be one of these. (If QCBOR_DISABLE_TAGS is set, this is effectively + the same as QCBORDecode_GetInt64Convert() because all the additional + number types this decodes are tags). */ void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pCtx, uint32_t uConvertTypes, @@ -1210,6 +1216,10 @@ void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pCtx, See also @ref CBOR_TAG_DECIMAL_FRACTION, QCBOREncode_AddDecimalFraction(), @ref QCBOR_TYPE_DECIMAL_FRACTION and QCBORDecode_GetDecimalFractionBig(). + + If QCBOR_DISABLE_TAGS is set, the only input this will decode is + an array of two integers. It will set an error if the the array is preceded + by by a tag number or if the mantissa is a big number. */ void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, @@ -1297,6 +1307,10 @@ void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pCtx, mantissa * ( 2 ** exponent ) + If the mantissa is a tag that is a positive or negative big number, + this will attempt to fit it into the int64_t that @c pnMantissa is + and set an overflow error if it doesn't fit. + See also QCBORDecode_GetInt64ConvertAll(), QCBORDecode_GetUInt64ConvertAll() and QCBORDecode_GetDoubleConvertAll() which can convert big floats. @@ -1979,21 +1993,28 @@ QCBORDecode_GetDoubleInMapSZ(QCBORDecodeContext *pMe, -// Semi private (this may change in the future) #define QCBOR_TAGSPEC_NUM_TYPES 4 -/* Improvement: Carefully understand what compilers do with this, -particularly initialization and see if it can be optimized so -there is less code and maybe so it can be smaller. */ +/* Semi-private data structure (which might change). + * + * See CheckTagRequirement() which uses this to check the type of a + * item to be decoded as a tag or tag content. + * + * Improvement: Carefully understand what compilers do with this, + * particularly initialization and see if it can be optimized so there + * is less code and maybe so it can be smaller. + */ typedef struct { /* One of QCBOR_TAGSPEC_MATCH_xxx */ uint8_t uTagRequirement; - /* The tagged type translated into QCBOR_TYPE_XXX. Used to match explicit - tagging */ + /* The tagged type translated into QCBOR_TYPE_XXX. Used to match + * explicit tagging */ uint8_t uTaggedTypes[QCBOR_TAGSPEC_NUM_TYPES]; - /* The types of the content, which are used to match implicit tagging */ + /* The types of the content, which are used to match implicit + * tagging */ uint8_t uAllowedContentTypes[QCBOR_TAGSPEC_NUM_TYPES]; } TagSpecification; + // Semi private void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, diff --git a/3rdparty/exported/QCBOR/src/UsefulBuf.c b/3rdparty/exported/QCBOR/src/UsefulBuf.c index f5149a5a661a..b36e5d00d36d 100644 --- a/3rdparty/exported/QCBOR/src/UsefulBuf.c +++ b/3rdparty/exported/QCBOR/src/UsefulBuf.c @@ -41,7 +41,8 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. when who what, where, why -------- ---- --------------------------------------------------- - 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf + 19/12/2022 llundblade Don't pass NULL to memmove when adding empty data. + 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual 01/28/2020 llundblade Refine integer signedness to quiet static analysis. 01/08/2020 llundblade Documentation corrections & improved code formatting. @@ -254,22 +255,23 @@ void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t } /* 3. Slide existing data to the right */ - uint8_t *pSourceOfMove = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; // PtrMath #1 - size_t uNumBytesToMove = pMe->data_len - uInsertionPos; // PtrMath #2 - uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3 + if (!UsefulOutBuf_IsBufferNULL(pMe)) { + uint8_t *pSourceOfMove = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; // PtrMath #1 + size_t uNumBytesToMove = pMe->data_len - uInsertionPos; // PtrMath #2 + uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3 - if(uNumBytesToMove && pMe->UB.ptr) { // To know memmove won't go off end of destination, see PtrMath #4 // Use memove because it handles overlapping buffers memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove); - } - /* 4. Put the new data in */ - uint8_t *pInsertionPoint = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; // PtrMath #5 - if(pMe->UB.ptr) { - // To know memmove won't go off end of destination, see PtrMath #6 - memmove(pInsertionPoint, NewData.ptr, NewData.len); + /* 4. Put the new data in */ + uint8_t *pInsertionPoint = pSourceOfMove; + // To know memmove won't go off end of destination, see PtrMath #5 + if(NewData.ptr != NULL) { + memmove(pInsertionPoint, NewData.ptr, NewData.len); + } } + pMe->data_len += NewData.len; } @@ -295,9 +297,7 @@ void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos) This algebraically rearranges to me->size > uInsertionPos + NewData.len - PtrMath #5 is exactly the same as PtrMath #1 - - PtrMath #6 will never wrap under because + PtrMath #5 will never wrap under because Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos; Check #1 makes sure me->data_len is less than me->size Check #3 makes sure uInsertionPos is less than me->data_len diff --git a/3rdparty/exported/QCBOR/src/qcbor_decode.c b/3rdparty/exported/QCBOR/src/qcbor_decode.c index 46c4f126ad3c..8a547eef0a66 100644 --- a/3rdparty/exported/QCBOR/src/qcbor_decode.c +++ b/3rdparty/exported/QCBOR/src/qcbor_decode.c @@ -501,18 +501,11 @@ DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe) static inline void StringAllocator_Free(const QCBORInternalAllocator *pMe, const void *pMem) { - /* These pragmas allow the "-Wcast-qual" warnings flag to be set for - * gcc and clang. This is the one place where the const needs to be - * cast away so const can be use in the rest of the code. + /* This cast to uintptr_t suppresses the "-Wcast-qual" warnings. + * This is the one place where the const needs to be cast away so const can + * be use in the rest of the code. */ -#ifndef _MSC_VER -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif - (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)pMem, 0); -#ifndef _MSC_VER -#pragma GCC diagnostic pop -#endif + (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, 0); } // StringAllocator_Reallocate called with pMem NULL is @@ -523,14 +516,7 @@ StringAllocator_Reallocate(const QCBORInternalAllocator *pMe, size_t uSize) { /* See comment in StringAllocator_Free() */ -#ifndef _MSC_VER -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif - return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)pMem, uSize); -#ifndef _MSC_VER -#pragma GCC diagnostic pop -#endif + return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, uSize); } static inline UsefulBuf @@ -543,16 +529,9 @@ static inline void StringAllocator_Destruct(const QCBORInternalAllocator *pMe) { /* See comment in StringAllocator_Free() */ -#ifndef _MSC_VER -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif if(pMe->pfAllocator) { (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0); } -#ifndef _MSC_VER -#pragma GCC diagnostic pop -#endif } #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ @@ -1163,12 +1142,16 @@ DecodeAtomicDataItem(UsefulInputBuf *pUInBuf, break; case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */ +#ifndef QCBOR_DISABLE_TAGS if(nAdditionalInfo == LEN_IS_INDEFINITE) { uReturn = QCBOR_ERR_BAD_INT; } else { pDecodedItem->val.uTagV = uArgument; pDecodedItem->uDataType = QCBOR_TYPE_TAG; } +#else /* QCBOR_DISABLE_TAGS */ + uReturn = QCBOR_ERR_TAGS_DISABLED; +#endif /* QCBOR_DISABLE_TAGS */ break; case CBOR_MAJOR_TYPE_SIMPLE: @@ -1347,6 +1330,7 @@ QCBORDecode_GetNextFullString(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem) } +#ifndef QCBOR_DISABLE_TAGS /** * @brief This converts a tag number to a shorter mapped value for storage. * @@ -1421,6 +1405,7 @@ UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber) return pMe->auMappedTags[uIndex]; } } +#endif /* QCBOR_DISABLE_TAGS */ /** @@ -1450,6 +1435,7 @@ UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber) static QCBORError QCBORDecode_GetNextTagNumber(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem) { +#ifndef QCBOR_DISABLE_TAGS /* Accummulate the tags from multiple items here and then copy them * into the last item, the non-tag item. */ @@ -1508,8 +1494,13 @@ QCBORDecode_GetNextTagNumber(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem) Done: return uReturn; -} +#else /* QCBOR_DISABLE_TAGS */ + + return QCBORDecode_GetNextFullString(pMe, pDecodedItem); + +#endif /* QCBOR_DISABLE_TAGS */ +} /** * @brief Combine a map entry label and value into one item (decode layer 3). @@ -1900,6 +1891,7 @@ QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem) } +#ifndef QCBOR_DISABLE_TAGS /** * @brief Shift 0th tag out of the tag list. * @@ -1916,6 +1908,7 @@ static inline void ShiftTags(QCBORItem *pDecodedItem) pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16; } +#endif /* QCBOR_DISABLE_TAGS */ /** * @brief Convert different epoch date formats in to the QCBOR epoch date format @@ -2074,6 +2067,18 @@ static QCBORError DecodeDaysEpoch(QCBORItem *pDecodedItem) #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA + +/* Forward declaration is necessary for + * QCBORDecode_MantissaAndExponent(). to be able to decode bignum + * tags in the mantissa. If the mantissa is a decimal fraction or big + * float in error, this will result in a recurive call to + * QCBORDecode_MantissaAndExponent(), but the recursion will unwined + * correctly and the correct error is returned. + */ +static QCBORError +QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem); + + /** * @brief Decode decimal fractions and big floats. * @@ -2086,14 +2091,19 @@ static QCBORError DecodeDaysEpoch(QCBORItem *pDecodedItem) * @returns Decoding errors from getting primitive data items or * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA. * - * When called pDecodedItem must be the array that is tagged as a big - * float or decimal fraction, the array that has the two members, the + * When called pDecodedItem must be the array with two members, the * exponent and mantissa. * * This will fetch and decode the exponent and mantissa and put the * result back into pDecodedItem. + * + * This does no checking or processing of tag numbers. That is to be + * done by the code that calls this. + * + * This stuffs the type of the mantissa into pDecodedItem with the expectation + * the caller will process it. */ -static inline QCBORError +static QCBORError QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem) { QCBORError uReturn; @@ -2105,16 +2115,12 @@ QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem } /* A check for pDecodedItem->val.uCount == 2 would work for - * definite-length arrays, but not for indefnite. Instead remember + * definite-length arrays, but not for indefinite. Instead remember * the nesting level the two integers must be at, which is one * deeper than that of the array. */ const int nNestLevel = pDecodedItem->uNestingLevel + 1; - /* --- Which is it, decimal fraction or a bigfloat? --- */ - const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(pMe, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION); - pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT; - /* --- Get the exponent --- */ QCBORItem exponentItem; uReturn = QCBORDecode_GetNextMapOrArray(pMe, &exponentItem); @@ -2142,7 +2148,7 @@ QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem /* --- Get the mantissa --- */ QCBORItem mantissaItem; - uReturn = QCBORDecode_GetNextWithTags(pMe, &mantissaItem, NULL); + uReturn = QCBORDecode_GetNextTagContent(pMe, &mantissaItem); if(uReturn != QCBOR_SUCCESS) { goto Done; } @@ -2151,6 +2157,9 @@ QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA; goto Done; } + /* Stuff the mantissa data type into the item to send it up to the + * the next level. */ + pDecodedItem->uDataType = mantissaItem.uDataType; if(mantissaItem.uDataType == QCBOR_TYPE_INT64) { /* Data arriving as an unsigned int < INT64_MAX has been * converted to QCBOR_TYPE_INT64 and thus handled here. This is @@ -2159,14 +2168,16 @@ QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem * and thus an error that will get handled in an else below. */ pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64; +#ifndef QCBOR_DISABLE_TAGS + /* With tags fully disabled a big number mantissa will error out + * in the call to QCBORDecode_GetNextWithTags() because it has + * a tag number. + */ } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) { /* Got a good big num mantissa */ pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum; - /* Depends on numbering of QCBOR_TYPE_XXX */ - pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType + - mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM + - 1); +#endif /* QCBOR_DISABLE_TAGS */ } else { /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */ uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA; @@ -2176,6 +2187,7 @@ QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem /* --- Check that array only has the two numbers --- */ if(mantissaItem.uNextNestLevel == nNestLevel) { /* Extra items in the decimal fraction / big float */ + /* Improvement: this should probably be an unrecoverable error. */ uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA; goto Done; } @@ -2187,6 +2199,8 @@ QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */ +#ifndef QCBOR_DISABLE_TAGS + #ifndef QCBOR_DISABLE_UNCOMMON_TAGS /** * @brief Decode the MIME type tag @@ -2215,7 +2229,6 @@ static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem) } #endif /* QCBOR_DISABLE_UNCOMMON_TAGS */ - /** * Table of CBOR tags whose content is either a text string or a byte * string. The table maps the CBOR tag to the QCBOR type. The high-bit @@ -2303,6 +2316,31 @@ ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem) pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK); return QCBOR_SUCCESS; } +#endif /* QCBOR_DISABLE_TAGS */ + + +#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA +/* + * This returns the QCBOR_TYPE for a mantissa and exponent. + +Called in one context where there is always a tag + + Called in another context where there might be a tag or the caller might say what they are expecting. + + 6 possible outputs + */ +static inline uint8_t +MantissaExponentDataType(const uint16_t uTagToProcess, const QCBORItem *pDecodedItem) +{ + uint8_t uBase = uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ? + QCBOR_TYPE_DECIMAL_FRACTION : + QCBOR_TYPE_BIGFLOAT; + if(pDecodedItem->uDataType != QCBOR_TYPE_INT64) { + uBase = (uint8_t)(uBase + pDecodedItem->uDataType - QCBOR_TYPE_POSBIGNUM + 1); + } + return uBase; +} +#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */ /** @@ -2328,6 +2366,7 @@ QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem) goto Done; } +#ifndef QCBOR_DISABLE_TAGS /* When there are no tag numbers for the item, this exits first * thing and effectively does nothing. * @@ -2357,6 +2396,9 @@ QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem) } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION || uTagToProcess == CBOR_TAG_BIGFLOAT) { uReturn = QCBORDecode_MantissaAndExponent(pMe, pDecodedItem); + /* --- Which is it, decimal fraction or a bigfloat? --- */ + pDecodedItem->uDataType = MantissaExponentDataType(uTagToProcess, pDecodedItem); + #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */ #ifndef QCBOR_DISABLE_UNCOMMON_TAGS } else if(uTagToProcess == CBOR_TAG_MIME || @@ -2388,6 +2430,7 @@ QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem) */ ShiftTags(pDecodedItem); } +#endif /* QCBOR_DISABLE_TAGS */ Done: return uReturn; @@ -2463,6 +2506,8 @@ QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem, QCBORTagListOut *pTags) { +#ifndef QCBOR_DISABLE_TAGS + QCBORError uReturn; uReturn = QCBORDecode_GetNext(pMe, pDecodedItem); @@ -2486,6 +2531,13 @@ QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe, } return QCBOR_SUCCESS; + +#else /* QCBOR_DISABLE_TAGS */ + (void)pMe; + (void)pDecodedItem; + (void)pTags; + return QCBOR_ERR_TAGS_DISABLED; +#endif /* QCBOR_DISABLE_TAGS */ } @@ -2496,6 +2548,7 @@ bool QCBORDecode_IsTagged(QCBORDecodeContext *pMe, const QCBORItem *pItem, uint64_t uTag) { +#ifndef QCBOR_DISABLE_TAGS for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) { if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) { break; @@ -2504,6 +2557,11 @@ bool QCBORDecode_IsTagged(QCBORDecodeContext *pMe, return true; } } +#else /* QCBOR_TAGS_DISABLED */ + (void)pMe; + (void)pItem; + (void)uTag; +#endif /* QCBOR_TAGS_DISABLED */ return false; } @@ -2564,6 +2622,7 @@ uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe, const QCBORItem *pItem, uint32_t uIndex) { +#ifndef QCBOR_DISABLE_TAGS if(pItem->uDataType == QCBOR_TYPE_NONE) { return CBOR_TAG_INVALID64; } @@ -2572,6 +2631,13 @@ uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe, } else { return UnMapTagNumber(pMe, pItem->uTags[uIndex]); } +#else /* QCBOR_DISABLE_TAGS */ + (void)pMe; + (void)pItem; + (void)uIndex; + + return CBOR_TAG_INVALID64; +#endif /* QCBOR_DISABLE_TAGS */ } @@ -2581,6 +2647,8 @@ uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe, uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe, uint32_t uIndex) { +#ifndef QCBOR_DISABLE_TAGS + if(pMe->uLastError != QCBOR_SUCCESS) { return CBOR_TAG_INVALID64; } @@ -2589,6 +2657,12 @@ uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe, } else { return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]); } +#else /* QCBOR_DISABLE_TAGS */ + (void)pMe; + (void)uIndex; + + return CBOR_TAG_INVALID64; +#endif /* QCBOR_DISABLE_TAGS */ } @@ -2784,9 +2858,15 @@ QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe, -static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem) +static inline void +CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem) { +#ifndef QCBOR_DISABLE_TAGS memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags)); +#else + (void)pMe; + (void)pItem; +#endif } @@ -3224,7 +3304,6 @@ void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe, } - static QCBORError CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES]) { @@ -3238,30 +3317,47 @@ CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES]) /** - @param[in] TagSpec Specification for matching tags. - @param[in] pItem The item to check. - - @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec - @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec - - The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered - tag value. + * Match a tag/type specification against the type of the item. + * + * @param[in] TagSpec Specification for matching tags. + * @param[in] pItem The item to check. + * + * @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec + * @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec + * + * This checks the item data type of untagged items as well as of + * tagged items against a specification to see if decoding should + * proceed. + * + * This relies on the automatic tag decoding done by QCBOR that turns + * tag numbers into particular QCBOR_TYPEs so there is no actual + * comparsion of tag numbers, just of QCBOR_TYPEs. + * + * This checks the data item type as possibly representing the tag + * number or as the tag content type. + * + * If QCBOR_DISABLE_TAGS is #defined, this primarily checks the item + * data type against the allowed tag content types. It will also error out + * if the caller tries to require a tag because there is no way that can + * ever be fulfilled. */ static QCBORError CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem) { + const int nItemType = pItem->uDataType; + const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS; + +#ifndef QCBOR_DISABLE_TAGS if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) && pItem->uTags[0] != CBOR_TAG_INVALID16) { /* There are tags that QCBOR couldn't process on this item and - the caller has told us there should not be. */ + * the caller has told us there should not be. + */ return QCBOR_ERR_UNEXPECTED_TYPE; } - const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS; - const int nItemType = pItem->uDataType; - if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) { - // Must match the tag and only the tag + /* Must match the tag number and only the tag */ return CheckTypeList(nItemType, TagSpec.uTaggedTypes); } @@ -3272,26 +3368,35 @@ CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem) if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) { /* Must match the content type and only the content type. - There was no match just above so it is a fail. */ + * There was no match just above so it is a fail. */ return QCBOR_ERR_UNEXPECTED_TYPE; } - /* If here it can match either the tag or the content - and it hasn't matched the content, so the end - result is whether it matches the tag. This is - also the case that the CBOR standard discourages. */ + /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either the tag or the content + * and it hasn't matched the content, so the end + * result is whether it matches the tag. This is + * the tag optional case that the CBOR standard discourages. + */ return CheckTypeList(nItemType, TagSpec.uTaggedTypes); -} +#else /* QCBOR_DISABLE_TAGS */ + if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) { + return QCBOR_ERR_UNEXPECTED_TYPE; + } + + return CheckTypeList(nItemType, TagSpec.uAllowedContentTypes); + +#endif /* QCBOR_DISABLE_TAGS */ +} // This could be semi-private if need be static inline -void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe, - int64_t nLabel, - TagSpecification TagSpec, - QCBORItem *pItem) +void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe, + const int64_t nLabel, + const TagSpecification TagSpec, + QCBORItem *pItem) { QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem); if(pMe->uLastError != QCBOR_SUCCESS) { @@ -3304,10 +3409,10 @@ void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe, // This could be semi-private if need be static inline -void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe, - const char *szLabel, - TagSpecification TagSpec, - QCBORItem *pItem) +void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe, + const char *szLabel, + const TagSpecification TagSpec, + QCBORItem *pItem) { QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem); if(pMe->uLastError != QCBOR_SUCCESS) { @@ -3321,7 +3426,7 @@ void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe, void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe, int64_t nLabel, TagSpecification TagSpec, - UsefulBufC *pString) + UsefulBufC *pString) { QCBORItem Item; QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item); @@ -3631,10 +3736,11 @@ void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType) -static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe, - const QCBORItem *pItem, - uint8_t uTagRequirement, - UsefulBufC *pBstr) +static QCBORError +InternalEnterBstrWrapped(QCBORDecodeContext *pMe, + const QCBORItem *pItem, + const uint8_t uTagRequirement, + UsefulBufC *pBstr) { if(pBstr) { *pBstr = NULLUsefulBufC; @@ -3875,7 +3981,7 @@ void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bo static void ProcessEpochDate(QCBORDecodeContext *pMe, QCBORItem *pItem, - uint8_t uTagRequirement, + const uint8_t uTagRequirement, int64_t *pnTime) { if(pMe->uLastError != QCBOR_SUCCESS) { @@ -4054,13 +4160,16 @@ QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe, - -void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, - TagSpecification TagSpec, - UsefulBufC *pBstr) +/* + * @brief Get a string that matches the type/tag specification. + */ +void +QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, + const TagSpecification TagSpec, + UsefulBufC *pBstr) { if(pMe->uLastError != QCBOR_SUCCESS) { - // Already in error state, do nothing + /* Already in error state, do nothing */ return; } @@ -4085,10 +4194,11 @@ void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, -static QCBORError ProcessBigNum(uint8_t uTagRequirement, - const QCBORItem *pItem, - UsefulBufC *pValue, - bool *pbIsNegative) +static QCBORError +ProcessBigNum(const uint8_t uTagRequirement, + const QCBORItem *pItem, + UsefulBufC *pValue, + bool *pbIsNegative) { const TagSpecification TagSpec = { @@ -4179,10 +4289,11 @@ void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe, // Semi private -QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement, - const QCBORItem *pItem, - UsefulBufC *pMessage, - bool *pbIsTag257) +QCBORError +QCBORDecode_GetMIMEInternal(const uint8_t uTagRequirement, + const QCBORItem *pItem, + UsefulBufC *pMessage, + bool *pbIsTag257) { const TagSpecification TagSpecText = { @@ -4230,7 +4341,20 @@ QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement, typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult); -// The exponentiator that works on only positive numbers +/** + * @brief Base 10 exponentiate a mantissa and exponent into an unsigned 64-bit integer. + * + * @param[in] uMantissa The unsigned integer mantissa. + * @param[in] nExponent The signed integer exponent. + * @param[out] puResult Place to return the unsigned integer result. + * + * This computes: mantissa * 10 ^^ exponent as for a decimal fraction. The output is a 64-bit + * unsigned integer. + * + * There are many inputs for which the result will not fit in the + * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will + * be returned. + */ static QCBORError Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult) { @@ -4243,7 +4367,7 @@ Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult) */ for(; nExponent > 0; nExponent--) { if(uResult > UINT64_MAX / 10) { - return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow + return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; } uResult = uResult * 10; } @@ -4251,7 +4375,7 @@ Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult) for(; nExponent < 0; nExponent++) { uResult = uResult / 10; if(uResult == 0) { - return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error + return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; } } } @@ -4263,7 +4387,20 @@ Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult) } -// The exponentiator that works on only positive numbers +/** + * @brief Base 2 exponentiate a mantissa and exponent into an unsigned 64-bit integer. + * + * @param[in] uMantissa The unsigned integer mantissa. + * @param[in] nExponent The signed integer exponent. + * @param[out] puResult Place to return the unsigned integer result. + * + * This computes: mantissa * 2 ^^ exponent as for a big float. The + * output is a 64-bit unsigned integer. + * + * There are many inputs for which the result will not fit in the + * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will + * be returned. + */ static QCBORError Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult) { @@ -4271,13 +4408,12 @@ Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult) uResult = uMantissa; - /* This loop will run a maximum of 64 times because - * INT64_MAX < 2^31. More than that will cause - * exit with the overflow error + /* This loop will run a maximum of 64 times because INT64_MAX < + * 2^31. More than that will cause exit with the overflow error */ while(nExponent > 0) { if(uResult > UINT64_MAX >> 1) { - return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow + return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; } uResult = uResult << 1; nExponent--; @@ -4285,7 +4421,7 @@ Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult) while(nExponent < 0 ) { if(uResult == 0) { - return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error + return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; } uResult = uResult >> 1; nExponent++; @@ -4297,77 +4433,145 @@ Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult) } -/* - Compute value with signed mantissa and signed result. Works with - exponent of 2 or 10 based on exponentiator. +/** + * @brief Exponentiate a signed mantissa and signed exponent to produce a signed result. + * + * @param[in] nMantissa Signed integer mantissa. + * @param[in] nExponent Signed integer exponent. + * @param[out] pnResult Place to put the signed integer result. + * @param[in] pfExp Exponentiation function. + * + * @returns Error code + * + * \c pfExp performs exponentiation on and unsigned mantissa and + * produces an unsigned result. This converts the mantissa from signed + * and converts the result to signed. The exponentiation function is + * either for base 2 or base 10 (and could be other if needed). */ -static inline QCBORError ExponentiateNN(int64_t nMantissa, - int64_t nExponent, - int64_t *pnResult, - fExponentiator pfExp) +static QCBORError +ExponentiateNN(int64_t nMantissa, + int64_t nExponent, + int64_t *pnResult, + fExponentiator pfExp) { uint64_t uResult; + uint64_t uMantissa; - // Take the absolute value of the mantissa and convert to unsigned. - // Improvement: this should be possible in one instruction - uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa; + /* Take the absolute value and put it into an unsigned. */ + if(nMantissa >= 0) { + /* Positive case is straightforward */ + uMantissa = (uint64_t)nMantissa; + } else if(nMantissa != INT64_MIN) { + /* The common negative case. See next. */ + uMantissa = (uint64_t)-nMantissa; + } else { + /* int64_t and uint64_t are always two's complement per the + * C standard (and since QCBOR uses these it only works with + * two's complement, which is pretty much universal these + * days). The range of a negative two's complement integer is + * one more that than a positive, so the simple code above might + * not work all the time because you can't simply negate the + * value INT64_MIN because it can't be represented in an + * int64_t. -INT64_MIN can however be represented in a + * uint64_t. Some compilers seem to recognize this case for the + * above code and put the correct value in uMantissa, however + * they are not required to do this by the C standard. This next + * line does however work for all compilers. + * + * This does assume two's complement where -INT64_MIN == + * INT64_MAX + 1 (which wouldn't be true for one's complement or + * sign and magnitude (but we know we're using two's complement + * because int64_t requires it)). + * + * See these, particularly the detailed commentary: + * https://stackoverflow.com/questions/54915742/does-c99-mandate-a-int64-t-type-be-available-always + * https://stackoverflow.com/questions/37301078/is-negating-int-min-undefined-behaviour + */ + uMantissa = (uint64_t)INT64_MAX+1; + } - // Do the exponentiation of the positive mantissa + /* Call the exponentiator passed for either base 2 or base 10. + * Here is where most of the overflow errors are caught. */ QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult); if(uReturn) { return uReturn; } - - /* (uint64_t)INT64_MAX+1 is used to represent the absolute value - of INT64_MIN. This assumes two's compliment representation where - INT64_MIN is one increment farther from 0 than INT64_MAX. - Trying to write -INT64_MIN doesn't work to get this because the - compiler tries to work with an int64_t which can't represent - -INT64_MIN. - */ - uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1; - - // Error out if too large - if(uResult > uMax) { - return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; + /* Convert back to the sign of the original mantissa */ + if(nMantissa >= 0) { + if(uResult > INT64_MAX) { + return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; + } + *pnResult = (int64_t)uResult; + } else { + /* (uint64_t)INT64_MAX+1 is used to represent the absolute value + * of INT64_MIN. This assumes two's compliment representation + * where INT64_MIN is one increment farther from 0 than + * INT64_MAX. Trying to write -INT64_MIN doesn't work to get + * this because the compiler makes it an int64_t which can't + * represent -INT64_MIN. Also see above. + */ + if(uResult > (uint64_t)INT64_MAX+1) { + return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; + } + *pnResult = -(int64_t)uResult; } - // Casts are safe because of checks above - *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult; - return QCBOR_SUCCESS; } -/* - Compute value with signed mantissa and unsigned result. Works with - exponent of 2 or 10 based on exponentiator. +/** + * @brief Exponentiate an unsigned mantissa and signed exponent to produce an unsigned result. + * + * @param[in] nMantissa Signed integer mantissa. + * @param[in] nExponent Signed integer exponent. + * @param[out] puResult Place to put the signed integer result. + * @param[in] pfExp Exponentiation function. + * + * @returns Error code + * + * \c pfExp performs exponentiation on and unsigned mantissa and + * produces an unsigned result. This errors out if the mantissa + * is negative because the output is unsigned. */ -static inline QCBORError ExponentitateNU(int64_t nMantissa, - int64_t nExponent, - uint64_t *puResult, - fExponentiator pfExp) +static QCBORError +ExponentitateNU(int64_t nMantissa, + int64_t nExponent, + uint64_t *puResult, + fExponentiator pfExp) { if(nMantissa < 0) { return QCBOR_ERR_NUMBER_SIGN_CONVERSION; } - // Cast to unsigned is OK because of check for negative - // Cast to unsigned is OK because UINT64_MAX > INT64_MAX - // Exponentiation is straight forward + /* Cast to unsigned is OK because of check for negative. + * Cast to unsigned is OK because UINT64_MAX > INT64_MAX. + * Exponentiation is straight forward + */ return (*pfExp)((uint64_t)nMantissa, nExponent, puResult); } -/* - Compute value with signed mantissa and unsigned result. Works with - exponent of 2 or 10 based on exponentiator. +/** + * @brief Exponentiate an usnigned mantissa and unsigned exponent to produce an unsigned result. + * + * @param[in] uMantissa Unsigned integer mantissa. + * @param[in] nExponent Unsigned integer exponent. + * @param[out] puResult Place to put the unsigned integer result. + * @param[in] pfExp Exponentiation function. + * + * @returns Error code + * + * \c pfExp performs exponentiation on and unsigned mantissa and + * produces an unsigned result so this is just a wrapper that does + * nothing (and is likely inlined). */ -static inline QCBORError ExponentitateUU(uint64_t uMantissa, - int64_t nExponent, - uint64_t *puResult, - fExponentiator pfExp) +static QCBORError +ExponentitateUU(uint64_t uMantissa, + int64_t nExponent, + uint64_t *puResult, + fExponentiator pfExp) { return (*pfExp)(uMantissa, nExponent, puResult); } @@ -4377,8 +4581,20 @@ static inline QCBORError ExponentitateUU(uint64_t uMantissa, - -static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult) +/** + * @brief Convert a CBOR big number to a uint64_t. + * + * @param[in] BigNum Bytes of the big number to convert. + * @param[in] uMax Maximum value allowed for the result. + * @param[out] pResult Place to put the unsigned integer result. + * + * @returns Error code + * + * Many values will overflow because a big num can represent a much + * larger range than uint64_t. + */ +static QCBORError +ConvertBigNumToUnsigned(const UsefulBufC BigNum, const uint64_t uMax, uint64_t *pResult) { uint64_t uResult; @@ -4397,49 +4613,85 @@ static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax } -static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult) +/** + * @brief Convert a CBOR postive big number to a uint64_t. + * + * @param[in] BigNum Bytes of the big number to convert. + * @param[out] pResult Place to put the unsigned integer result. + * + * @returns Error code + * + * Many values will overflow because a big num can represent a much + * larger range than uint64_t. + */ +static QCBORError +ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult) { return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult); } -static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult) +/** + * @brief Convert a CBOR positive big number to an int64_t. + * + * @param[in] BigNum Bytes of the big number to convert. + * @param[out] pResult Place to put the signed integer result. + * + * @returns Error code + * + * Many values will overflow because a big num can represent a much + * larger range than int64_t. + */ +static QCBORError +ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult) { uint64_t uResult; - QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult); + QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult); if(uError) { return uError; } - /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */ + /* Cast is safe because ConvertBigNumToUnsigned is told to limit to INT64_MAX */ *pResult = (int64_t)uResult; return QCBOR_SUCCESS; } -static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult) +/** + * @brief Convert a CBOR negative big number to an int64_t. + * + * @param[in] BigNum Bytes of the big number to convert. + * @param[out] pnResult Place to put the signed integer result. + * + * @returns Error code + * + * Many values will overflow because a big num can represent a much + * larger range than int64_t. + */ +static QCBORError +ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult) { uint64_t uResult; /* The negative integer furthest from zero for a C int64_t is - INT64_MIN which is expressed as -INT64_MAX - 1. The value of a - negative number in CBOR is computed as -n - 1 where n is the - encoded integer, where n is what is in the variable BigNum. When - converting BigNum to a uint64_t, the maximum value is thus - INT64_MAX, so that when it -n - 1 is applied to it the result will - never be further from 0 than INT64_MIN. - - -n - 1 <= INT64_MIN. - -n - 1 <= -INT64_MAX - 1 - n <= INT64_MAX. + * INT64_MIN which is expressed as -INT64_MAX - 1. The value of a + * negative number in CBOR is computed as -n - 1 where n is the + * encoded integer, where n is what is in the variable BigNum. When + * converting BigNum to a uint64_t, the maximum value is thus + * INT64_MAX, so that when it -n - 1 is applied to it the result + * will never be further from 0 than INT64_MIN. + * + * -n - 1 <= INT64_MIN. + * -n - 1 <= -INT64_MAX - 1 + * n <= INT64_MAX. */ QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult); if(uError != QCBOR_SUCCESS) { return uError; } - /// Now apply -n - 1. The cast is safe because - // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit - // is the largest positive integer that an int64_t can - // represent. */ + /* Now apply -n - 1. The cast is safe because + * ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit + * is the largest positive integer that an int64_t can + * represent. */ *pnResult = -(int64_t)uResult - 1; return QCBOR_SUCCESS; @@ -5469,38 +5721,105 @@ static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer) } -static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe, - TagSpecification TagSpec, - QCBORItem *pItem) +/** + * @brief Check and/or complete mantissa and exponent item. + * + * @param[in] pMe The decoder context + * @param[in] TagSpec Expected type(s) + * @param[in,out] pItem See below + * + * This is for decimal fractions and big floats, both of which are a + * mantissa and exponent. + * + * The input item is either a fully decoded decimal faction or big + * float, or a just the decoded first item of a decimal fraction or + * big float. + * + * On output, the item is always a fully decoded decimal fraction or + * big float. + * + * This errors out if the input type does not meet the TagSpec. + */ +// TODO: document and see tests for the bug that was fixed by this rewrite +static QCBORError +MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe, + const TagSpecification TagSpec, + QCBORItem *pItem) { QCBORError uErr; - // Loops runs at most 1.5 times. Making it a loop saves object code. - while(1) { - uErr = CheckTagRequirement(TagSpec, pItem); - if(uErr != QCBOR_SUCCESS) { - goto Done; - } - if(pItem->uDataType != QCBOR_TYPE_ARRAY) { - break; // Successful exit. Moving on to finish decoding. - } + /* pItem could either be an auto-decoded mantissa and exponent or + * the opening array of an undecoded mantissa and exponent. This + * check will succeed on either, but doesn't say which it was. + */ + uErr = CheckTagRequirement(TagSpec, pItem); + if(uErr != QCBOR_SUCCESS) { + goto Done; + } - // The item is an array, which means an undecoded - // mantissa and exponent, so decode it. It will then - // have a different type and exit the loop if. + if(pItem->uDataType == QCBOR_TYPE_ARRAY) { + /* The item is an array, which means is is an undecoded mantissa + * and exponent. This call consumes the items in the array and + * results in a decoded mantissa and exponent in pItem. This is + * the case where there was no tag. + */ uErr = QCBORDecode_MantissaAndExponent(pMe, pItem); if(uErr != QCBOR_SUCCESS) { goto Done; } - // Second time around, the type must match. - TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG; + /* The above decode didn't determine whether it is a decimal + * fraction or big num. Which of these two depends on what the + * caller wants it decoded as since there is no tag, so fish the + * type out of the TagSpec. */ + pItem->uDataType = MantissaExponentDataType(TagSpec.uTaggedTypes[0], pItem); + + /* No need to check the type again. All that we need to know was + * that it decoded correctly as a mantissa and exponent. The + * QCBOR type is set out by what was requested. + */ } + + /* If the item was not an array and the check passed, then + * it is a fully decoded big float or decimal fraction and + * matches what is requested. + */ + Done: return uErr; } +/* Some notes from the work to disable tags. + * + * The API for big floats and decimal fractions seems good. + * If there's any issue with it it's that the code size to + * implement is a bit large because of the conversion + * to/from int and bignum that is required. There is no API + * that doesn't do the conversion so dead stripping will never + * leave that code out. + * + * The implementation itself seems correct, but not as clean + * and neat as it could be. It could probably be smaller too. + * + * The implementation has three main parts / functions + * - The decoding of the array of two + * - All the tag and type checking for the various API functions + * - Conversion to/from bignum and int + * + * The type checking seems like it wastes the most code for + * what it needs to do. + * + * The inlining for the conversion is probably making the + * overall code base larger. + * + * The tests cases could be organized a lot better and be + * more thorough. + * + * Seems also like there could be more common code in the + * first tier part of the public API. Some functions only + * vary by a TagSpec. + */ static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe, TagSpecification TagSpec, QCBORItem *pItem, @@ -5518,10 +5837,12 @@ static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe, case QCBOR_TYPE_DECIMAL_FRACTION: case QCBOR_TYPE_BIGFLOAT: - *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt; *pnExponent = pItem->val.expAndMantissa.nExponent; + *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt; break; +#ifndef QCBOR_DISABLE_TAGS + /* If tags are disabled, mantissas can never be big nums */ case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM: case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM: *pnExponent = pItem->val.expAndMantissa.nExponent; @@ -5533,6 +5854,7 @@ static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe, *pnExponent = pItem->val.expAndMantissa.nExponent; uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa); break; +#endif /* QCBOR_DISABLE_TAGS */ default: uErr = QCBOR_ERR_UNEXPECTED_TYPE; @@ -5564,17 +5886,23 @@ static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe, case QCBOR_TYPE_DECIMAL_FRACTION: case QCBOR_TYPE_BIGFLOAT: + /* See comments in ExponentiateNN() on handling INT64_MIN */ if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) { uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt; *pbIsNegative = false; - } else { + } else if(pItem->val.expAndMantissa.Mantissa.nInt != INT64_MIN) { uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt; *pbIsNegative = true; + } else { + uMantissa = (uint64_t)INT64_MAX+1; + *pbIsNegative = true; } *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa); *pnExponent = pItem->val.expAndMantissa.nExponent; break; +#ifndef QCBOR_DISABLE_TAGS + /* If tags are disabled, mantissas can never be big nums */ case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM: case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM: *pnExponent = pItem->val.expAndMantissa.nExponent; @@ -5588,6 +5916,7 @@ static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe, *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum; *pbIsNegative = true; break; +#endif /* QCBOR_DISABLE_TAGS */ default: uErr = QCBOR_ERR_UNEXPECTED_TYPE; @@ -5690,7 +6019,7 @@ void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe, */ void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe, uint8_t uTagRequirement, - UsefulBuf MantissaBuffer, + UsefulBuf MantissaBuffer, UsefulBufC *pMantissa, bool *pbMantissaIsNegative, int64_t *pnExponent) diff --git a/3rdparty/exported/QCBOR/src/qcbor_encode.c b/3rdparty/exported/QCBOR/src/qcbor_encode.c index 26d86ce1e075..53df657cfbb7 100644 --- a/3rdparty/exported/QCBOR/src/qcbor_encode.c +++ b/3rdparty/exported/QCBOR/src/qcbor_encode.c @@ -658,8 +658,13 @@ void QCBOREncode_AddInt64(QCBOREncodeContext *me, int64_t nNum) uint64_t uValue; if(nNum < 0) { - /* In CBOR -1 encodes as 0x00 with major type negative int. */ - uValue = (uint64_t)(-nNum - 1); + /* In CBOR -1 encodes as 0x00 with major type negative int. + * First add one as a signed integer because that will not + * overflow. Then change the sign as needed for encoding. (The + * opposite order, changing the sign and subtracting, can cause + * an overflow when encoding INT64_MIN. */ + int64_t nTmp = nNum + 1; + uValue = (uint64_t)-nTmp; uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT; } else { uValue = (uint64_t)nNum; diff --git a/3rdparty/exported/QCBOR/test/CMakeLists.txt b/3rdparty/exported/QCBOR/test/CMakeLists.txt new file mode 100644 index 000000000000..ab53f70dc0d4 --- /dev/null +++ b/3rdparty/exported/QCBOR/test/CMakeLists.txt @@ -0,0 +1,71 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2022-2023, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# See BSD-3-Clause license in README.md +#------------------------------------------------------------------------------- + +cmake_minimum_required(VERSION 3.15) + +# Validate value of BUILD_QCBOR_TEST config option +if ((NOT BUILD_QCBOR_TEST STREQUAL "LIB") AND (NOT BUILD_QCBOR_TEST STREQUAL "APP")) + message(FATAL_ERROR "QCBOR | Invalid Config: BUILD_QCBOR_TEST=${BUILD_QCBOR_TEST}") +endif() + +add_library(qcbor_test STATIC) + +target_sources(qcbor_test + PRIVATE + float_tests.c + half_to_double_from_rfc7049.c + qcbor_decode_tests.c + qcbor_encode_tests.c + run_tests.c + UsefulBuf_Tests.c +) + +target_include_directories(qcbor_test + PUBLIC + . + PRIVATE + ../inc +) + +target_compile_definitions(qcbor_test + PUBLIC + $<$:QCBOR_DISABLE_FLOAT_HW_USE> + $<$:QCBOR_DISABLE_PREFERRED_FLOAT> + $<$:USEFULBUF_DISABLE_ALL_FLOAT> +) + +target_link_libraries(qcbor_test + PRIVATE + qcbor + # The math library is needed for floating-point support. + # To avoid need for it #define QCBOR_DISABLE_FLOAT_HW_USE + # Using GCC + $<$,$>>:m> +) + +if (BUILD_QCBOR_TEST STREQUAL "APP") + add_executable(qcbortest) + + target_sources(qcbortest + PRIVATE + ../cmd_line_main.c + ../example.c + ../ub-example.c + ) + + target_include_directories(qcbortest + PRIVATE + ../ + ) + + target_link_libraries(qcbortest + PRIVATE + qcbor + qcbor_test + ) +endif() diff --git a/3rdparty/exported/QCBOR/test/UsefulBuf_Tests.c b/3rdparty/exported/QCBOR/test/UsefulBuf_Tests.c index e729ff139ffb..e93a011b86f6 100644 --- a/3rdparty/exported/QCBOR/test/UsefulBuf_Tests.c +++ b/3rdparty/exported/QCBOR/test/UsefulBuf_Tests.c @@ -57,6 +57,12 @@ const char *AddStuffToUOB(UsefulOutBuf *pUOB) /* add a space to end */ UsefulOutBuf_AppendByte(pUOB, ' '); + /* Add an empty string */ + UsefulOutBuf_AppendUsefulBuf(pUOB, NULLUsefulBufC); + + /* Add a zero length string (valid pointer, 0 length) */ + UsefulOutBuf_AppendData(pUOB, "xxx", 0); + /* Add 6 bytes to the end */ UsefulBufC UBC = {"hunny ", 6}; UsefulOutBuf_AppendUsefulBuf(pUOB, UBC); diff --git a/3rdparty/exported/QCBOR/test/float_tests.c b/3rdparty/exported/QCBOR/test/float_tests.c index 3484084a18dd..2bf5fad311b7 100644 --- a/3rdparty/exported/QCBOR/test/float_tests.c +++ b/3rdparty/exported/QCBOR/test/float_tests.c @@ -127,7 +127,7 @@ inline static bool CheckDouble(double d, uint64_t u) } -int32_t HalfPrecisionDecodeBasicTests() +int32_t HalfPrecisionDecodeBasicTests(void) { UsefulBufC HalfPrecision = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedHalf); @@ -247,7 +247,7 @@ int32_t HalfPrecisionDecodeBasicTests() -int32_t HalfPrecisionAgainstRFCCodeTest() +int32_t HalfPrecisionAgainstRFCCodeTest(void) { for(uint32_t uHalfP = 0; uHalfP < 0xffff; uHalfP += 60) { unsigned char x[2]; @@ -441,7 +441,7 @@ static const uint8_t spExpectedSmallest[] = { #define MAKE_DOUBLE(x) UsefulBufUtil_CopyUint64ToDouble(x) -int32_t DoubleAsSmallestTest() +int32_t DoubleAsSmallestTest(void) { UsefulBuf_MAKE_STACK_UB(EncodedHalfsMem, sizeof(spExpectedSmallest)); @@ -700,7 +700,7 @@ static const uint8_t spExpectedFloatsNoHalf[] = { 0x18, 0x6A, 0xFA, 0x00, 0x00, 0x00, 0x00}; -int32_t GeneralFloatEncodeTests() +int32_t GeneralFloatEncodeTests(void) { UsefulBufC ExpectedFloats; #ifndef QCBOR_DISABLE_PREFERRED_FLOAT @@ -774,7 +774,7 @@ static int CHECK_EXPECTED_DOUBLE(double val, double expected) #endif /* USEFULBUF_DISABLE_ALL_FLOAT */ -int32_t GeneralFloatDecodeTests() +int32_t GeneralFloatDecodeTests(void) { QCBORItem Item; QCBORError uErr; diff --git a/3rdparty/exported/QCBOR/test/not_well_formed_cbor.h b/3rdparty/exported/QCBOR/test/not_well_formed_cbor.h index 6734e9396dbf..e50588716720 100644 --- a/3rdparty/exported/QCBOR/test/not_well_formed_cbor.h +++ b/3rdparty/exported/QCBOR/test/not_well_formed_cbor.h @@ -15,7 +15,8 @@ #ifndef not_well_formed_cbor_h #define not_well_formed_cbor_h -#include // for size_t and uint8_t +#include // for size_t +#include // for uint8_t struct someBinaryBytes { @@ -50,8 +51,10 @@ static const struct someBinaryBytes paNotWellFormedCBOR[] = { {(uint8_t[]){0x5f, 0x80, 0xff}, 3}, // indefinite length byte string with an map chunk {(uint8_t[]){0x5f, 0xa0, 0xff}, 3}, +#ifndef QCBOR_DISABLE_TAGS // indefinite length byte string with tagged integer chunk {(uint8_t[]){0x5f, 0xc0, 0x00, 0xff}, 4}, +#endif /* QCBOR_DISABLE_TAGS */ // indefinite length byte string with an simple type chunk {(uint8_t[]){0x5f, 0xe0, 0xff}, 3}, // indefinite length byte string with indefinite string inside @@ -246,11 +249,12 @@ static const struct someBinaryBytes paNotWellFormedCBOR[] = { {(uint8_t[]){0x1f}, 1}, // Negative integer with "argument" an indefinite length {(uint8_t[]){0x3f}, 1}, +#ifndef QCBOR_DISABLE_TAGS // CBOR tag with "argument" an indefinite length {(uint8_t[]){0xdf, 0x00}, 2}, // CBOR tag with "argument" an indefinite length alternate vector {(uint8_t[]){0xdf}, 1}, - +#endif /* QCBOR_DISABLE_TAGS */ // Missing content bytes from a definite length string diff --git a/3rdparty/exported/QCBOR/test/qcbor_decode_tests.c b/3rdparty/exported/QCBOR/test/qcbor_decode_tests.c index 431836cdca30..e913854d7a3d 100644 --- a/3rdparty/exported/QCBOR/test/qcbor_decode_tests.c +++ b/3rdparty/exported/QCBOR/test/qcbor_decode_tests.c @@ -484,7 +484,7 @@ static const uint8_t spTooSmallNegative[] = { Tests the decoding of lots of different integers sizes and values. */ -int32_t IntegerValuesParseTest() +int32_t IntegerValuesParseTest(void) { int nReturn; QCBORDecodeContext DCtx; @@ -691,7 +691,7 @@ static int32_t ParseOrderedArray(const uint8_t *pEncoded, -int32_t SimpleArrayTest() +int32_t SimpleArrayTest(void) { uint8_t *pEncoded; size_t nEncodedLen; @@ -898,7 +898,7 @@ static int32_t CheckEmpties(UsefulBufC input, bool bCheckCounts) } -int32_t EmptyMapsAndArraysTest() +int32_t EmptyMapsAndArraysTest(void) { int nResult; nResult = CheckEmpties(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(sEmpties), @@ -966,7 +966,7 @@ static const uint8_t spDeepArrays[] = { 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80}; -int32_t ParseDeepArrayTest() +int32_t ParseDeepArrayTest(void) { QCBORDecodeContext DCtx; int nReturn = 0; @@ -999,7 +999,7 @@ static const uint8_t spTooDeepArrays[] = { 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80}; -int32_t ParseTooDeepArrayTest() +int32_t ParseTooDeepArrayTest(void) { QCBORDecodeContext DCtx; int nReturn = 0; @@ -1030,7 +1030,7 @@ int32_t ParseTooDeepArrayTest() -int32_t ShortBufferParseTest() +int32_t ShortBufferParseTest(void) { int nResult = 0; @@ -1054,7 +1054,7 @@ int32_t ShortBufferParseTest() -int32_t ShortBufferParseTest2() +int32_t ShortBufferParseTest2(void) { uint8_t *pEncoded; int nReturn; @@ -1214,7 +1214,7 @@ static int32_t ParseMapTest1(QCBORDecodeMode nMode) Decode and thoroughly check a moderately complex set of maps in the QCBOR_DECODE_MODE_MAP_AS_ARRAY mode. */ -int32_t ParseMapAsArrayTest() +int32_t ParseMapAsArrayTest(void) { QCBORDecodeContext DCtx; QCBORItem Item; @@ -1637,7 +1637,7 @@ static int32_t ExtraBytesTest(int nLevel) -int32_t ParseMapTest() +int32_t ParseMapTest(void) { // Parse a moderatly complex map structure very thoroughly int32_t nResult = ParseMapTest1(QCBOR_DECODE_MODE_NORMAL); @@ -1672,7 +1672,7 @@ static const uint8_t spSimpleValues[] = { 0xf8, 0x00, 0xf8, 0x13, 0xf8, 0x1f, 0xf8, 0x20, 0xf8, 0xff}; -int32_t ParseSimpleTest() +int32_t ParseSimpleTest(void) { QCBORDecodeContext DCtx; QCBORItem Item; @@ -1748,7 +1748,7 @@ int32_t ParseSimpleTest() } -int32_t NotWellFormedTests() +int32_t NotWellFormedTests(void) { // Loop over all the not-well-formed instance of CBOR // that are test vectors in not_well_formed_cbor.h @@ -1758,6 +1758,10 @@ int32_t NotWellFormedTests() const struct someBinaryBytes *pBytes = &paNotWellFormedCBOR[nIterate]; const UsefulBufC Input = (UsefulBufC){pBytes->p, pBytes->n}; + if(nIterate == 86) { + nIterate = 86; + } + // Set up decoder context. String allocator needed for indefinite // string test cases QCBORDecodeContext DCtx; @@ -1814,6 +1818,11 @@ static int32_t ProcessFailures(const struct FailInput *pFailInputs, size_t nNumF } #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ + const size_t nIndexx = (size_t)(pF - pFailInputs); + if(nIndexx == 8) { + uCBORError = 9; + } + // Iterate until there is an error of some sort error QCBORItem Item; @@ -1867,8 +1876,13 @@ static const struct FailInput Failures[] = { { {(uint8_t[]){0x5f, 0x80, 0xff}, 3}, QCBOR_ERR_INDEFINITE_STRING_CHUNK }, // indefinite length byte string with an map chunk { {(uint8_t[]){0x5f, 0xa0, 0xff}, 3}, QCBOR_ERR_INDEFINITE_STRING_CHUNK }, +#ifndef QCBOR_DISABLE_TAGS // indefinite length byte string with tagged integer chunk { {(uint8_t[]){0x5f, 0xc0, 0x00, 0xff}, 4}, QCBOR_ERR_INDEFINITE_STRING_CHUNK }, +#else + // indefinite length byte string with tagged integer chunk + { {(uint8_t[]){0x5f, 0xc0, 0x00, 0xff}, 4}, QCBOR_ERR_TAGS_DISABLED }, +#endif /* QCBOR_DISABLE_TAGS */ // indefinite length byte string with an simple type chunk { {(uint8_t[]){0x5f, 0xe0, 0xff}, 3}, QCBOR_ERR_INDEFINITE_STRING_CHUNK }, { {(uint8_t[]){0x5f, 0x5f, 0x41, 0x00, 0xff, 0xff}, 6}, QCBOR_ERR_INDEFINITE_STRING_CHUNK}, @@ -1999,10 +2013,12 @@ static const struct FailInput Failures[] = { // double-precision with 3 byte argument { {(uint8_t[]){0xfb, 0x00, 0x00, 0x00}, 4}, QCBOR_ERR_HIT_END }, - +#ifndef QCBOR_DISABLE_TAGS // Tag with no content { {(uint8_t[]){0xc0}, 1}, QCBOR_ERR_HIT_END }, - +#else /* QCBOR_DISABLE_TAGS */ + { {(uint8_t[]){0xc0}, 1}, QCBOR_ERR_TAGS_DISABLED }, +#endif /* QCBOR_DISABLE_TAGS */ // Breaks must not occur in definite length arrays and maps // Array of length 1 with sole member replaced by a break @@ -2094,11 +2110,16 @@ static const struct FailInput Failures[] = { { {(uint8_t[]){0x1f}, 1}, QCBOR_ERR_BAD_INT }, // Negative integer with additional info indefinite length { {(uint8_t[]){0x3f}, 1}, QCBOR_ERR_BAD_INT }, + +#ifndef QCBOR_DISABLE_TAGS // CBOR tag with "argument" an indefinite length { {(uint8_t[]){0xdf, 0x00}, 2}, QCBOR_ERR_BAD_INT }, // CBOR tag with "argument" an indefinite length alternate vector { {(uint8_t[]){0xdf}, 1}, QCBOR_ERR_BAD_INT }, - +#else /* QCBOR_DISABLE_TAGS */ + { {(uint8_t[]){0xdf, 0x00}, 2}, QCBOR_ERR_TAGS_DISABLED }, + { {(uint8_t[]){0xdf}, 1}, QCBOR_ERR_TAGS_DISABLED }, +#endif /* QCBOR_DISABLE_TAGS */ // Missing bytes from a deterministic length string // A byte string is of length 1 without the 1 byte @@ -2191,7 +2212,7 @@ static const struct FailInput Failures[] = { { {(uint8_t[]){0xbf, 0x00, 0x00, 0x00, 0xff}, 5}, QCBOR_ERR_BAD_BREAK }, #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */ - +#ifndef QCBOR_DISABLE_TAGS // In addition to not-well-formed, some invalid CBOR // Text-based date, with an integer { {(uint8_t[]){0xc0, 0x00}, 2}, QCBOR_ERR_BAD_OPT_TAG }, @@ -2201,9 +2222,20 @@ static const struct FailInput Failures[] = { { {(uint8_t[]){0xc1, 0xc0, 0x00}, 3}, QCBOR_ERR_BAD_OPT_TAG }, // big num tagged an int, not a byte string { {(uint8_t[]){0xc2, 0x00}, 2}, QCBOR_ERR_BAD_OPT_TAG }, +#else /* QCBOR_DISABLE_TAGS */ + // Text-based date, with an integer + { {(uint8_t[]){0xc0, 0x00}, 2}, QCBOR_ERR_TAGS_DISABLED }, + // Epoch date, with an byte string + { {(uint8_t[]){0xc1, 0x41, 0x33}, 3}, QCBOR_ERR_TAGS_DISABLED }, + // tagged as both epoch and string dates + { {(uint8_t[]){0xc1, 0xc0, 0x00}, 3}, QCBOR_ERR_TAGS_DISABLED }, + // big num tagged an int, not a byte string + { {(uint8_t[]){0xc2, 0x00}, 2}, QCBOR_ERR_TAGS_DISABLED }, +#endif /* QCBOR_DISABLE_TAGS */ + }; -int32_t DecodeFailureTests() +int32_t DecodeFailureTests(void) { int32_t nResult; @@ -2303,7 +2335,7 @@ static void ComprehensiveInputRecurser(uint8_t *pBuf, size_t nLen, size_t nLenMa } -int32_t ComprehensiveInputTest() +int32_t ComprehensiveInputTest(void) { // Size 2 tests 64K inputs and runs quickly uint8_t pBuf[2]; @@ -2314,7 +2346,7 @@ int32_t ComprehensiveInputTest() } -int32_t BigComprehensiveInputTest() +int32_t BigComprehensiveInputTest(void) { // size 3 tests 16 million inputs and runs OK // in seconds on fast machines. Size 4 takes @@ -2401,8 +2433,8 @@ static int CHECK_EXPECTED_DOUBLE(double val, double expected) { #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ - -int32_t DateParseTest() +/* Test date decoding using GetNext() */ +int32_t DateParseTest(void) { QCBORDecodeContext DCtx; QCBORItem Item; @@ -2532,6 +2564,7 @@ int32_t DateParseTest() return 0; } + /* Test cases covered here. Some items cover more than one of these. positive integer (zero counts as a positive integer) @@ -2561,76 +2594,82 @@ int32_t DateParseTest() Untagged values */ static const uint8_t spSpiffyDateTestInput[] = { - 0x86, // array of 6 items + 0x87, // array of 7 items - 0xc1, - 0xfb, 0xc3, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // -9.2233720368547748E+18, too negative + 0xa6, // Open a map for tests involving untagged items with labels. - 0xc1, // tag for epoch date - 0x1b, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // Too-large integer + // Untagged integer 0 + 0x08, + 0x00, - 0xc1, // tag for epoch date - 0xf9, 0xfc, 0x00, // Half-precision -Infinity + // Utagged date string with string label y + 0x61, 0x79, + 0x6a, '2','0','8','5','-','0','4','-','1','2', // Untagged date string - 0xad, // Open a map for tests involving labels. + // Untagged single-precision float with value 3.14 with string label x + 0x61, 0x78, + 0xFA, 0x40, 0x48, 0xF5, 0xC3, + + // Untagged half-precision float with value -2 + 0x09, + 0xF9, 0xC0, 0x00, + + /* Untagged date-only date string */ + 0x18, 0x63, + 0x6A, 0x31, 0x39, 0x38, 0x35, 0x2D, 0x30, 0x34, 0x2D, 0x31, 0x32, /* "1985-04-12" */ + + /* Untagged days-count epoch date */ + 0x11, + 0x19, 0x0F, 0x9A, /* 3994 */ + + // End of map, back to array + + 0xa7, // Open map of tagged items with labels 0x00, 0xc0, // tag for string date 0x6a, '1','9','8','5','-','0','4','-','1','2', // Tagged date string + 0x01, 0xda, 0x03, 0x03, 0x03, 0x03, // An additional tag 0xc1, // tag for epoch date 0x1a, 0x53, 0x72, 0x4E, 0x00, // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT - // Untagged integer 0 - 0x08, - 0x00, - - // Utagged date string with string label y - 0x61, 0x79, - 0x6a, '2','0','8','5','-','0','4','-','1','2', // Untagged date string + 0x05, + 0xc1, + 0xfb, 0xc3, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, // -9223372036854773760 largest negative - // Untagged -1000 with label z - 0x61, 0x7a, - 0xda, 0x01, 0x01, 0x01, 0x01, // An additional tag - 0x39, 0x03, 0xe7, 0x07, 0xc1, // tag for epoch date 0xfb, 0x43, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, // 9223372036854773760 largest supported - 0x05, - 0xc1, - 0xfb, 0xc3, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, // -9223372036854773760 largest negative - - // Untagged single-precision float with value 3.14 with string label x - 0x61, 0x78, - 0xFA, 0x40, 0x48, 0xF5, 0xC3, + /* Tagged days-count epoch date */ + 0x63, 0x53, 0x44, 0x45, + 0xD8, 0x64, /* tag(100) */ + 0x39, 0x29, 0xB3, /* -10676 */ - // Untagged half-precision float with value -2 - 0x09, - 0xF9, 0xC0, 0x00, + // Untagged -1000 with label z + 0x61, 0x7a, + 0xda, 0x01, 0x01, 0x01, 0x01, // An additional tag + 0x39, 0x03, 0xe7, /* Tagged date-only date string */ 0x63, 0x53, 0x44, 0x53, 0xD9, 0x03, 0xEC, 0x6A, 0x31, 0x39, 0x38, 0x35, 0x2D, 0x30, 0x34, 0x2D, 0x31, 0x32, /* "1985-04-12" */ - /* Untagged date-only date string */ - 0x18, 0x63, - 0x6A, 0x31, 0x39, 0x38, 0x35, 0x2D, 0x30, 0x34, 0x2D, 0x31, 0x32, /* "1985-04-12" */ + // End of map of tagged items - /* Tagged days-count epoch date */ - 0x63, 0x53, 0x44, 0x45, - 0xD8, 0x64, /* tag(100) */ - 0x39, 0x29, 0xB3, /* -10676 */ + 0xc1, + 0xfb, 0xc3, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // -9.2233720368547748E+18, too negative - /* Untagged days-count epoch date */ - 0x11, - 0x19, 0x0F, 0x9A, /* 3994 */ + 0xc1, // tag for epoch date + 0x1b, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // Too-large integer - // End of map, back to array + 0xc1, // tag for epoch date + 0xf9, 0xfc, 0x00, // Half-precision -Infinity // These two at the end because they are unrecoverable errors 0xc1, // tag for epoch date @@ -2638,78 +2677,28 @@ static const uint8_t spSpiffyDateTestInput[] = { 0xc0, // tag for string date 0xa0 // Erroneous empty map as content for date - }; -int32_t SpiffyDateDecodeTest() +int32_t SpiffyDateDecodeTest(void) { QCBORDecodeContext DC; QCBORError uError; - int64_t nEpochDate2, nEpochDate3, nEpochDate5, - nEpochDate4, nEpochDate6, nEpochDateFail, - nEpochDate1400000000, nEpochDays1, nEpochDays2; - UsefulBufC StringDate1, StringDate2, StringDays1, StringDays2; - uint64_t uTag1, uTag2; + int64_t nEpochDate3, nEpochDate5, + nEpochDate4, nEpochDate6, + nEpochDays2; + UsefulBufC StringDate1, StringDate2, StringDays2; QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSpiffyDateTestInput), QCBOR_DECODE_MODE_NORMAL); - QCBORDecode_EnterArray(&DC, NULL); - - // Too-negative float, -9.2233720368547748E+18 - QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nEpochDateFail); - uError = QCBORDecode_GetAndResetError(&DC); - if(uError != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_ERR_DATE_OVERFLOW)) { - return 1111; - } - - // Too-large integer - QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nEpochDateFail); - uError = QCBORDecode_GetAndResetError(&DC); - if(uError != QCBOR_ERR_DATE_OVERFLOW) { - return 1; - } - - // Half-precision minus infinity - QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nEpochDateFail); - uError = QCBORDecode_GetAndResetError(&DC); - if(uError != FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(QCBOR_ERR_DATE_OVERFLOW)) { - return 2; - } - + /* Items are in an array or map to test look up by label and other + * that might not occur in isolated items. But it does make the + * test a bit messy. */ + QCBORDecode_EnterArray(&DC, NULL); QCBORDecode_EnterMap(&DC, NULL); - // Get largest negative double precision epoch date allowed - QCBORDecode_GetEpochDateInMapN(&DC, - 5, - QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG | - QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS, - &nEpochDate2); - uError = QCBORDecode_GetAndResetError(&DC); - if(uError != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)) { - return 102; - } - if(uError == QCBOR_SUCCESS) { - if(nEpochDate2 != -9223372036854773760LL) { - return 101; - } - } - - // Get largest double precision epoch date allowed - QCBORDecode_GetEpochDateInMapN(&DC, 7, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, - &nEpochDate2); - uError = QCBORDecode_GetAndResetError(&DC); - if(uError != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)) { - return 112; - } - if(uError == QCBOR_SUCCESS) { - if(nEpochDate2 != 9223372036854773760ULL) { - return 111; - } - } - // A single-precision date QCBORDecode_GetEpochDateInMapSZ(&DC, "x", QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, &nEpochDate5); @@ -2772,6 +2761,39 @@ int32_t SpiffyDateDecodeTest() // The rest of these succeed even if float features are disabled + + // Untagged integer 0 + QCBORDecode_GetEpochDateInMapN(&DC, 8, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, + &nEpochDate3); + // Untagged date string + QCBORDecode_GetDateStringInMapSZ(&DC, "y", QCBOR_TAG_REQUIREMENT_NOT_A_TAG, + &StringDate2); + + QCBORDecode_GetDaysStringInMapN(&DC, 99, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, + &StringDays2); + + QCBORDecode_GetEpochDaysInMapN(&DC, 17, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, + &nEpochDays2); + + QCBORDecode_ExitMap(&DC); + if(QCBORDecode_GetError(&DC) != QCBOR_SUCCESS) { + return 3001; + } + + // The map of tagged items + QCBORDecode_EnterMap(&DC, NULL); + +#ifndef QCBOR_DISABLE_TAGS + int64_t nEpochDate2, + nEpochDateFail, + nEpochDate1400000000, nEpochDays1; + UsefulBufC StringDays1; + uint64_t uTag1, uTag2; + + // Tagged date string + QCBORDecode_GetDateStringInMapN(&DC, 0, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, + &StringDate1); + // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT QCBORDecode_GetEpochDateInMapN(&DC, 1, @@ -2779,15 +2801,23 @@ int32_t SpiffyDateDecodeTest() QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS, &nEpochDate1400000000); uTag1 = QCBORDecode_GetNthTagOfLast(&DC, 0); - // Tagged date string - QCBORDecode_GetDateStringInMapN(&DC, 0, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, - &StringDate1); - // Untagged integer 0 - QCBORDecode_GetEpochDateInMapN(&DC, 8, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, - &nEpochDate3); - // Untagged date string - QCBORDecode_GetDateStringInMapSZ(&DC, "y", QCBOR_TAG_REQUIREMENT_NOT_A_TAG, - &StringDate2); + + // Get largest negative double precision epoch date allowed + QCBORDecode_GetEpochDateInMapN(&DC, + 5, + QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG | + QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS, + &nEpochDate2); + uError = QCBORDecode_GetAndResetError(&DC); + if(uError != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)) { + return 102; + } + if(uError == QCBOR_SUCCESS) { + if(nEpochDate2 != -9223372036854773760LL) { + return 101; + } + } + // Untagged -1000 with label z QCBORDecode_GetEpochDateInMapSZ(&DC, "z", @@ -2796,6 +2826,20 @@ int32_t SpiffyDateDecodeTest() &nEpochDate6); uTag2 = QCBORDecode_GetNthTagOfLast(&DC, 0); + + // Get largest double precision epoch date allowed + QCBORDecode_GetEpochDateInMapN(&DC, 7, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, + &nEpochDate2); + uError = QCBORDecode_GetAndResetError(&DC); + if(uError != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS)) { + return 112; + } + if(uError == QCBOR_SUCCESS) { + if(nEpochDate2 != 9223372036854773760ULL) { + return 111; + } + } + /* The days format is much simpler than the date format * because it can't be a floating point value. The test * of the spiffy decode functions sufficiently covers @@ -2807,20 +2851,36 @@ int32_t SpiffyDateDecodeTest() QCBORDecode_GetDaysStringInMapSZ(&DC, "SDS", QCBOR_TAG_REQUIREMENT_TAG, &StringDays1); - QCBORDecode_GetDaysStringInMapN(&DC, 99, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, - &StringDays2); - QCBORDecode_GetEpochDaysInMapSZ(&DC, "SDE", QCBOR_TAG_REQUIREMENT_TAG, &nEpochDays1); - QCBORDecode_GetEpochDaysInMapN(&DC, 17, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, - &nEpochDays2); - QCBORDecode_ExitMap(&DC); if(QCBORDecode_GetError(&DC) != QCBOR_SUCCESS) { return 3001; } + // Too-negative float, -9.2233720368547748E+18 + QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nEpochDateFail); + uError = QCBORDecode_GetAndResetError(&DC); + if(uError != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_ERR_DATE_OVERFLOW)) { + return 1111; + } + + // Too-large integer + QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nEpochDateFail); + uError = QCBORDecode_GetAndResetError(&DC); + if(uError != QCBOR_ERR_DATE_OVERFLOW) { + return 1; + } + + // Half-precision minus infinity + QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nEpochDateFail); + uError = QCBORDecode_GetAndResetError(&DC); + if(uError != FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(QCBOR_ERR_DATE_OVERFLOW)) { + return 2; + } + + // Bad content for epoch date QCBORDecode_GetEpochDate(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nEpochDateFail); uError = QCBORDecode_GetAndResetError(&DC); @@ -2840,6 +2900,17 @@ int32_t SpiffyDateDecodeTest() if(uError != QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT) { return 1000 + (int32_t)uError; } +#else /* QCBOR_DISABLE_TAGS */ + QCBORDecode_GetDateStringInMapN(&DC, 0, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, + &StringDate1); + uError = QCBORDecode_GetAndResetError(&DC); + if(uError != QCBOR_ERR_TAGS_DISABLED) { + return 4; + } +#endif /* QCBOR_DISABLE_TAGS */ + + +#ifndef QCBOR_DISABLE_TAGS if(nEpochDate1400000000 != 1400000000) { return 200; @@ -2849,36 +2920,38 @@ int32_t SpiffyDateDecodeTest() return 201; } - if(nEpochDate3 != 0) { - return 202; + if(nEpochDays1 != -10676) { + return 205; } - if(nEpochDate6 != -1000) { - return 203; + if(UsefulBuf_Compare(StringDays1, UsefulBuf_FromSZ("1985-04-12"))) { + return 207; } if(uTag2 != 0x01010101) { return 204; } - if(nEpochDays1 != -10676) { - return 205; - } - - if(nEpochDays2 != 3994) { - return 206; + if(nEpochDate6 != -1000) { + return 203; } if(UsefulBuf_Compare(StringDate1, UsefulBuf_FromSZ("1985-04-12"))) { return 205; } - if(UsefulBuf_Compare(StringDate2, UsefulBuf_FromSZ("2085-04-12"))) { +#endif /* QCBOR_DISABLE_TAGS */ + + if(nEpochDate3 != 0) { + return 202; + } + + if(nEpochDays2 != 3994) { return 206; } - if(UsefulBuf_Compare(StringDays1, UsefulBuf_FromSZ("1985-04-12"))) { - return 207; + if(UsefulBuf_Compare(StringDate2, UsefulBuf_FromSZ("2085-04-12"))) { + return 206; } if(UsefulBuf_Compare(StringDays2, UsefulBuf_FromSZ("1985-04-12"))) { @@ -2889,7 +2962,6 @@ int32_t SpiffyDateDecodeTest() } - // Input for one of the tagging tests static const uint8_t spTagInput[] = { 0xd9, 0xd9, 0xf7, // CBOR magic number @@ -3050,7 +3122,7 @@ static const uint8_t spSpiffyTagInput[] = { static int32_t CheckCSRMaps(QCBORDecodeContext *pDC); -int32_t OptTagParseTest() +int32_t OptTagParseTest(void) { QCBORDecodeContext DCtx; QCBORItem Item; @@ -3530,8 +3602,19 @@ int32_t OptTagParseTest() return 0; } - - +/* + * These are showing the big numbers converted to integers. + * The tag numbers are not shown. + * + * [ 18446744073709551616, + * -18446744073709551617, + * {"BN+": 18446744073709551616, + * 64: 18446744073709551616, + * "BN-": -18446744073709551617, + * -64: -18446744073709551617 + * } + * ] + */ static const uint8_t spBigNumInput[] = { 0x83, @@ -3547,13 +3630,15 @@ static const uint8_t spBigNumInput[] = { 0x38, 0x3F, 0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +#ifndef QCBOR_DISABLE_TAGS /* The expected big num */ static const uint8_t spBigNum[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +#endif /* QCBOR_DISABLE_TAGS */ -int32_t BignumParseTest() +int32_t BignumParseTest(void) { QCBORDecodeContext DCtx; QCBORItem Item; @@ -3571,6 +3656,7 @@ int32_t BignumParseTest() return -2; } +#ifndef QCBOR_DISABLE_TAGS // if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) return -3; @@ -3627,6 +3713,12 @@ int32_t BignumParseTest() UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){ return -16; } +#else + + if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_TAGS_DISABLED) { + return -100; + } +#endif /* QCBOR_DISABLE_TAGS */ return 0; } @@ -3743,7 +3835,7 @@ static const uint8_t spCSRInputIndefLen[] = { 0x35, 0xbf, 0x24, 0x22, 0xff, 0xff}; -int32_t NestedMapTest() +int32_t NestedMapTest(void) { QCBORDecodeContext DCtx; @@ -3756,7 +3848,7 @@ int32_t NestedMapTest() -int32_t StringDecoderModeFailTest() +int32_t StringDecoderModeFailTest(void) { QCBORDecodeContext DCtx; @@ -3784,7 +3876,7 @@ int32_t StringDecoderModeFailTest() -int32_t NestedMapTestIndefLen() +int32_t NestedMapTestIndefLen(void) { QCBORDecodeContext DCtx; @@ -3848,7 +3940,7 @@ static int32_t parse_indeflen_nested(UsefulBufC Nested, int nNestLevel) } -int32_t IndefiniteLengthNestTest() +int32_t IndefiniteLengthNestTest(void) { UsefulBuf_MAKE_STACK_UB(Storage, 50); int i; @@ -3875,7 +3967,7 @@ static const uint8_t spIndefiniteArrayBad4[] = {0x81, 0x9f}; // confused tag static const uint8_t spIndefiniteArrayBad5[] = {0x9f, 0xd1, 0xff}; -int32_t IndefiniteLengthArrayMapTest() +int32_t IndefiniteLengthArrayMapTest(void) { QCBORError nResult; // --- first test ----- @@ -4015,6 +4107,8 @@ int32_t IndefiniteLengthArrayMapTest() QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL); nResult = QCBORDecode_GetNext(&DC, &Item); + +#ifndef QCBOR_DISABLE_TAGS if(nResult || Item.uDataType != QCBOR_TYPE_ARRAY) { return -18; } @@ -4023,6 +4117,11 @@ int32_t IndefiniteLengthArrayMapTest() if(nResult != QCBOR_ERR_BAD_BREAK) { return -19; } +#else /* QCBOR_DISABLE_TAGS */ + if(nResult != QCBOR_ERR_TAGS_DISABLED) { + return -20; + } +#endif /* QCBOR_DISABLE_TAGS */ return 0; } @@ -4118,7 +4217,7 @@ static int CheckBigString(UsefulBufC BigString) } -int32_t IndefiniteLengthStringTest() +int32_t IndefiniteLengthStringTest(void) { QCBORDecodeContext DC; QCBORItem Item; @@ -4307,7 +4406,7 @@ int32_t IndefiniteLengthStringTest() } -int32_t AllocAllStringsTest() +int32_t AllocAllStringsTest(void) { QCBORDecodeContext DC; QCBORError nCBORError; @@ -4549,155 +4648,534 @@ int32_t SetUpAllocatorTest(void) #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA -/* exponent, mantissa - [ - 4([-1, 3]), - 4([-20, 4759477275222530853136]), - 4([9223372036854775807, -4759477275222530853137]), - 5([300, 100]), - 5([-20, 4759477275222530853136]), - 5([-9223372036854775807, -4759477275222530853137]) - 5([ 9223372036854775806, -4759477275222530853137]) - 5([ 9223372036854775806, 9223372036854775806])] - ] - */ -static const uint8_t spExpectedExponentsAndMantissas[] = { - 0x88, - 0xC4, 0x82, 0x20, - 0x03, - 0xC4, 0x82, 0x33, - 0xC2, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, - 0xC4, 0x82, 0x1B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC3, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, - 0xC5, 0x82, 0x19, 0x01, 0x2C, - 0x18, 0x64, - 0xC5, 0x82, 0x33, - 0xC2, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, - 0xC5, 0x82, 0x3B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, - 0xC3, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, - 0xC5, 0x82, 0x1B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, - 0xC3, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, - 0xC5, 0x82, 0x1B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, - 0x1B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE +struct EaMTest { + const char *szName; + UsefulBufC Input; + uint8_t uTagRequirement; + bool bHasTags; + + /* Expected values for GetNext */ + QCBORError uExpectedErrorGN; + uint8_t uQCBORTypeGN; + int64_t nExponentGN; + int64_t nMantissaGN; + UsefulBufC MantissaGN; + + /* Expected values for GetDecimalFraction */ + QCBORError uExpectedErrorGDF; + int64_t nExponentGDF; + int64_t nMantissaGDF; + + /* Expected values for GetDecimalFractionBig */ + QCBORError uExpectedErrorGDFB; + int64_t nExponentGDFB; + UsefulBufC MantissaGDFB; + bool IsNegativeGDFB; + + /* Expected values for GetBigFloat */ + QCBORError uExpectedErrorGBF; + int64_t nExponentGBF; + int64_t nMantissaGBF; + + /* Expected values for GetBigFloatBig */ + QCBORError uExpectedErrorGBFB; + int64_t nExponentGBFB; + UsefulBufC MantissaGBFB; + bool IsNegativeGBFB; }; -int32_t ExponentAndMantissaDecodeTests(void) -{ - QCBORDecodeContext DC; - QCBORError uErr; - QCBORItem item; - static const uint8_t spBigNumMantissa[] = {0x01, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x08, 0x09, 0x010}; - UsefulBufC BN = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNumMantissa); +static const struct EaMTest pEaMTests[] = { + { + "1. Untagged pair (big float or decimal fraction), no tag required", + {(const uint8_t []){0x82, 0x20, 0x03}, 3}, + QCBOR_TAG_REQUIREMENT_NOT_A_TAG, + false, + QCBOR_SUCCESS, /* for GetNext */ + QCBOR_TYPE_ARRAY, + 0, + 0, + {(const uint8_t []){0x00}, 1}, - QCBORDecode_Init(&DC, - UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedExponentsAndMantissas), - QCBOR_DECODE_MODE_NORMAL); + QCBOR_SUCCESS, /* GetDecimalFraction */ + -1, + 3, - uErr = QCBORDecode_GetNext(&DC, &item); - if(uErr != QCBOR_SUCCESS) { - return 1; - } + QCBOR_SUCCESS, /* for GetDecimalFractionBig */ + -1, + {(const uint8_t []){0x03}, 1}, + false, - if(item.uDataType != QCBOR_TYPE_ARRAY) { - return 2; - } + QCBOR_SUCCESS, /* for GetBigFloat */ + -1, + 3, - uErr = QCBORDecode_GetNext(&DC, &item); - if(uErr != QCBOR_SUCCESS) { - return 3; - } + QCBOR_SUCCESS, /* for GetBigFloatBig */ + -1, + {(const uint8_t []){0x03}, 1}, + false + }, - if(item.uDataType != QCBOR_TYPE_DECIMAL_FRACTION || - item.val.expAndMantissa.Mantissa.nInt != 3 || - item.val.expAndMantissa.nExponent != -1) { - return 4; - } + { + "2. Untagged pair (big float or decimal fraction), tag required", + {(const uint8_t []){0x82, 0x20, 0x03}, 3}, + QCBOR_TAG_REQUIREMENT_TAG, + false, - uErr = QCBORDecode_GetNext(&DC, &item); - if(uErr != QCBOR_SUCCESS) { - return 5; - } + QCBOR_SUCCESS, /* for GetNext */ + QCBOR_TYPE_ARRAY, + 0, + 0, + {(const uint8_t []){0x00}, 1}, - if(item.uDataType != QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM || - item.val.expAndMantissa.nExponent != -20 || - UsefulBuf_Compare(item.val.expAndMantissa.Mantissa.bigNum, BN)) { - return 6; - } + QCBOR_ERR_UNEXPECTED_TYPE, /* for GetDecimalFraction */ + 0, + 0, - uErr = QCBORDecode_GetNext(&DC, &item); - if(uErr != QCBOR_SUCCESS) { - return 7; - } + QCBOR_ERR_UNEXPECTED_TYPE, /* for GetDecimalFractionBig */ + 0, + {(const uint8_t []){0x00}, 1}, + false, - if(item.uDataType != QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM || - item.val.expAndMantissa.nExponent != 9223372036854775807 || - UsefulBuf_Compare(item.val.expAndMantissa.Mantissa.bigNum, BN)) { - return 8; - } + QCBOR_ERR_UNEXPECTED_TYPE, /* for GetBigFloat */ + 0, + 0, - uErr = QCBORDecode_GetNext(&DC, &item); - if(uErr != QCBOR_SUCCESS) { - return 9; - } + QCBOR_ERR_UNEXPECTED_TYPE, /* for GetBigFloatBig */ + 0, + {(const uint8_t []){0x00}, 1}, + false - if(item.uDataType != QCBOR_TYPE_BIGFLOAT || - item.val.expAndMantissa.Mantissa.nInt != 100 || - item.val.expAndMantissa.nExponent != 300) { - return 10; - } + }, - // 5([-20, 4759477275222530853136]), - uErr = QCBORDecode_GetNext(&DC, &item); - if(uErr != QCBOR_SUCCESS) { - return 11; - } - if(item.uDataType != QCBOR_TYPE_BIGFLOAT_POS_BIGNUM || - item.val.expAndMantissa.nExponent != -20 || - UsefulBuf_Compare(item.val.expAndMantissa.Mantissa.bigNum, BN)) { - return 12; - } + { + "3. Tagged 1.5 decimal fraction, tag 4 optional", + {(const uint8_t []){0xC4, 0x82, 0x20, 0x03}, 4}, + QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, + true, - // 5([-9223372036854775807, -4759477275222530853137]) - uErr = QCBORDecode_GetNext(&DC, &item); - if(uErr != QCBOR_SUCCESS) { - return 13; - } - if(item.uDataType != QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM || - item.val.expAndMantissa.nExponent != -9223372036854775807 || - UsefulBuf_Compare(item.val.expAndMantissa.Mantissa.bigNum, BN)) { - return 14; + QCBOR_SUCCESS, /* for GetNext */ + QCBOR_TYPE_DECIMAL_FRACTION, + -1, + 3, + {(const uint8_t []){0x00}, 1}, + + + QCBOR_SUCCESS, /* for GetDecimalFraction */ + -1, + 3, + + QCBOR_SUCCESS, /* for GetDecimalFractionBig */ + -1, + {(const uint8_t []){0x03}, 1}, + false, + + QCBOR_ERR_UNEXPECTED_TYPE, /* for GetBigFloat */ + 0, + 0, + + QCBOR_ERR_UNEXPECTED_TYPE, /* for GetBigFloatBig */ + 0, + {(const uint8_t []){0x00}, 1}, + false + }, + { + "4. Tagged 100 * 2^300 big float, tag 5 optional", + {(const uint8_t []){0xC5, 0x82, 0x19, 0x01, 0x2C, 0x18, 0x64}, 7}, + QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, + true, + + QCBOR_SUCCESS, /* for GetNext */ + QCBOR_TYPE_BIGFLOAT, + 300, + 100, + {(const uint8_t []){0x00}, 1}, + + + QCBOR_ERR_UNEXPECTED_TYPE, /* for GetDecimalFraction */ + 0, + 0, + + QCBOR_ERR_UNEXPECTED_TYPE, /* for GetDecimalFractionBig */ + 0, + {(const uint8_t []){0x03}, 1}, + false, + + QCBOR_SUCCESS, /* for GetBigFloat */ + 300, + 100, + + QCBOR_SUCCESS, /* for GetBigFloatBig */ + 300, + {(const uint8_t []){0x64}, 1}, + false + }, + + { + "5. Tagged 4([-20, 4759477275222530853136]) decimal fraction, tag 4 required", + {(const uint8_t []){0xC4, 0x82, 0x33, + 0xC2, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,}, 15}, + QCBOR_TAG_REQUIREMENT_TAG, + true, + + QCBOR_SUCCESS, /* for GetNext */ + QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, + -20, + 0, + {(const uint8_t []){0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10}, 10}, + + QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, /* for GetDecimalFraction */ + 0, + 0, + + QCBOR_SUCCESS, /* for GetDecimalFractionBig */ + -20, + {(const uint8_t []){0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10}, 10}, + false, + + QCBOR_ERR_UNEXPECTED_TYPE, /* for GetBigFloat */ + 0, + 0, + + QCBOR_ERR_UNEXPECTED_TYPE, /* for GetBigFloatBig */ + 0, + {(const uint8_t []){0x00}, 0}, + false + }, + + { + "6. Error: Mantissa and exponent inside a Mantissa and exponent", + {(const uint8_t []){0xC4, 0x82, 0x33, + 0xC5, 0x82, 0x19, 0x01, 0x2C, 0x18, 0x64}, 10}, + QCBOR_TAG_REQUIREMENT_TAG, + true, + + QCBOR_ERR_BAD_EXP_AND_MANTISSA, /* for GetNext */ + QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, + 0, + 0, + {(const uint8_t []){0x00}, 0}, + + QCBOR_ERR_BAD_EXP_AND_MANTISSA, /* for GetDecimalFraction */ + 0, + 0, + + QCBOR_ERR_BAD_EXP_AND_MANTISSA, /* for GetDecimalFractionBig */ + 0, + {(const uint8_t []){0x00}, 0}, + false, + + QCBOR_ERR_BAD_EXP_AND_MANTISSA, /* for GetBigFloat */ + 0, + 0, + + QCBOR_ERR_BAD_EXP_AND_MANTISSA, /* for GetBigFloatBig */ + 0, + {(const uint8_t []){0x00}, 0}, + false + }, + { + "7. Tagged 5([-20, 4294967295]) big float, big num mantissa, tag 5 required", + {(const uint8_t []){0xC5, 0x82, 0x33, + 0xC2, 0x44, 0xff, 0xff, 0xff, 0xff}, 9}, + QCBOR_TAG_REQUIREMENT_TAG, + true, + + QCBOR_SUCCESS, /* for GetNext */ + QCBOR_TYPE_BIGFLOAT_POS_BIGNUM, + -20, + 0, + {(const uint8_t []){0xff, 0xff, 0xff, 0xff}, 4}, + + QCBOR_ERR_UNEXPECTED_TYPE, /* for GetDecimalFraction */ + 0, + 0, + + QCBOR_ERR_UNEXPECTED_TYPE, /* for GetDecimalFractionBig */ + -20, + {(const uint8_t []){0x00}, 1}, + false, + + QCBOR_SUCCESS, /* for GetBigFloat */ + -20, + 4294967295, + + QCBOR_SUCCESS, /* for GetBigFloatBig */ + -20, + {(const uint8_t []){0xff, 0xff, 0xff, 0xff}, 4}, + false + }, + + { + /* Special case for test 8. Don't renumber it. */ + "8. Untagged pair with big num (big float or decimal fraction), tag optional", + {(const uint8_t []){0x82, 0x33, 0xC2, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10}, 14}, + QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, + true, + + QCBOR_SUCCESS, /* for GetNext */ + QCBOR_TYPE_ARRAY, + 0, + 0, + {(const uint8_t []){0x00}, 1}, + + QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, /* GetDecimalFraction */ + 0, + 0, + + QCBOR_SUCCESS, /* for GetDecimalFractionBig */ + -20, + {(const uint8_t []){0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10}, 10}, + false, + + QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, /* for GetBigFloat */ + 0, + 0, + + QCBOR_SUCCESS, /* for GetBigFloatBig */ + -20, + {(const uint8_t []){0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10}, 10}, + false + }, + + { + "9. decimal fraction with large exponent and negative big num mantissa", + {(const uint8_t []){0xC4, 0x82, 0x1B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC3, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10}, 23}, + QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, + true, + + QCBOR_SUCCESS, /* for GetNext */ + QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, + 9223372036854775807, + 0, + {(const uint8_t []){0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10}, 10}, + + QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, /* GetDecimalFraction */ + 0, + 0, + + QCBOR_SUCCESS, /* for GetDecimalFractionBig */ + 9223372036854775807, + {(const uint8_t []){0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10}, 10}, + true, + + QCBOR_ERR_UNEXPECTED_TYPE, /* for GetBigFloat */ + 0, + 0, + + QCBOR_ERR_UNEXPECTED_TYPE, /* for GetBigFloatBig */ + 0, + {(const uint8_t []){0x00}, 1}, + false + }, +}; + + + +int32_t ProcessEaMTests(void) +{ + size_t uIndex; + QCBORDecodeContext DCtx; + QCBORItem Item; + QCBORError uError; + int64_t nMantissa, nExponent; + MakeUsefulBufOnStack( MantissaBuf, 200); + UsefulBufC Mantissa; + bool bMantissaIsNegative; + + for(uIndex = 0; uIndex < C_ARRAY_COUNT(pEaMTests, struct EaMTest); uIndex++) { + const struct EaMTest *pT = &pEaMTests[uIndex]; + /* Decode with GetNext */ + QCBORDecode_Init(&DCtx, pT->Input, 0); + + if(uIndex + 1 == 9) { + nExponent = 99; // just to set a break point + } + + uError = QCBORDecode_GetNext(&DCtx, &Item); +#ifdef QCBOR_DISABLE_TAGS + /* Test 8 is a special case when tags are disabled */ + if(pT->bHasTags && uIndex + 1 != 8) { + if(uError != QCBOR_ERR_TAGS_DISABLED) { + return (int32_t)(1+uIndex) * 1000 + 9; + } + } else { +#endif + /* Now check return code, data type, mantissa and exponent */ + if(pT->uExpectedErrorGN != uError) { + return (int32_t)(1+uIndex) * 1000 + 1; + } + if(uError == QCBOR_SUCCESS && pT->uQCBORTypeGN != QCBOR_TYPE_ARRAY) { + if(pT->uQCBORTypeGN != Item.uDataType) { + return (int32_t)(1+uIndex) * 1000 + 2; + } + if(pT->nExponentGN != Item.val.expAndMantissa.nExponent) { + return (int32_t)(1+uIndex) * 1000 + 3; + } + if(Item.uDataType == QCBOR_TYPE_DECIMAL_FRACTION || Item.uDataType == QCBOR_TYPE_BIGFLOAT ) { + if(pT->nMantissaGN != Item.val.expAndMantissa.Mantissa.nInt) { + return (int32_t)(1+uIndex) * 1000 + 4; + } + } else { + if(UsefulBuf_Compare(Item.val.expAndMantissa.Mantissa.bigNum, pT->MantissaGN)) { + return (int32_t)(1+uIndex) * 1000 + 5; + } + } + } +#ifdef QCBOR_DISABLE_TAGS + } +#endif + + /* Decode with GetDecimalFraction */ + QCBORDecode_Init(&DCtx, pT->Input, 0); + QCBORDecode_GetDecimalFraction(&DCtx, + pT->uTagRequirement, + &nMantissa, + &nExponent); + uError = QCBORDecode_GetAndResetError(&DCtx); +#ifdef QCBOR_DISABLE_TAGS + if(pT->bHasTags) { + if(uError != QCBOR_ERR_TAGS_DISABLED) { + return (int32_t)(1+uIndex) * 1000 + 39; + } + } else { +#endif + /* Now check return code, mantissa and exponent */ + if(pT->uExpectedErrorGDF != uError) { + return (int32_t)(1+uIndex) * 1000 + 31; + } + if(uError == QCBOR_SUCCESS) { + if(pT->nExponentGDF != nExponent) { + return (int32_t)(1+uIndex) * 1000 + 32; + } + if(pT->nMantissaGDF != nMantissa) { + return (int32_t)(1+uIndex) * 1000 + 33; + } + } +#ifdef QCBOR_DISABLE_TAGS + } +#endif + + /* Decode with GetDecimalFractionBig */ + QCBORDecode_Init(&DCtx, pT->Input, 0); + QCBORDecode_GetDecimalFractionBig(&DCtx, + pT->uTagRequirement, + MantissaBuf, + &Mantissa, + &bMantissaIsNegative, + &nExponent); + uError = QCBORDecode_GetAndResetError(&DCtx); +#ifdef QCBOR_DISABLE_TAGS + if(pT->bHasTags) { + if(uError != QCBOR_ERR_TAGS_DISABLED) { + return (int32_t)(1+uIndex) * 1000 + 49; + } + } else { +#endif + /* Now check return code, mantissa (bytes and sign) and exponent */ + if(pT->uExpectedErrorGDFB != uError) { + return (int32_t)(1+uIndex) * 1000 + 41; + } + if(uError == QCBOR_SUCCESS) { + if(pT->nExponentGDFB != nExponent) { + return (int32_t)(1+uIndex) * 1000 + 42; + } + if(pT->IsNegativeGDFB != bMantissaIsNegative) { + return (int32_t)(1+uIndex) * 1000 + 43; + } + if(UsefulBuf_Compare(Mantissa, pT->MantissaGDFB)) { + return (int32_t)(1+uIndex) * 1000 + 44; + } + } +#ifdef QCBOR_DISABLE_TAGS + } +#endif + + /* Decode with GetBigFloat */ + QCBORDecode_Init(&DCtx, pT->Input, 0); + QCBORDecode_GetBigFloat(&DCtx, + pT->uTagRequirement, + &nMantissa, + &nExponent); + uError = QCBORDecode_GetAndResetError(&DCtx); +#ifdef QCBOR_DISABLE_TAGS + if(pT->bHasTags) { + if(uError != QCBOR_ERR_TAGS_DISABLED) { + return (int32_t)(1+uIndex) * 1000 + 19; + } + } else { +#endif + /* Now check return code, mantissa and exponent */ + if(pT->uExpectedErrorGBF != uError) { + return (int32_t)(1+uIndex) * 1000 + 11; + } + if(uError == QCBOR_SUCCESS) { + if(pT->nExponentGBF != nExponent) { + return (int32_t)(1+uIndex) * 1000 + 12; + } + if(pT->nMantissaGBF != nMantissa) { + return (int32_t)(1+uIndex) * 1000 + 13; + } + } +#ifdef QCBOR_DISABLE_TAGS + } +#endif + + /* Decode with GetBigFloatBig */ + QCBORDecode_Init(&DCtx, pT->Input, 0); + QCBORDecode_GetBigFloatBig(&DCtx, + pT->uTagRequirement, + MantissaBuf, + &Mantissa, + &bMantissaIsNegative, + &nExponent); + uError = QCBORDecode_GetAndResetError(&DCtx); +#ifdef QCBOR_DISABLE_TAGS + if(pT->bHasTags) { + if(uError != QCBOR_ERR_TAGS_DISABLED) { + return (int32_t)(1+uIndex) * 1000 + 29; + } + } else { +#endif + /* Now check return code, mantissa (bytes and sign) and exponent */ + if(pT->uExpectedErrorGBFB != uError) { + return (int32_t)(1+uIndex) * 1000 + 21; + } + if(uError == QCBOR_SUCCESS) { + if(pT->nExponentGBFB != nExponent) { + return (int32_t)(1+uIndex) * 1000 + 22; + } + if(pT->IsNegativeGBFB != bMantissaIsNegative) { + return (int32_t)(1+uIndex) * 1000 + 23; + } + if(UsefulBuf_Compare(Mantissa, pT->MantissaGBFB)) { + return (int32_t)(1+uIndex) * 1000 + 24; + } + } +#ifdef QCBOR_DISABLE_TAGS + } +#endif } - // 5([ 9223372036854775806, -4759477275222530853137]) - uErr = QCBORDecode_GetNext(&DC, &item); - if(uErr != QCBOR_SUCCESS) { - return 15; - } - if(item.uDataType != QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM || - item.val.expAndMantissa.nExponent != 9223372036854775806 || - UsefulBuf_Compare(item.val.expAndMantissa.Mantissa.bigNum, BN)) { - return 16; - } + return 0; +} + + +int32_t ExponentAndMantissaDecodeTestsSecondary(void) +{ +#ifndef QCBOR_DISABLE_TAGS + QCBORDecodeContext DC; + QCBORError uErr; + QCBORItem item; + + static const uint8_t spBigNumMantissa[] = {0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x010}; + UsefulBufC BN = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNumMantissa); - // 5([ 9223372036854775806, 9223372036854775806])] - uErr = QCBORDecode_GetNext(&DC, &item); - if(uErr != QCBOR_SUCCESS) { - return 17; - } - if(item.uDataType != QCBOR_TYPE_BIGFLOAT || - item.val.expAndMantissa.nExponent != 9223372036854775806 || - item.val.expAndMantissa.Mantissa.nInt!= 9223372036854775806 ) { - return 18; - } - uErr = QCBORDecode_Finish(&DC); - if(uErr != QCBOR_SUCCESS) { - return 18; - } /* Now encode some stuff and then decode it */ uint8_t pBuf[40]; @@ -4752,55 +5230,20 @@ int32_t ExponentAndMantissaDecodeTests(void) return 106; } +#endif /* QCBOR_TAGS_DISABLED */ - int64_t nExp, nMant; - UsefulBuf_MAKE_STACK_UB( MantBuf, 20); - UsefulBufC Mant; - bool bIsNeg; - - QCBORDecode_Init(&DC, - UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedExponentsAndMantissas), - QCBOR_DECODE_MODE_NORMAL); - QCBORDecode_EnterArray(&DC, NULL); - - // 4([-1, 3]), - QCBORDecode_GetDecimalFraction(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nExp, &nMant); - - // 4([-20, 4759477275222530853136]), - QCBORDecode_GetDecimalFractionBig(&DC, QCBOR_TAG_REQUIREMENT_TAG, MantBuf, - &Mant, &bIsNeg, &nExp); - - // 4([9223372036854775807, -4759477275222530853137]), - QCBORDecode_GetDecimalFractionBig(&DC, QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG, - MantBuf, &Mant, &bIsNeg, &nExp); - - // 5([300, 100]), - QCBORDecode_GetBigFloat(&DC, QCBOR_TAG_REQUIREMENT_TAG, &nExp, &nMant); - - // 5([-20, 4759477275222530853136]), - QCBORDecode_GetBigFloatBig(&DC, QCBOR_TAG_REQUIREMENT_TAG, MantBuf, &Mant, - &bIsNeg, &nExp); - - // 5([-9223372036854775807, -4759477275222530853137]) - QCBORDecode_GetBigFloatBig(&DC, QCBOR_TAG_REQUIREMENT_TAG, MantBuf, &Mant, - &bIsNeg, &nExp); - - // 5([ 9223372036854775806, -4759477275222530853137]) - QCBORDecode_GetBigFloatBig(&DC, QCBOR_TAG_REQUIREMENT_TAG, MantBuf, &Mant, - &bIsNeg, &nExp); - - // 5([ 9223372036854775806, 9223372036854775806])] - QCBORDecode_GetBigFloatBig(&DC, QCBOR_TAG_REQUIREMENT_TAG, MantBuf, &Mant, - &bIsNeg, &nExp); + return 0; +} - QCBORDecode_ExitArray(&DC); - uErr = QCBORDecode_Finish(&DC); - if(uErr != QCBOR_SUCCESS) { - return 200; +int32_t ExponentAndMantissaDecodeTests(void) +{ + int32_t rv = ProcessEaMTests(); + if(rv) { + return rv; } - return 0; + return ExponentAndMantissaDecodeTestsSecondary(); } @@ -4845,7 +5288,7 @@ static const struct FailInput ExponentAndMantissaFailures[] = { }; -int32_t ExponentAndMantissaDecodeFailTests() +int32_t ExponentAndMantissaDecodeFailTests(void) { return ProcessFailures(ExponentAndMantissaFailures, C_ARRAY_COUNT(ExponentAndMantissaFailures, @@ -5211,10 +5654,14 @@ static const uint8_t spMapOfEmpty[] = { } */ static const uint8_t spRecoverableMapErrors[] = { +#ifndef QCBOR_DISABLE_TAGS 0xa6, + 0x04, 0xc1, 0xfb, 0x7e, 0x37, 0xe4, 0x3c, 0x88, 0x00, 0x75, 0x9c, 0x01, 0xd8, 0xe0, 0xd8, 0xe1, 0xd8, 0xe2, 0xd8, 0xe3, 0xd8, 0x04, 0x00, +#else + 0xa4, +#endif 0x03, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x04, 0xc1, 0xfb, 0x7e, 0x37, 0xe4, 0x3c, 0x88, 0x00, 0x75, 0x9c, 0x05, 0x00, 0x05, 0x00, 0x08, 0x08, @@ -5282,7 +5729,7 @@ const unsigned char spBadConsumeInput5[] = { -int32_t EnterMapTest() +int32_t EnterMapTest(void) { QCBORItem Item1; QCBORItem ArrayItem; @@ -5487,6 +5934,7 @@ int32_t EnterMapTest() int64_t nInt; QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spRecoverableMapErrors), 0); QCBORDecode_EnterMap(&DCtx, NULL); +#ifndef QCBOR_DISABLE_TAGS QCBORDecode_GetInt64InMapN(&DCtx, 0x01, &nInt); uErr = QCBORDecode_GetError(&DCtx); if(uErr != QCBOR_ERR_TOO_MANY_TAGS) { @@ -5496,6 +5944,7 @@ int32_t EnterMapTest() return 2121; } (void)QCBORDecode_GetAndResetError(&DCtx); +#endif QCBORDecode_GetInt64InMapN(&DCtx, 0x03, &nInt); @@ -5504,11 +5953,13 @@ int32_t EnterMapTest() return 2023; } +#ifndef QCBOR_DISABLE_TAGS QCBORDecode_GetEpochDateInMapN(&DCtx, 0x04, QCBOR_TAG_REQUIREMENT_TAG, &nInt); uErr = QCBORDecode_GetAndResetError(&DCtx); if(uErr != FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_ERR_DATE_OVERFLOW)) { return 2024; } +#endif QCBORDecode_GetInt64InMapN(&DCtx, 0x05, &nInt); uErr = QCBORDecode_GetAndResetError(&DCtx); @@ -5623,6 +6074,7 @@ int32_t EnterMapTest() return 2600; } +#ifndef QCBOR_DISABLE_TAGS QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBadConsumeInput2), 0); QCBORDecode_VGetNextConsume(&DCtx, &Item1); if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) { @@ -5634,6 +6086,8 @@ int32_t EnterMapTest() if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT) { return 2800; } +#endif + QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBadConsumeInput4), 0); QCBORDecode_VGetNextConsume(&DCtx, &Item1); @@ -5676,6 +6130,19 @@ struct NumberConversion { static const struct NumberConversion NumberConversions[] = { +#ifndef QCBOR_DISABLE_TAGS + { + "Big float: INT64_MIN * 2e-1 to test handling of INT64_MIN", + {(uint8_t[]){0xC5, 0x82, 0x20, + 0x3B, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x0ff, 0xff, 0xff, + }, 15}, + -4611686018427387904, /* INT64_MIN / 2 */ + EXP_AND_MANTISSA_ERROR(QCBOR_SUCCESS), + 0, + EXP_AND_MANTISSA_ERROR(QCBOR_ERR_NUMBER_SIGN_CONVERSION), + -4.6116860184273879E+18, + FLOAT_ERR_CODE_NO_FLOAT_HW(EXP_AND_MANTISSA_ERROR(QCBOR_SUCCESS)) + }, { "too large to fit into int64_t", {(uint8_t[]){0xc3, 0x48, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 10}, @@ -5793,77 +6260,6 @@ static const struct NumberConversion NumberConversions[] = { 12.0, FLOAT_ERR_CODE_NO_FLOAT_HW(EXP_AND_MANTISSA_ERROR(QCBOR_SUCCESS)) }, - { - "Positive integer 18446744073709551615", - {(uint8_t[]){0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 9}, - 0, - QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, - 18446744073709551615ULL, - QCBOR_SUCCESS, - 18446744073709551615.0, - FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS) - }, - { - "Positive bignum 0xffff", - {(uint8_t[]){0xC2, 0x42, 0xff, 0xff}, 4}, - 65536-1, - QCBOR_SUCCESS, - 0xffff, - QCBOR_SUCCESS, - 65535.0, - FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS) - }, - { - "Postive integer 0", - {(uint8_t[]){0x0}, 1}, - 0LL, - QCBOR_SUCCESS, - 0ULL, - QCBOR_SUCCESS, - 0.0, - FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS) - }, - { - "Negative integer -18446744073709551616", - {(uint8_t[]){0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 9}, - -9223372036854775807-1, // INT64_MIN - QCBOR_SUCCESS, - 0ULL, - QCBOR_ERR_NUMBER_SIGN_CONVERSION, - -9223372036854775808.0, - FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS) - }, - { - "Double Floating point value 100.3", - {(uint8_t[]){0xfb, 0x40, 0x59, 0x13, 0x33, 0x33, 0x33, 0x33, 0x33}, 9}, - 100L, - FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS), - 100ULL, - FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS), - 100.3, - FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS), - }, - { - "Floating point value NaN 0xfa7fc00000", - {(uint8_t[]){0xfa, 0x7f, 0xc0, 0x00, 0x00}, 5}, - 0, - FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_ERR_FLOAT_EXCEPTION), - 0, - FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_ERR_FLOAT_EXCEPTION), - NAN, - FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS), - }, - { - "half-precision Floating point value -4", - {(uint8_t[]){0xf9, 0xc4, 0x00}, 3}, - // Normal case with all enabled. - -4, - FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(QCBOR_SUCCESS), - 0, - FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(QCBOR_ERR_NUMBER_SIGN_CONVERSION), - -4.0, - FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS) - }, { "Decimal fraction 3/10", {(uint8_t[]){0xC4, 0x82, 0x20, 0x03}, 4}, @@ -5874,17 +6270,6 @@ static const struct NumberConversion NumberConversions[] = { 0.30000000000000004, FLOAT_ERR_CODE_NO_FLOAT_HW(EXP_AND_MANTISSA_ERROR(QCBOR_SUCCESS)) }, - { - "+inifinity single precision", - {(uint8_t[]){0xfa, 0x7f, 0x80, 0x00, 0x00}, 5}, - 0, - FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_ERR_FLOAT_EXCEPTION), - 0, - FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW), - INFINITY, - FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS) - }, - { "extreme pos bignum", {(uint8_t[]){0xc2, 0x59, 0x01, 0x90, @@ -6038,6 +6423,90 @@ static const struct NumberConversion NumberConversions[] = { -INFINITY, FLOAT_ERR_CODE_NO_FLOAT_HW(EXP_AND_MANTISSA_ERROR(QCBOR_SUCCESS)) }, + { + "Positive bignum 0xffff", + {(uint8_t[]){0xC2, 0x42, 0xff, 0xff}, 4}, + 65536-1, + QCBOR_SUCCESS, + 0xffff, + QCBOR_SUCCESS, + 65535.0, + FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS) + }, +#endif /* QCBOR_DISABLE_TAGS */ + { + "Positive integer 18446744073709551615", + {(uint8_t[]){0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 9}, + 0, + QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW, + 18446744073709551615ULL, + QCBOR_SUCCESS, + 18446744073709551615.0, + FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS) + }, + + { + "Postive integer 0", + {(uint8_t[]){0x0}, 1}, + 0LL, + QCBOR_SUCCESS, + 0ULL, + QCBOR_SUCCESS, + 0.0, + FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS) + }, + { + "Negative integer -18446744073709551616", + {(uint8_t[]){0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 9}, + -9223372036854775807-1, // INT64_MIN + QCBOR_SUCCESS, + 0ULL, + QCBOR_ERR_NUMBER_SIGN_CONVERSION, + -9223372036854775808.0, + FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS) + }, + { + "Double Floating point value 100.3", + {(uint8_t[]){0xfb, 0x40, 0x59, 0x13, 0x33, 0x33, 0x33, 0x33, 0x33}, 9}, + 100L, + FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS), + 100ULL, + FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS), + 100.3, + FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS), + }, + { + "Floating point value NaN 0xfa7fc00000", + {(uint8_t[]){0xfa, 0x7f, 0xc0, 0x00, 0x00}, 5}, + 0, + FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_ERR_FLOAT_EXCEPTION), + 0, + FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_ERR_FLOAT_EXCEPTION), + NAN, + FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS), + }, + { + "half-precision Floating point value -4", + {(uint8_t[]){0xf9, 0xc4, 0x00}, 3}, + // Normal case with all enabled. + -4, + FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(QCBOR_SUCCESS), + 0, + FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(QCBOR_ERR_NUMBER_SIGN_CONVERSION), + -4.0, + FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS) + }, + { + "+inifinity single precision", + {(uint8_t[]){0xfa, 0x7f, 0x80, 0x00, 0x00}, 5}, + 0, + FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_ERR_FLOAT_EXCEPTION), + 0, + FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW), + INFINITY, + FLOAT_ERR_CODE_NO_FLOAT_HW(QCBOR_SUCCESS) + }, + }; @@ -6057,7 +6526,7 @@ static int32_t SetUpDecoder(QCBORDecodeContext *DCtx, UsefulBufC CBOR, UsefulBuf } -int32_t IntegerConvertTest() +int32_t IntegerConvertTest(void) { const int nNumTests = C_ARRAY_COUNT(NumberConversions, struct NumberConversion); @@ -6130,7 +6599,7 @@ int32_t IntegerConvertTest() #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS -int32_t CBORTestIssue134() +int32_t CBORTestIssue134(void) { QCBORDecodeContext DCtx; QCBORItem Item; @@ -6143,7 +6612,7 @@ int32_t CBORTestIssue134() UsefulBuf_MAKE_STACK_UB(StringBuf, 200); QCBORDecode_SetMemPool(&DCtx, StringBuf, false); - + do { uCBORError = QCBORDecode_GetNext(&DCtx, &Item); } while (QCBOR_SUCCESS == uCBORError); @@ -6155,6 +6624,23 @@ int32_t CBORTestIssue134() #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ + + +static const uint8_t spSequenceTestInput[] = { + /* 1. The valid date string "1985-04-12" */ + 0x6a, '1','9','8','5','-','0','4','-','1','2', // Date string + + /* 2. */ + 0x00, + + /* 3. A valid epoch date, 1400000000; Tue, 13 May 2014 16:53:20 GMT */ + 0x1a, 0x53, 0x72, 0x4E, 0x00, + + /* 4. */ + 0x62, 'h', 'i', +}; + + int32_t CBORSequenceDecodeTests(void) { QCBORDecodeContext DCtx; @@ -6164,46 +6650,43 @@ int32_t CBORSequenceDecodeTests(void) // --- Test a sequence with extra bytes --- - // The input for the date test happens to be a sequence so it - // is reused. It is a sequence because it doesn't start as - // an array or map. QCBORDecode_Init(&DCtx, - UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spDateTestInput), + UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSequenceTestInput), QCBOR_DECODE_MODE_NORMAL); - // Get the first item + // Get 1. uCBORError = QCBORDecode_GetNext(&DCtx, &Item); if(uCBORError != QCBOR_SUCCESS) { return 1; } - if(Item.uDataType != QCBOR_TYPE_DATE_STRING) { + if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ) { return 2; } uCBORError = QCBORDecode_PartialFinish(&DCtx, &uConsumed); if(uCBORError != QCBOR_ERR_EXTRA_BYTES || - uConsumed != 12) { + uConsumed != 11) { return 102; } - // Get a second item + // Get 2. uCBORError = QCBORDecode_GetNext(&DCtx, &Item); - if(uCBORError != QCBOR_ERR_BAD_OPT_TAG) { + if(uCBORError != QCBOR_SUCCESS) { return 66; } uCBORError = QCBORDecode_PartialFinish(&DCtx, &uConsumed); if(uCBORError != QCBOR_ERR_EXTRA_BYTES || - uConsumed != 14) { + uConsumed != 12) { return 102; } - // Get a third item + // Get 3. uCBORError = QCBORDecode_GetNext(&DCtx, &Item); if(uCBORError != QCBOR_SUCCESS) { return 2; } - if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH) { + if(Item.uDataType != QCBOR_TYPE_INT64) { return 3; } @@ -6220,7 +6703,6 @@ int32_t CBORSequenceDecodeTests(void) return 4; } - // --- Test an empty input ---- uint8_t empty[1]; UsefulBufC Empty = {empty, 0}; @@ -6318,7 +6800,7 @@ int32_t CBORSequenceDecodeTests(void) -int32_t IntToTests() +int32_t IntToTests(void) { int nErrCode; int32_t n32; @@ -6572,7 +7054,7 @@ static const uint8_t spBreakInByteString[] = { }; -int32_t EnterBstrTest() +int32_t EnterBstrTest(void) { UsefulBuf_MAKE_STACK_UB(OutputBuffer, 100); @@ -6734,7 +7216,7 @@ static const uint8_t spTaggedTypes[] = { 0x54, 0x43, 0x46, 0x49, 0x43, 0x41, 0x32 }; -int32_t DecodeTaggedTypeTests() +int32_t DecodeTaggedTypeTests(void) { QCBORDecodeContext DC; QCBORError uErr; @@ -7034,6 +7516,12 @@ int32_t TooLargeInputTest(void) #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS +/* + An array of three map entries + 1) Indefinite length string label for indefinite lenght byte string + 2) Indefinite length string label for an integer + 3) Indefinite length string label for an indefinite-length negative big num + */ static const uint8_t spMapWithIndefLenStrings[] = { 0xa3, 0x7f, 0x61, 'l', 0x64, 'a', 'b', 'e', 'l' , 0x61, '1', 0xff, @@ -7045,7 +7533,7 @@ static const uint8_t spMapWithIndefLenStrings[] = { 0x5f, 0x42, 0x00, 0x01, 0x42, 0x00, 0x01, 0x41, 0x01, 0xff, }; -int32_t SpiffyIndefiniteLengthStringsTests() +int32_t SpiffyIndefiniteLengthStringsTests(void) { QCBORDecodeContext DCtx; @@ -7059,6 +7547,8 @@ int32_t SpiffyIndefiniteLengthStringsTests() UsefulBufC ByteString; QCBORDecode_EnterMap(&DCtx, NULL); QCBORDecode_GetByteStringInMapSZ(&DCtx, "label1", &ByteString); + +#ifndef QCBOR_DISABLE_TAGS if(QCBORDecode_GetAndResetError(&DCtx)) { return 1; } @@ -7083,6 +7573,7 @@ int32_t SpiffyIndefiniteLengthStringsTests() "label2", 0xff, &uDouble); + #ifndef QCBOR_DISABLE_FLOAT_HW_USE if(QCBORDecode_GetAndResetError(&DCtx)) { return 5; @@ -7097,13 +7588,23 @@ int32_t SpiffyIndefiniteLengthStringsTests() #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ #endif /* USEFULBUF_DISABLE_ALL_FLOAT */ - QCBORDecode_ExitMap(&DCtx); if(QCBORDecode_Finish(&DCtx)) { return 99; } +#else /* QCBOR_DISABLE_TAGS */ + /* The big num in the input is a CBOR tag and you can't do + * map lookups in a map with a tag so this test does very little + * when tags are disabled. That is OK, the test coverage is still + * good when they are not. + */ + if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_TAGS_DISABLED) { + return 1002; + } +#endif /*QCBOR_DISABLE_TAGS */ + return 0; } #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ @@ -7179,6 +7680,20 @@ static const uint8_t pWithEmptyMapInDef[] = {0x9f, 0x18, 0x64, 0xbf, 0xff, 0xff} #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */ #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS + +/* +An array of one that contains + a byte string that is tagged 24 which means CBOR-encoded data + the byte string is an indefinite length string + the wrapped byte string is an array of three numbers + [42, 43, 44] + +[ + 24( + (_ h'83', h'18', h'2A182B', h'182C') + ) +] + */ static const uint8_t pWrappedByIndefiniteLength[] = { 0x81, 0xd8, 0x18, @@ -7192,7 +7707,7 @@ static const uint8_t pWrappedByIndefiniteLength[] = { #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ -int32_t PeekAndRewindTest() +int32_t PeekAndRewindTest(void) { QCBORItem Item; QCBORError nCBORError; @@ -7779,6 +8294,7 @@ int32_t PeekAndRewindTest() // Rewind an indefnite length byte-string wrapped sequence #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS + // TODO: rewrite this test to not use tags QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pWrappedByIndefiniteLength), 0); @@ -7787,11 +8303,13 @@ int32_t PeekAndRewindTest() QCBORDecode_EnterArray(&DCtx, NULL); QCBORDecode_EnterBstrWrapped(&DCtx, 2, NULL); +#ifndef QCBOR_DISABLE_TAGS if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_INPUT_TOO_LARGE) { - /* this is what happens when trying to enter - indefinite-length byte string - wrapped CBOR. Tolerate for now. Eventually it needs - to be fixed so this works, but that is not simple. */ + /* TODO: This is what happens when trying to enter + * indefinite-length byte string wrapped CBOR. Tolerate for + * now. Eventually it needs to be fixed so this works, but that + * is not simple. + */ return 7300; } @@ -7805,6 +8323,13 @@ int32_t PeekAndRewindTest() if(i != 42) { return 7220; }*/ + +#else /* QCBOR_DISABLE_TAGS */ + if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_TAGS_DISABLED) { + return 7301; + } +#endif /* QCBOR_DISABLE_TAGS */ + #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */ diff --git a/3rdparty/exported/QCBOR/test/qcbor_encode_tests.c b/3rdparty/exported/QCBOR/test/qcbor_encode_tests.c index bfb4a8375ed0..6e569cac82fb 100644 --- a/3rdparty/exported/QCBOR/test/qcbor_encode_tests.c +++ b/3rdparty/exported/QCBOR/test/qcbor_encode_tests.c @@ -1,7 +1,7 @@ /*============================================================================== Copyright (c) 2016-2018, The Linux Foundation. Copyright (c) 2018-2021, Laurence Lundblade. - All rights reserved. + Copyright (c) 2022, Arm Limited. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -143,7 +143,7 @@ static uint8_t spBigBuf[2200]; /* Some very minimal tests. */ -int32_t BasicEncodeTest() +int32_t BasicEncodeTest(void) { // Very simple CBOR, a map with one boolean that is true in it QCBOREncodeContext EC; @@ -281,7 +281,7 @@ int32_t BasicEncodeTest() static const uint8_t spExpectedEncodedAll[] = { - 0x98, 0x22, 0x66, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x32, 0xd8, + 0x98, 0x23, 0x66, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x32, 0xd8, 0x64, 0x1a, 0x05, 0x5d, 0x23, 0x15, 0x65, 0x49, 0x4e, 0x54, 0x36, 0x34, 0xd8, 0x4c, 0x1b, 0x00, 0x00, 0x00, 0x12, 0x16, 0xaf, 0x2b, 0x15, 0x00, 0x38, 0x2b, 0xa4, 0x63, 0x4c, 0x42, @@ -296,12 +296,14 @@ static const uint8_t spExpectedEncodedAll[] = { 0x69, 0x65, 0xc1, 0x1a, 0x53, 0x72, 0x4e, 0x00, 0x66, 0x74, 0x69, 0x6d, 0x65, 0x28, 0x29, 0xc1, 0x1a, 0x58, 0x0d, 0x41, 0x72, 0x39, 0x07, 0xb0, 0xc1, 0x1a, 0x58, 0x0d, 0x3f, 0x76, - 0x42, 0xff, 0x00, 0xa3, 0x66, 0x62, 0x69, 0x6e, 0x62, 0x69, - 0x6e, 0xda, 0x00, 0x01, 0x86, 0xa0, 0x41, 0x00, 0x66, 0x62, + 0x42, 0xff, 0x00, 0xa4, 0x66, 0x62, 0x69, 0x6e, 0x62, 0x69, + 0x6e, 0xda, 0x00, 0x01, 0x86, 0xa0, 0x41, 0x00, + 0x65, 0x65, 0x6D, 0x70, 0x74, 0x79, 0x40, + 0x66, 0x62, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x43, 0x01, 0x02, 0x03, 0x00, 0x44, 0x04, 0x02, 0x03, 0xfe, 0x6f, 0x62, 0x61, 0x72, 0x20, 0x62, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x20, 0x62, 0x61, - 0x72, 0x64, 0x6f, 0x6f, 0x66, 0x0a, 0xd8, 0x20, 0x78, 0x6b, + 0x72, 0x64, 0x6f, 0x6f, 0x66, 0x0a, 0x60, 0xd8, 0x20, 0x78, 0x6b, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x71, 0x75, 0x65, 0x73, 0x74, @@ -553,6 +555,7 @@ static void AddAll(QCBOREncodeContext *pECtx) QCBOREncode_AddSZString(pECtx, "binbin"); QCBOREncode_AddTag(pECtx, 100000); QCBOREncode_AddBytes(pECtx, ((UsefulBufC) {(uint8_t []){0x00}, 1})); + QCBOREncode_AddBytesToMap(pECtx, "empty", NULLUsefulBufC); // Empty string QCBOREncode_AddBytesToMap(pECtx, "blabel", ((UsefulBufC) {(uint8_t []){0x01, 0x02, 0x03}, 3})); QCBOREncode_AddBytesToMapN(pECtx, 0, ((UsefulBufC){(uint8_t []){0x04, 0x02, 0x03, 0xfe}, 4})); QCBOREncode_CloseMap(pECtx); @@ -560,6 +563,8 @@ static void AddAll(QCBOREncodeContext *pECtx) /* text blobs */ QCBOREncode_AddText(pECtx, UsefulBuf_FROM_SZ_LITERAL("bar bar foo bar")); QCBOREncode_AddSZString(pECtx, "oof\n"); + QCBOREncode_AddText(pECtx, NULLUsefulBufC); // Empty string + const char *szURL = "http://stackoverflow.com/questions/28059697/how-do-i-toggle-between-debug-and-release-builds-in-xcode-6-7-8"; QCBOREncode_AddURI(pECtx, UsefulBuf_FromSZ(szURL)); @@ -686,7 +691,7 @@ static void AddAll(QCBOREncodeContext *pECtx) } -int32_t AllAddMethodsTest() +int32_t AllAddMethodsTest(void) { /* Improvement: this test should be broken down into several so it is more * managable. Tags and labels could be more sensible */ @@ -814,7 +819,7 @@ static const uint8_t spExpectedEncodedInts[] = { to expected values generated from http://cbor.me. */ -int32_t IntegerValuesTest1() +int32_t IntegerValuesTest1(void) { QCBOREncodeContext ECtx; int nReturn = 0; @@ -899,7 +904,7 @@ int32_t IntegerValuesTest1() static const uint8_t spExpectedEncodedSimple[] = { 0x85, 0xf5, 0xf4, 0xf6, 0xf7, 0xa1, 0x65, 0x55, 0x4e, 0x44, 0x65, 0x66, 0xf7}; -int32_t SimpleValuesTest1() +int32_t SimpleValuesTest1(void) { QCBOREncodeContext ECtx; int nReturn = 0; @@ -946,7 +951,7 @@ int32_t SimpleValuesTest1() static const uint8_t spExpectedEncodedSimpleIndefiniteLength[] = { 0x9f, 0xf5, 0xf4, 0xf6, 0xf7, 0xbf, 0x65, 0x55, 0x4e, 0x44, 0x65, 0x66, 0xf7, 0xff, 0xff}; -int32_t SimpleValuesIndefiniteLengthTest1() +int32_t SimpleValuesIndefiniteLengthTest1(void) { QCBOREncodeContext ECtx; int nReturn = 0; @@ -1141,7 +1146,7 @@ static const uint8_t EncodeLengthThirtyone[] = { 0x31 }; -int32_t EncodeLengthThirtyoneTest() +int32_t EncodeLengthThirtyoneTest(void) { QCBOREncodeContext ECtx; int nReturn = 0; @@ -1234,7 +1239,7 @@ static const uint8_t spExpectedEncodedDates[] = { 0x30, 0x2E, 0x35, 0x32, 0x5A, 0x62, 0x53, 0x59, 0xD8, 0x64, 0x39, 0x29, 0xB3, 0x18, 0x2D, 0x19, 0x0F, 0x9A}; -int32_t EncodeDateTest() +int32_t EncodeDateTest(void) { QCBOREncodeContext ECtx; @@ -1291,7 +1296,7 @@ int32_t EncodeDateTest() } -int32_t ArrayNestingTest1() +int32_t ArrayNestingTest1(void) { QCBOREncodeContext ECtx; int i; @@ -1314,7 +1319,7 @@ int32_t ArrayNestingTest1() -int32_t ArrayNestingTest2() +int32_t ArrayNestingTest2(void) { QCBOREncodeContext ECtx; int i; @@ -1338,7 +1343,7 @@ int32_t ArrayNestingTest2() -int32_t ArrayNestingTest3() +int32_t ArrayNestingTest3(void) { QCBOREncodeContext ECtx; int i; @@ -1455,7 +1460,7 @@ static const uint8_t spEncodeRawExpected[] = { 0xff, 0xff}; -int32_t EncodeRawTest() +int32_t EncodeRawTest(void) { QCBOREncodeContext ECtx; @@ -1578,7 +1583,7 @@ static const uint8_t spValidMapEncoded[] = { 0x73 } ; -int32_t MapEncodeTest() +int32_t MapEncodeTest(void) { uint8_t *pEncodedMaps; size_t nEncodedMapLen; @@ -1734,7 +1739,7 @@ static const uint8_t spExpectedRTIC[] = { 0xaa, 0xbb, 0x01, 0x01}; -int32_t RTICResultsTest() +int32_t RTICResultsTest(void) { const UsefulBufC Encoded = FormatRTICResults(CBOR_SIMPLEV_FALSE, 1477263730, "recent", "0xA1eC5001", @@ -1772,7 +1777,7 @@ static const uint8_t spExpectedForBstrWrapCancel[] = {0x82, 0x19, 0x01, 0xC3, 0x /* * bstr wrapping test */ -int BstrWrapTest() +int32_t BstrWrapTest(void) { QCBOREncodeContext EC; @@ -1896,7 +1901,7 @@ int BstrWrapTest() -int32_t BstrWrapErrorTest() +int32_t BstrWrapErrorTest(void) { QCBOREncodeContext EC; UsefulBufC Wrapped; @@ -1963,7 +1968,7 @@ int32_t BstrWrapErrorTest() if(uError != QCBOR_ERR_ARRAY_NESTING_TOO_DEEP) { return (int32_t)(300 + uError); } - + return 0; } @@ -2207,7 +2212,7 @@ static int32_t DecodeNextNested2(UsefulBufC Wrapped) } -int32_t BstrWrapNestTest() +int32_t BstrWrapNestTest(void) { QCBOREncodeContext EC; QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf)); @@ -2350,7 +2355,7 @@ static const uint8_t pProtectedHeaders[] = {0xa1, 0x01, 0x26}; C.2.1. This doesn't actually verify the signature (however the t_cose implementation does). */ -int32_t CoseSign1TBSTest() +int32_t CoseSign1TBSTest(void) { // All of this is from RFC 8152 C.2.1 const char *szKid = "11"; @@ -2474,7 +2479,7 @@ int32_t CoseSign1TBSTest() } -int32_t EncodeErrorTests() +int32_t EncodeErrorTests(void) { QCBOREncodeContext EC; QCBORError uErr; @@ -2767,7 +2772,7 @@ static const uint8_t spExpectedExponentAndMantissaMap[] = { }; -int32_t ExponentAndMantissaEncodeTests() +int32_t ExponentAndMantissaEncodeTests(void) { QCBOREncodeContext EC; UsefulBufC EncodedExponentAndMantissa; @@ -2879,7 +2884,7 @@ int32_t ExponentAndMantissaEncodeTests() #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */ -int32_t QCBORHeadTest() +int32_t QCBORHeadTest(void) { /* This test doesn't have to be extensive, because just about every * other test exercises QCBOREncode_EncodeHead(). diff --git a/3rdparty/exported/QCBOR/test/run_tests.c b/3rdparty/exported/QCBOR/test/run_tests.c index f28f526c0bdc..f2baaf114efa 100644 --- a/3rdparty/exported/QCBOR/test/run_tests.c +++ b/3rdparty/exported/QCBOR/test/run_tests.c @@ -99,8 +99,11 @@ static test_entry s_tests[] = { TEST_ENTRY(BasicEncodeTest), TEST_ENTRY(NestedMapTest), TEST_ENTRY(BignumParseTest), +#ifndef QCBOR_DISABLE_TAGS TEST_ENTRY(OptTagParseTest), TEST_ENTRY(DateParseTest), + TEST_ENTRY(DecodeTaggedTypeTests), +#endif /* QCBOR_DISABLE_TAGS */ TEST_ENTRY(SpiffyDateDecodeTest), TEST_ENTRY(ShortBufferParseTest2), TEST_ENTRY(ShortBufferParseTest), @@ -136,12 +139,12 @@ static test_entry s_tests[] = { TEST_ENTRY(EncodeLengthThirtyoneTest), TEST_ENTRY(CBORSequenceDecodeTests), TEST_ENTRY(IntToTests), - TEST_ENTRY(DecodeTaggedTypeTests), TEST_ENTRY(PeekAndRewindTest), -#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA - TEST_ENTRY(EncodeLengthThirtyoneTest), +#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA TEST_ENTRY(ExponentAndMantissaDecodeTests), +#ifndef QCBOR_DISABLE_TAGS TEST_ENTRY(ExponentAndMantissaDecodeFailTests), +#endif /* QCBOR_DISABLE_TAGS */ TEST_ENTRY(ExponentAndMantissaEncodeTests), #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */ TEST_ENTRY(ParseEmptyMapInMapTest), diff --git a/3rdparty/exported/QCBOR/ub-example.c b/3rdparty/exported/QCBOR/ub-example.c index 4c48d31a935c..996cf3a9071e 100644 --- a/3rdparty/exported/QCBOR/ub-example.c +++ b/3rdparty/exported/QCBOR/ub-example.c @@ -214,7 +214,7 @@ ExpandxUBAdaptor(const UsefulBufC Input, #define INPUT "xyz123xyz" -int32_t RunUsefulBufExample() +int32_t RunUsefulBufExample(void) { /* ------------ UsefulBuf examples ------------- */ UsefulBufC Input = UsefulBuf_FROM_SZ_LITERAL(INPUT); diff --git a/CHANGELOG.md b/CHANGELOG.md index fee241d57c4c..9f7623776f61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [5.0.0-dev2] + +[5.0.0-dev2]: https://github.com/microsoft/CCF/releases/tag/ccf-5.0.0-dev2 + +- Updated QCBOR from `1.1` to `1.2`. + ## [5.0.0-dev1] [5.0.0-dev1]: https://github.com/microsoft/CCF/releases/tag/ccf-5.0.0-dev1 diff --git a/cgmanifest.json b/cgmanifest.json index 98ca3daa549e..781a146bdfcd 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -141,7 +141,7 @@ "type": "git", "git": { "repositoryUrl": "https://github.com/laurencelundblade/QCBOR", - "commitHash": "07653df2bbdb2d090d98d0df514fa019ac23dff3" + "commitHash": "92d3f89030baff4af7be8396c563e6c8ef263622" } } },