mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 05:13:46 -07:00
added tinycbor
This commit is contained in:
parent
fd1c0cac79
commit
f8c0ec53bd
17 changed files with 5764 additions and 0 deletions
666
client/tinycbor/cborvalidation.c
Normal file
666
client/tinycbor/cborvalidation.c
Normal file
|
@ -0,0 +1,666 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 Intel Corporation
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
** of this software and associated documentation files (the "Software"), to deal
|
||||
** in the Software without restriction, including without limitation the rights
|
||||
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
** copies of the Software, and to permit persons to whom the Software is
|
||||
** furnished to do so, subject to the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included in
|
||||
** all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
** THE SOFTWARE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#define _BSD_SOURCE 1
|
||||
#define _DEFAULT_SOURCE 1
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
# define __STDC_LIMIT_MACROS 1
|
||||
#endif
|
||||
|
||||
#include "cbor.h"
|
||||
#include "cborinternal_p.h"
|
||||
#include "compilersupport_p.h"
|
||||
#include "utf8_p.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifndef CBOR_NO_FLOATING_POINT
|
||||
# include <float.h>
|
||||
# include <math.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef CBOR_PARSER_MAX_RECURSIONS
|
||||
# define CBOR_PARSER_MAX_RECURSIONS 1024
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \addtogroup CborParsing
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \enum CborValidationFlags
|
||||
* The CborValidationFlags enum contains flags that control the validation of a
|
||||
* CBOR stream.
|
||||
*
|
||||
* \value CborValidateBasic Validates only the syntactic correctedness of the stream.
|
||||
* \value CborValidateCanonical Validates that the stream is in canonical format, according to
|
||||
* RFC 7049 section 3.9.
|
||||
* \value CborValidateStrictMode Performs strict validation, according to RFC 7049 section 3.10.
|
||||
* \value CborValidateStrictest Attempt to perform the strictest validation we know of.
|
||||
*
|
||||
* \value CborValidateShortestIntegrals (Canonical) Validate that integral numbers and lengths are
|
||||
* enconded in their shortest form possible.
|
||||
* \value CborValidateShortestFloatingPoint (Canonical) Validate that floating-point numbers are encoded
|
||||
* in their shortest form possible.
|
||||
* \value CborValidateShortestNumbers (Canonical) Validate both integral and floating-point numbers
|
||||
* are in their shortest form possible.
|
||||
* \value CborValidateNoIndeterminateLength (Canonical) Validate that no string, array or map uses
|
||||
* indeterminate length encoding.
|
||||
* \value CborValidateMapIsSorted (Canonical & Strict mode) Validate that map keys appear in
|
||||
* sorted order.
|
||||
* \value CborValidateMapKeysAreUnique (Strict mode) Validate that map keys are unique.
|
||||
* \value CborValidateTagUse (Strict mode) Validate that known tags are used with the
|
||||
* correct types. This does not validate that the content of
|
||||
* those types is syntactically correct. For example, this
|
||||
* option validates that tag 1 (DateTimeString) is used with
|
||||
* a Text String, but it does not validate that the string is
|
||||
* a valid date/time representation.
|
||||
* \value CborValidateUtf8 (Strict mode) Validate that text strings are appropriately
|
||||
* encoded in UTF-8.
|
||||
* \value CborValidateMapKeysAreString Validate that all map keys are text strings.
|
||||
* \value CborValidateNoUndefined Validate that no elements of type "undefined" are present.
|
||||
* \value CborValidateNoTags Validate that no tags are used.
|
||||
* \value CborValidateFiniteFloatingPoint Validate that all floating point numbers are finite (no NaN or
|
||||
* infinities are allowed).
|
||||
* \value CborValidateCompleteData Validate that the stream is complete and there is no more data
|
||||
* in the buffer.
|
||||
* \value CborValidateNoUnknownSimpleTypesSA Validate that all Standards Action simple types are registered
|
||||
* with IANA.
|
||||
* \value CborValidateNoUnknownSimpleTypes Validate that all simple types used are registered with IANA.
|
||||
* \value CborValidateNoUnknownTagsSA Validate that all Standard Actions tags are registered with IANA.
|
||||
* \value CborValidateNoUnknownTagsSR Validate that all Standard Actions and Specification Required tags
|
||||
* are registered with IANA (see below for limitations).
|
||||
* \value CborValidateNoUnkonwnTags Validate that all tags are registered with IANA
|
||||
* (see below for limitations).
|
||||
*
|
||||
* \par Simple type registry
|
||||
* The CBOR specification requires that registration for use of the first 19
|
||||
* simple types must be done by way of Standards Action. The rest of the simple
|
||||
* types only require a specification. The official list can be obtained from
|
||||
* https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xhtml.
|
||||
*
|
||||
* \par
|
||||
* There are no registered simple types recognized by this release of TinyCBOR
|
||||
* (beyond those defined by RFC 7049).
|
||||
*
|
||||
* \par Tag registry
|
||||
* The CBOR specification requires that registration for use of the first 23
|
||||
* tags must be done by way of Standards Action. The next up to tag 255 only
|
||||
* require a specification. Finally, all other tags can be registered on a
|
||||
* first-come-first-serve basis. The official list can be ontained from
|
||||
* https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml.
|
||||
*
|
||||
* \par
|
||||
* Given the variability of this list, TinyCBOR cannot recognize all tags
|
||||
* registered with IANA. Instead, the implementation only recognizes tags
|
||||
* that are backed by an RFC.
|
||||
*
|
||||
* \par
|
||||
* These are the tags known to the current TinyCBOR release:
|
||||
<table>
|
||||
<tr>
|
||||
<th>Tag</th>
|
||||
<th>Data Item</th>
|
||||
<th>Semantics</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>UTF-8 text string</td>
|
||||
<td>Standard date/time string</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>integer</td>
|
||||
<td>Epoch-based date/time</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>byte string</td>
|
||||
<td>Positive bignum</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>byte string</td>
|
||||
<td>Negative bignum</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td>array</td>
|
||||
<td>Decimal fraction</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td>array</td>
|
||||
<td>Bigfloat</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>16</td>
|
||||
<td>array</td>
|
||||
<td>COSE Single Recipient Encrypted Data Object (RFC 8152)</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>17</td>
|
||||
<td>array</td>
|
||||
<td>COSE Mac w/o Recipients Object (RFC 8152)</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>18</td>
|
||||
<td>array</td>
|
||||
<td>COSE Single Signer Data Object (RFC 8162)</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>21</td>
|
||||
<td>byte string, array, map</td>
|
||||
<td>Expected conversion to base64url encoding</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>22</td>
|
||||
<td>byte string, array, map</td>
|
||||
<td>Expected conversion to base64 encoding</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>23</td>
|
||||
<td>byte string, array, map</td>
|
||||
<td>Expected conversion to base16 encoding</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>24</td>
|
||||
<td>byte string</td>
|
||||
<td>Encoded CBOR data item</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>32</td>
|
||||
<td>UTF-8 text string</td>
|
||||
<td>URI</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>33</td>
|
||||
<td>UTF-8 text string</td>
|
||||
<td>base64url</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>34</td>
|
||||
<td>UTF-8 text string</td>
|
||||
<td>base64</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>35</td>
|
||||
<td>UTF-8 text string</td>
|
||||
<td>Regular expression</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>36</td>
|
||||
<td>UTF-8 text string</td>
|
||||
<td>MIME message</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>96</td>
|
||||
<td>array</td>
|
||||
<td>COSE Encrypted Data Object (RFC 8152)</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>97</td>
|
||||
<td>array</td>
|
||||
<td>COSE MACed Data Object (RFC 8152)</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>98</td>
|
||||
<td>array</td>
|
||||
<td>COSE Signed Data Object (RFC 8152)</td>
|
||||
</td>
|
||||
<tr>
|
||||
<td>55799</td>
|
||||
<td>any</td>
|
||||
<td>Self-describe CBOR</td>
|
||||
</td>
|
||||
</table>
|
||||
*/
|
||||
|
||||
struct KnownTagData { uint32_t tag; uint32_t types; };
|
||||
static const struct KnownTagData knownTagData[] = {
|
||||
{ 0, (uint32_t)CborTextStringType },
|
||||
{ 1, (uint32_t)(CborIntegerType+1) },
|
||||
{ 2, (uint32_t)CborByteStringType },
|
||||
{ 3, (uint32_t)CborByteStringType },
|
||||
{ 4, (uint32_t)CborArrayType },
|
||||
{ 5, (uint32_t)CborArrayType },
|
||||
{ 16, (uint32_t)CborArrayType },
|
||||
{ 17, (uint32_t)CborArrayType },
|
||||
{ 18, (uint32_t)CborArrayType },
|
||||
{ 21, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) },
|
||||
{ 22, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) },
|
||||
{ 23, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) },
|
||||
{ 24, (uint32_t)CborByteStringType },
|
||||
{ 32, (uint32_t)CborTextStringType },
|
||||
{ 33, (uint32_t)CborTextStringType },
|
||||
{ 34, (uint32_t)CborTextStringType },
|
||||
{ 35, (uint32_t)CborTextStringType },
|
||||
{ 36, (uint32_t)CborTextStringType },
|
||||
{ 96, (uint32_t)CborArrayType },
|
||||
{ 97, (uint32_t)CborArrayType },
|
||||
{ 98, (uint32_t)CborArrayType },
|
||||
{ 55799, 0U }
|
||||
};
|
||||
|
||||
static CborError validate_value(CborValue *it, uint32_t flags, int recursionLeft);
|
||||
|
||||
static inline CborError validate_utf8_string(const void *ptr, size_t n)
|
||||
{
|
||||
const uint8_t *buffer = (const uint8_t *)ptr;
|
||||
const uint8_t * const end = buffer + n;
|
||||
while (buffer < end) {
|
||||
uint32_t uc = get_utf8(&buffer, end);
|
||||
if (uc == ~0U)
|
||||
return CborErrorInvalidUtf8TextString;
|
||||
}
|
||||
return CborNoError;
|
||||
}
|
||||
|
||||
static inline CborError validate_simple_type(uint8_t simple_type, uint32_t flags)
|
||||
{
|
||||
/* At current time, all known simple types are those from RFC 7049,
|
||||
* which are parsed by the parser into different CBOR types.
|
||||
* That means that if we've got here, the type is unknown */
|
||||
if (simple_type < 32)
|
||||
return (flags & CborValidateNoUnknownSimpleTypesSA) ? CborErrorUnknownSimpleType : CborNoError;
|
||||
return (flags & CborValidateNoUnknownSimpleTypes) == CborValidateNoUnknownSimpleTypes ?
|
||||
CborErrorUnknownSimpleType : CborNoError;
|
||||
}
|
||||
|
||||
static inline CborError validate_number(const CborValue *it, CborType type, uint32_t flags)
|
||||
{
|
||||
CborError err = CborNoError;
|
||||
const uint8_t *ptr = it->ptr;
|
||||
size_t bytesUsed, bytesNeeded;
|
||||
uint64_t value;
|
||||
|
||||
if ((flags & CborValidateShortestIntegrals) == 0)
|
||||
return err;
|
||||
if (type >= CborHalfFloatType && type <= CborDoubleType)
|
||||
return err; /* checked elsewhere */
|
||||
|
||||
err = _cbor_value_extract_number(&ptr, it->parser->end, &value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
bytesUsed = (size_t)(ptr - it->ptr - 1);
|
||||
bytesNeeded = 0;
|
||||
if (value >= Value8Bit)
|
||||
++bytesNeeded;
|
||||
if (value > 0xffU)
|
||||
++bytesNeeded;
|
||||
if (value > 0xffffU)
|
||||
bytesNeeded += 2;
|
||||
if (value > 0xffffffffU)
|
||||
bytesNeeded += 4;
|
||||
if (bytesNeeded < bytesUsed)
|
||||
return CborErrorOverlongEncoding;
|
||||
return CborNoError;
|
||||
}
|
||||
|
||||
static inline CborError validate_tag(CborValue *it, CborTag tag, uint32_t flags, int recursionLeft)
|
||||
{
|
||||
CborType type = cbor_value_get_type(it);
|
||||
const size_t knownTagCount = sizeof(knownTagData) / sizeof(knownTagData[0]);
|
||||
const struct KnownTagData *tagData = knownTagData;
|
||||
const struct KnownTagData * const knownTagDataEnd = knownTagData + knownTagCount;
|
||||
|
||||
if (!recursionLeft)
|
||||
return CborErrorNestingTooDeep;
|
||||
if (flags & CborValidateNoTags)
|
||||
return CborErrorExcludedType;
|
||||
|
||||
/* find the tag data, if any */
|
||||
for ( ; tagData != knownTagDataEnd; ++tagData) {
|
||||
if (tagData->tag < tag)
|
||||
continue;
|
||||
if (tagData->tag > tag)
|
||||
tagData = NULL;
|
||||
break;
|
||||
}
|
||||
if (tagData == knownTagDataEnd)
|
||||
tagData = NULL;
|
||||
|
||||
if (flags & CborValidateNoUnknownTags && !tagData) {
|
||||
/* tag not found */
|
||||
if (flags & CborValidateNoUnknownTagsSA && tag < 24)
|
||||
return CborErrorUnknownTag;
|
||||
if ((flags & CborValidateNoUnknownTagsSR) == CborValidateNoUnknownTagsSR && tag < 256)
|
||||
return CborErrorUnknownTag;
|
||||
if ((flags & CborValidateNoUnknownTags) == CborValidateNoUnknownTags)
|
||||
return CborErrorUnknownTag;
|
||||
}
|
||||
|
||||
if (flags & CborValidateTagUse && tagData && tagData->types) {
|
||||
uint32_t allowedTypes = tagData->types;
|
||||
|
||||
/* correct Integer so it's not zero */
|
||||
if (type == CborIntegerType)
|
||||
type = (CborType)(type + 1);
|
||||
|
||||
while (allowedTypes) {
|
||||
if ((uint8_t)(allowedTypes & 0xff) == type)
|
||||
break;
|
||||
allowedTypes >>= 8;
|
||||
}
|
||||
if (!allowedTypes)
|
||||
return CborErrorInappropriateTagForType;
|
||||
}
|
||||
|
||||
return validate_value(it, flags, recursionLeft);
|
||||
}
|
||||
|
||||
#ifndef CBOR_NO_FLOATING_POINT
|
||||
static inline CborError validate_floating_point(CborValue *it, CborType type, uint32_t flags)
|
||||
{
|
||||
CborError err;
|
||||
int r;
|
||||
double val;
|
||||
float valf;
|
||||
uint16_t valf16;
|
||||
|
||||
if (type != CborDoubleType) {
|
||||
if (type == CborFloatType) {
|
||||
err = cbor_value_get_float(it, &valf);
|
||||
val = valf;
|
||||
} else {
|
||||
# ifdef CBOR_NO_HALF_FLOAT_TYPE
|
||||
(void)valf16;
|
||||
return CborErrorUnsupportedType;
|
||||
# else
|
||||
err = cbor_value_get_half_float(it, &valf16);
|
||||
val = decode_half(valf16);
|
||||
# endif
|
||||
}
|
||||
} else {
|
||||
err = cbor_value_get_double(it, &val);
|
||||
}
|
||||
cbor_assert(err == CborNoError); /* can't fail */
|
||||
|
||||
r = fpclassify(val);
|
||||
if (r == FP_NAN || r == FP_INFINITE) {
|
||||
if (flags & CborValidateFiniteFloatingPoint)
|
||||
return CborErrorExcludedValue;
|
||||
if (flags & CborValidateShortestFloatingPoint) {
|
||||
if (type == CborDoubleType)
|
||||
return CborErrorOverlongEncoding;
|
||||
# ifndef CBOR_NO_HALF_FLOAT_TYPE
|
||||
if (type == CborFloatType)
|
||||
return CborErrorOverlongEncoding;
|
||||
if (r == FP_NAN && valf16 != 0x7e00)
|
||||
return CborErrorImproperValue;
|
||||
if (r == FP_INFINITE && valf16 != 0x7c00 && valf16 != 0xfc00)
|
||||
return CborErrorImproperValue;
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & CborValidateShortestFloatingPoint && type > CborHalfFloatType) {
|
||||
if (type == CborDoubleType) {
|
||||
valf = (float)val;
|
||||
if ((double)valf == val)
|
||||
return CborErrorOverlongEncoding;
|
||||
}
|
||||
# ifndef CBOR_NO_HALF_FLOAT_TYPE
|
||||
if (type == CborFloatType) {
|
||||
valf16 = encode_half(valf);
|
||||
if (valf == decode_half(valf16))
|
||||
return CborErrorOverlongEncoding;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
return CborNoError;
|
||||
}
|
||||
#endif
|
||||
|
||||
static CborError validate_container(CborValue *it, int containerType, uint32_t flags, int recursionLeft)
|
||||
{
|
||||
CborError err;
|
||||
const uint8_t *previous = NULL;
|
||||
const uint8_t *previous_end = NULL;
|
||||
|
||||
if (!recursionLeft)
|
||||
return CborErrorNestingTooDeep;
|
||||
|
||||
while (!cbor_value_at_end(it)) {
|
||||
const uint8_t *current = cbor_value_get_next_byte(it);
|
||||
|
||||
if (containerType == CborMapType) {
|
||||
if (flags & CborValidateMapKeysAreString) {
|
||||
CborType type = cbor_value_get_type(it);
|
||||
if (type == CborTagType) {
|
||||
/* skip the tags */
|
||||
CborValue copy = *it;
|
||||
err = cbor_value_skip_tag(©);
|
||||
if (err)
|
||||
return err;
|
||||
type = cbor_value_get_type(©);
|
||||
}
|
||||
if (type != CborTextStringType)
|
||||
return CborErrorMapKeyNotString;
|
||||
}
|
||||
}
|
||||
|
||||
err = validate_value(it, flags, recursionLeft);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (containerType != CborMapType)
|
||||
continue;
|
||||
|
||||
if (flags & CborValidateMapIsSorted) {
|
||||
if (previous) {
|
||||
uint64_t len1, len2;
|
||||
const uint8_t *ptr;
|
||||
|
||||
/* extract the two lengths */
|
||||
ptr = previous;
|
||||
_cbor_value_extract_number(&ptr, it->parser->end, &len1);
|
||||
ptr = current;
|
||||
_cbor_value_extract_number(&ptr, it->parser->end, &len2);
|
||||
|
||||
if (len1 > len2)
|
||||
return CborErrorMapNotSorted;
|
||||
if (len1 == len2) {
|
||||
size_t bytelen1 = (size_t)(previous_end - previous);
|
||||
size_t bytelen2 = (size_t)(it->ptr - current);
|
||||
int r = memcmp(previous, current, bytelen1 <= bytelen2 ? bytelen1 : bytelen2);
|
||||
|
||||
if (r == 0 && bytelen1 != bytelen2)
|
||||
r = bytelen1 < bytelen2 ? -1 : +1;
|
||||
if (r > 0)
|
||||
return CborErrorMapNotSorted;
|
||||
if (r == 0 && (flags & CborValidateMapKeysAreUnique) == CborValidateMapKeysAreUnique)
|
||||
return CborErrorMapKeysNotUnique;
|
||||
}
|
||||
}
|
||||
|
||||
previous = current;
|
||||
previous_end = it->ptr;
|
||||
}
|
||||
|
||||
/* map: that was the key, so get the value */
|
||||
err = validate_value(it, flags, recursionLeft);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
return CborNoError;
|
||||
}
|
||||
|
||||
static CborError validate_value(CborValue *it, uint32_t flags, int recursionLeft)
|
||||
{
|
||||
CborError err;
|
||||
CborType type = cbor_value_get_type(it);
|
||||
|
||||
if (cbor_value_is_length_known(it)) {
|
||||
err = validate_number(it, type, flags);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
if (flags & CborValidateNoIndeterminateLength)
|
||||
return CborErrorUnknownLength;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case CborArrayType:
|
||||
case CborMapType: {
|
||||
/* recursive type */
|
||||
CborValue recursed;
|
||||
err = cbor_value_enter_container(it, &recursed);
|
||||
if (!err)
|
||||
err = validate_container(&recursed, type, flags, recursionLeft - 1);
|
||||
if (err) {
|
||||
it->ptr = recursed.ptr;
|
||||
return err;
|
||||
}
|
||||
err = cbor_value_leave_container(it, &recursed);
|
||||
if (err)
|
||||
return err;
|
||||
return CborNoError;
|
||||
}
|
||||
|
||||
case CborIntegerType: {
|
||||
uint64_t val;
|
||||
err = cbor_value_get_raw_integer(it, &val);
|
||||
cbor_assert(err == CborNoError); /* can't fail */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CborByteStringType:
|
||||
case CborTextStringType: {
|
||||
size_t n = 0;
|
||||
const void *ptr;
|
||||
|
||||
err = _cbor_value_prepare_string_iteration(it);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
while (1) {
|
||||
err = validate_number(it, type, flags);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = _cbor_value_get_string_chunk(it, &ptr, &n, it);
|
||||
if (err)
|
||||
return err;
|
||||
if (!ptr)
|
||||
break;
|
||||
|
||||
if (type == CborTextStringType && flags & CborValidateUtf8) {
|
||||
err = validate_utf8_string(ptr, n);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return CborNoError;
|
||||
}
|
||||
|
||||
case CborTagType: {
|
||||
CborTag tag;
|
||||
err = cbor_value_get_tag(it, &tag);
|
||||
cbor_assert(err == CborNoError); /* can't fail */
|
||||
|
||||
err = cbor_value_advance_fixed(it);
|
||||
if (err)
|
||||
return err;
|
||||
err = validate_tag(it, tag, flags, recursionLeft - 1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return CborNoError;
|
||||
}
|
||||
|
||||
case CborSimpleType: {
|
||||
uint8_t simple_type;
|
||||
err = cbor_value_get_simple_type(it, &simple_type);
|
||||
cbor_assert(err == CborNoError); /* can't fail */
|
||||
err = validate_simple_type(simple_type, flags);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
}
|
||||
|
||||
case CborNullType:
|
||||
case CborBooleanType:
|
||||
break;
|
||||
|
||||
case CborUndefinedType:
|
||||
if (flags & CborValidateNoUndefined)
|
||||
return CborErrorExcludedType;
|
||||
break;
|
||||
|
||||
case CborHalfFloatType:
|
||||
case CborFloatType:
|
||||
case CborDoubleType: {
|
||||
#ifdef CBOR_NO_FLOATING_POINT
|
||||
return CborErrorUnsupportedType;
|
||||
#else
|
||||
err = validate_floating_point(it, type, flags);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
#endif /* !CBOR_NO_FLOATING_POINT */
|
||||
}
|
||||
|
||||
case CborInvalidType:
|
||||
return CborErrorUnknownType;
|
||||
}
|
||||
|
||||
err = cbor_value_advance_fixed(it);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a full validation, controlled by the \a flags options, of the CBOR
|
||||
* stream pointed by \a it and returns the error it found. If no error was
|
||||
* found, it returns CborNoError and the application can iterate over the items
|
||||
* with certainty that no errors will appear during parsing.
|
||||
*
|
||||
* If \a flags is CborValidateBasic, the result should be the same as
|
||||
* cbor_value_validate_basic().
|
||||
*
|
||||
* This function has the same timing and memory requirements as
|
||||
* cbor_value_advance() and cbor_value_validate_basic().
|
||||
*
|
||||
* \sa CborValidationFlags, cbor_value_validate_basic(), cbor_value_advance()
|
||||
*/
|
||||
CborError cbor_value_validate(const CborValue *it, uint32_t flags)
|
||||
{
|
||||
CborValue value = *it;
|
||||
CborError err = validate_value(&value, flags, CBOR_PARSER_MAX_RECURSIONS);
|
||||
if (err)
|
||||
return err;
|
||||
if (flags & CborValidateCompleteData && it->ptr != it->parser->end)
|
||||
return CborErrorGarbageAtEnd;
|
||||
return CborNoError;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
Loading…
Add table
Add a link
Reference in a new issue