blob: 6b19c58ff70139cb635561d1e546c3b3077c6a90 [file] [log] [blame]
Thiago Macieiraaddf8042017-02-26 11:37:06 -08001/****************************************************************************
2**
3** Copyright (C) 2017 Intel Corporation
4**
5** Permission is hereby granted, free of charge, to any person obtaining a copy
6** of this software and associated documentation files (the "Software"), to deal
7** in the Software without restriction, including without limitation the rights
8** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9** copies of the Software, and to permit persons to whom the Software is
10** furnished to do so, subject to the following conditions:
11**
12** The above copyright notice and this permission notice shall be included in
13** all copies or substantial portions of the Software.
14**
15** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21** THE SOFTWARE.
22**
23****************************************************************************/
24
25#define _BSD_SOURCE 1
26#define _DEFAULT_SOURCE 1
27#ifndef __STDC_LIMIT_MACROS
28# define __STDC_LIMIT_MACROS 1
29#endif
30
31#include "cbor.h"
32#include "cborinternal_p.h"
33#include "compilersupport_p.h"
34
35#include <string.h>
36
37#ifndef CBOR_NO_FLOATING_POINT
38# include <float.h>
39# include <math.h>
40#endif
41
42
43#ifndef CBOR_PARSER_MAX_RECURSIONS
44# define CBOR_PARSER_MAX_RECURSIONS 1024
45#endif
46
47/**
48 * \addtogroup CborParsing
49 * @{
50 */
51
52/**
53 * \enum CborValidationFlags
54 * The CborValidationFlags enum contains flags that control the validation of a
55 * CBOR stream.
56 *
57 * \value CborValidateBasic Validates only the syntax correctedness of the stream.
58 * \value CborValidateCanonical Validates that the stream is in canonical format, according to
59 * RFC 7049 section 3.9.
60 * \value CborValidateStrictMode Performs strict validation, according to RFC 7049 section 3.10.
61 * \value CborValidateStrictest Attempt to perform the strictest validation we know of.
62 *
63 * \value CborValidateShortestIntegrals (Canonical) Validate that integral numbers and lengths are
64 * enconded in their shortest form possible.
65 * \value CborValidateShortestFloatingPoint (Canonical) Validate that floating-point numbers are encoded
66 * in their shortest form possible.
67 * \value CborValidateShortestNumbers (Canonical) Validate both integrals and floating-point numbers
68 * are in their shortest form possible.
69 * \value CborValidateNoIndeterminateLength (Canonical) Validate that no string, array or map uses
70 * indeterminate length encoding.
71 * \value CborValidateMapIsSorted (Canonical & Strict mode) Validate that map keys appear in
72 * sorted order.
73 * \value CborValidateMapKeysAreUnique (Strict mode) Validate that map keys are unique.
74 * \value CborValidateTagUse (Strict mode) Validate that known tags are used with the
75 * correct types. This does not validate that the content of
76 * those types is syntactically correct.
77 * \value CborValidateUtf8 (Strict mode) Validate that text strings are appropriately
78 * encoded in UTF-8.
79 * \value CborValidateMapKeysAreString Validate that all map keys are text strings.
80 * \value CborValidateNoUndefined Validate that no elements of type "undefined" are present.
81 * \value CborValidateNoTags Validate that no tags are used.
82 * \value CborValidateFiniteFloatingPoint Validate that all floating point numbers are finite (no NaN or
83 * infinities are allowed).
84 * \value CborValidateCompleteData Validate that the stream is complete and there is no more data
85 * in the buffer.
86 * \value CborValidateNoUnknownSimpleTypesSA Validate that all Standards Action simple types are registered
87 * with IANA.
88 * \value CborValidateNoUnknownSimpleTypes Validate that all simple types used are registered with IANA.
89 * \value CborValidateNoUnknownTagsSA Validate that all Standard Actions tags are registered with IANA.
90 * \value CborValidateNoUnknownTagsSR Validate that all Standard Actions and Specification Required tags
91 * are registered with IANA (see below for limitations).
92 * \value CborValidateNoUnkonwnTags Validate that all tags are registered with IANA
93 * (see below for limitations).
94 *
95 * \par Simple type registry
96 * The CBOR specification requires that registration for use of the first 19
97 * simple types must be done by way of Standards Action. The rest of the simple
98 * types only require a specification. The official list can be obtained from
99 * https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xhtml.
100 *
101 * \par
102 * There are no registered simple types recognized by this release of TinyCBOR
103 * (beyond those defined by RFC 7049).
104 *
105 * \par Tag registry
106 * The CBOR specification requires that registration for use of the first 23
107 * tags must be done by way of Standards Action. The next up to tag 255 only
108 * require a specification. Finally, all other tags can be registered on a
109 * first-come-first-serve basis. The official list can be ontained from
110 * https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml.
111 *
112 * \par
113 * Given the variability of this list, TinyCBOR cannot recognize all tags
114 * registered with IANA. Instead, the implementation only recognizes tags
115 * that are backed by an RFC.
116 *
117 * \par
118 * These are the tags known to the current TinyCBOR release:
119[will be added in the next commit]
120 */
121
122static CborError validate_value(CborValue *it, int flags, int recursionLeft);
123
124static inline CborError validate_simple_type(uint8_t simple_type, int flags)
125{
126 /* At current time, all known simple types are those from RFC 7049,
127 * which are parsed by the parser into different CBOR types.
128 * That means that if we've got here, the type is unknown */
129 if (simple_type < 32)
130 return (flags & CborValidateNoUnknownSimpleTypesSA) ? CborErrorUnknownSimpleType : CborNoError;
131 return (flags & CborValidateNoUnknownSimpleTypes) == CborValidateNoUnknownSimpleTypes ?
132 CborErrorUnknownSimpleType : CborNoError;
133}
134
135static inline CborError validate_tag(CborValue *it, CborTag tag, int flags, int recursionLeft)
136{
137 CborType type = cbor_value_get_type(it);
138 if (!recursionLeft)
139 return CborErrorNestingTooDeep;
140
141 if (flags & CborValidateNoTags)
142 return CborErrorExcludedType;
143 if (flags & CborValidateNoUnknownTags) {
144 if (tag > 255 && (flags & CborValidateNoUnknownTagsSR) == 0)
145 return CborErrorUnknownTag;
146 if (flags & CborValidateNoUnknownTagsSR) {
147 if (tag > 23 && (flags & CborValidateNoUnknownTagsSA) == 0)
148 return CborErrorUnknownTag;
149 if (flags & CborValidateNoUnknownTagsSA)
150 return CborErrorUnknownTag;
151 }
152 }
153
154 return validate_value(it, flags, recursionLeft);
155}
156
157#ifndef CBOR_NO_FLOATING_POINT
158static inline CborError validate_floating_point(CborValue *it, CborType type, int flags)
159{
160 CborError err;
161 double val;
162 float valf;
163 uint16_t valf16;
164
165 if (type != CborDoubleType) {
166 if (type == CborFloatType) {
167 err = cbor_value_get_float(it, &valf);
168 val = valf;
169 } else {
170# ifdef CBOR_NO_HALF_FLOAT_TYPE
171 (void)val16;
172 return CborErrorUnsupportedType;
173# else
174 err = cbor_value_get_half_float(it, &valf16);
175 val = decode_half(valf16);
176# endif
177 }
178 } else {
179 err = cbor_value_get_double(it, &val);
180 }
181 cbor_assert(err == CborNoError); /* can't fail */
182
183 int r = fpclassify(val);
184 if (r == FP_NAN || r == FP_INFINITE) {
185 if (flags & CborValidateFiniteFloatingPoint)
186 return CborErrorExcludedValue;
187 if (flags & CborValidateShortestFloatingPoint) {
188 if (type == CborDoubleType)
189 return CborErrorOverlongEncoding;
190# ifndef CBOR_NO_HALF_FLOAT_TYPE
191 if (type == CborFloatType)
192 return CborErrorOverlongEncoding;
193 if (r == FP_NAN && valf16 != 0x7e00)
194 return CborErrorImproperValue;
195 if (r == FP_INFINITE && valf16 != 0x7c00 && valf16 != 0xfc00)
196 return CborErrorImproperValue;
197# endif
198 }
199 }
200
201 if (flags & CborValidateShortestFloatingPoint && type > CborHalfFloatType) {
202 if (type == CborDoubleType) {
203 valf = (float)val;
204 if ((double)valf == val)
205 return CborErrorOverlongEncoding;
206 }
207# ifndef CBOR_NO_HALF_FLOAT_TYPE
208 if (type == CborFloatType) {
209 valf16 = encode_half(valf);
210 if (valf == decode_half(valf16))
211 return CborErrorOverlongEncoding;
212 }
213# endif
214 }
215
216 return CborNoError;
217}
218#endif
219
220static CborError validate_container(CborValue *it, int containerType, int flags, int recursionLeft)
221{
222 CborError err;
223 if (!recursionLeft)
224 return CborErrorNestingTooDeep;
225
226 while (!cbor_value_at_end(it)) {
227 err = validate_value(it, flags, recursionLeft);
228 if (err)
229 return err;
230
231 if (containerType == CborArrayType)
232 continue;
233
234 /* map: that was the key, so get he value */
235 err = validate_value(it, flags, recursionLeft);
236 if (err)
237 return err;
238 }
239 return CborNoError;
240}
241
242static CborError validate_value(CborValue *it, int flags, int recursionLeft)
243{
244 CborError err;
245 if (flags & CborValidateNoIndeterminateLength) {
246 if (!cbor_value_is_length_known(it))
247 return CborErrorUnknownLength;
248 }
249
250 CborType type = cbor_value_get_type(it);
251 switch (type) {
252 case CborArrayType:
253 case CborMapType: {
254 /* recursive type */
255 CborValue recursed;
256 err = cbor_value_enter_container(it, &recursed);
257 if (!err)
258 err = validate_container(&recursed, type, flags, recursionLeft - 1);
259 if (err) {
260 it->ptr = recursed.ptr;
261 return err;
262 }
263 err = cbor_value_leave_container(it, &recursed);
264 if (err)
265 return err;
266 return CborNoError;
267 }
268
269 case CborIntegerType: {
270 uint64_t val;
271 err = cbor_value_get_raw_integer(it, &val);
272 cbor_assert(err == CborNoError); /* can't fail */
273
274 break;
275 }
276
277 case CborByteStringType:
278 case CborTextStringType: {
279 size_t n = 0;
280 const void *ptr;
281
282 while (1) {
283 err = _cbor_value_get_string_chunk(it, &ptr, &n, it);
284 if (err)
285 return err;
286 if (!ptr)
287 break;
288 }
289
290 return CborNoError;
291 }
292
293 case CborTagType: {
294 CborTag tag;
295 err = cbor_value_get_tag(it, &tag);
296 cbor_assert(err == CborNoError); /* can't fail */
297
298 err = cbor_value_advance_fixed(it);
299 if (err)
300 return err;
301 err = validate_tag(it, tag, flags, recursionLeft - 1);
302 if (err)
303 return err;
304
305 return CborNoError;
306 }
307
308 case CborSimpleType: {
309 uint8_t simple_type;
310 err = cbor_value_get_simple_type(it, &simple_type);
311 cbor_assert(err == CborNoError); /* can't fail */
312 err = validate_simple_type(simple_type, flags);
313 if (err)
314 return err;
315 break;
316 }
317
318 case CborNullType:
319 case CborBooleanType:
320 break;
321
322 case CborUndefinedType:
323 if (flags & CborValidateNoUndefined)
324 return CborErrorExcludedType;
325 break;
326
327 case CborHalfFloatType:
328 case CborFloatType:
329 case CborDoubleType: {
330#ifdef CBOR_NO_FLOATING_POINT
331 return CborErrorUnsupportedType;
332#else
333 err = validate_floating_point(it, type, flags);
334 if (err)
335 return err;
336 break;
337 }
338#endif /* !CBOR_NO_FLOATING_POINT */
339
340 case CborInvalidType:
341 return CborErrorUnknownType;
342 }
343
344 err = cbor_value_advance_fixed(it);
345 return err;
346}
347
348/**
349 * Performs a full validation controlled by the \a flags options of the CBOR
350 * stream pointed by \a it and returns the error it found. If no error was
351 * found, it returns CborNoError and the application can iterate over the items
352 * with certainty that no other errors will appear during parsing.
353 *
354 * If \a flags is CborValidateBasic, the result should be the same as
355 * cbor_value_validate_basic().
356 *
357 * This function has the same timing and memory requirements as
358 * cbor_value_advance() and cbor_value_validate_basic().
359 *
360 * \sa CborValidationFlags, cbor_value_validate_basic(), cbor_value_advance()
361 */
362CborError cbor_value_validate(const CborValue *it, int flags)
363{
364 CborValue value = *it;
365 CborError err = validate_value(&value, flags, CBOR_PARSER_MAX_RECURSIONS);
366 if (err)
367 return err;
368 if (flags & CborValidateCompleteData && it->ptr != it->parser->end)
369 return CborErrorGarbageAtEnd;
370 return CborNoError;
371}
372
373/**
374 * @}
375 */