55 * it under the terms of the MIT license. See LICENSE for details.
66 */
77
8+ #include <stdbool.h>
9+ #include <string.h>
10+
811#include "cbor.h"
912#include "cbor/internal/builder_callbacks.h"
1013#include "cbor/internal/loaders.h"
@@ -115,6 +118,9 @@ cbor_item_t* cbor_load(cbor_data source, size_t source_size,
115118}
116119
117120static cbor_item_t * _cbor_copy_int (cbor_item_t * item , bool negative ) {
121+ CBOR_ASSERT (cbor_isa_uint (item ) || cbor_isa_negint (item ));
122+ CBOR_ASSERT (cbor_int_get_width (item ) >= CBOR_INT_8 &&
123+ cbor_int_get_width (item ) <= CBOR_INT_64 );
118124 cbor_item_t * res = NULL ;
119125 switch (cbor_int_get_width (item )) {
120126 case CBOR_INT_8 :
@@ -137,6 +143,9 @@ static cbor_item_t* _cbor_copy_int(cbor_item_t* item, bool negative) {
137143}
138144
139145static cbor_item_t * _cbor_copy_float_ctrl (cbor_item_t * item ) {
146+ CBOR_ASSERT (cbor_isa_float_ctrl (item ));
147+ CBOR_ASSERT (cbor_float_get_width (item ) >= CBOR_FLOAT_0 &&
148+ cbor_float_get_width (item ) <= CBOR_FLOAT_64 );
140149 switch (cbor_float_get_width (item )) {
141150 case CBOR_FLOAT_0 :
142151 return cbor_build_ctrl (cbor_ctrl_value (item ));
@@ -146,13 +155,14 @@ static cbor_item_t* _cbor_copy_float_ctrl(cbor_item_t* item) {
146155 return cbor_build_float4 (cbor_float_get_float4 (item ));
147156 case CBOR_FLOAT_64 :
148157 return cbor_build_float8 (cbor_float_get_float8 (item ));
149- default :
158+ default : // LCOV_EXCL_START
150159 _CBOR_UNREACHABLE ;
151- return NULL ;
160+ return NULL ; // LCOV_EXCL_START
152161 }
153162}
154163
155164cbor_item_t * cbor_copy (cbor_item_t * item ) {
165+ CBOR_ASSERT_VALID_TYPE (cbor_typeof (item ));
156166 switch (cbor_typeof (item )) {
157167 case CBOR_TYPE_UINT :
158168 return _cbor_copy_int (item , false);
@@ -283,9 +293,138 @@ cbor_item_t* cbor_copy(cbor_item_t* item) {
283293 }
284294 case CBOR_TYPE_FLOAT_CTRL :
285295 return _cbor_copy_float_ctrl (item );
286- default :
296+ default : // LCOV_EXCL_START
297+ _CBOR_UNREACHABLE ;
298+ return NULL ; // LCOV_EXCL_STOP
299+ }
300+ }
301+
302+ cbor_item_t * cbor_copy_definite (cbor_item_t * item ) {
303+ CBOR_ASSERT_VALID_TYPE (cbor_typeof (item ));
304+ switch (cbor_typeof (item )) {
305+ case CBOR_TYPE_UINT :
306+ case CBOR_TYPE_NEGINT :
307+ return cbor_copy (item );
308+ case CBOR_TYPE_BYTESTRING :
309+ if (cbor_bytestring_is_definite (item )) {
310+ return cbor_copy (item );
311+ } else {
312+ size_t total_length = 0 ;
313+ for (size_t i = 0 ; i < cbor_bytestring_chunk_count (item ); i ++ ) {
314+ total_length +=
315+ cbor_bytestring_length (cbor_bytestring_chunks_handle (item )[i ]);
316+ }
317+
318+ unsigned char * combined_data = _cbor_malloc (total_length );
319+ if (combined_data == NULL ) {
320+ return NULL ;
321+ }
322+
323+ size_t offset = 0 ;
324+ for (size_t i = 0 ; i < cbor_bytestring_chunk_count (item ); i ++ ) {
325+ cbor_item_t * chunk = cbor_bytestring_chunks_handle (item )[i ];
326+ memcpy (combined_data + offset , cbor_bytestring_handle (chunk ),
327+ cbor_bytestring_length (chunk ));
328+ offset += cbor_bytestring_length (chunk );
329+ }
330+
331+ cbor_item_t * res = cbor_new_definite_bytestring ();
332+ cbor_bytestring_set_handle (res , combined_data , total_length );
333+ return res ;
334+ }
335+ case CBOR_TYPE_STRING :
336+ if (cbor_string_is_definite (item )) {
337+ return cbor_copy (item );
338+ } else {
339+ size_t total_length = 0 ;
340+ for (size_t i = 0 ; i < cbor_string_chunk_count (item ); i ++ ) {
341+ total_length +=
342+ cbor_string_length (cbor_string_chunks_handle (item )[i ]);
343+ }
344+
345+ unsigned char * combined_data = _cbor_malloc (total_length );
346+ if (combined_data == NULL ) {
347+ return NULL ;
348+ }
349+
350+ size_t offset = 0 ;
351+ for (size_t i = 0 ; i < cbor_string_chunk_count (item ); i ++ ) {
352+ cbor_item_t * chunk = cbor_string_chunks_handle (item )[i ];
353+ memcpy (combined_data + offset , cbor_string_handle (chunk ),
354+ cbor_string_length (chunk ));
355+ offset += cbor_string_length (chunk );
356+ }
357+
358+ cbor_item_t * res = cbor_new_definite_string ();
359+ cbor_string_set_handle (res , combined_data , total_length );
360+ return res ;
361+ }
362+ case CBOR_TYPE_ARRAY : {
363+ cbor_item_t * res = cbor_new_definite_array (cbor_array_size (item ));
364+ if (res == NULL ) {
365+ return NULL ;
366+ }
367+
368+ for (size_t i = 0 ; i < cbor_array_size (item ); i ++ ) {
369+ cbor_item_t * entry_copy =
370+ cbor_copy_definite (cbor_array_handle (item )[i ]);
371+ if (entry_copy == NULL ) {
372+ cbor_decref (& res );
373+ return NULL ;
374+ }
375+ // Cannot fail since we have a definite array preallocated
376+ // cppcheck-suppress syntaxError
377+ const bool item_pushed _CBOR_UNUSED = cbor_array_push (res , entry_copy );
378+ CBOR_ASSERT (item_pushed );
379+ cbor_decref (& entry_copy );
380+ }
381+ return res ;
382+ }
383+ case CBOR_TYPE_MAP : {
384+ cbor_item_t * res ;
385+ res = cbor_new_definite_map (cbor_map_size (item ));
386+ if (res == NULL ) {
387+ return NULL ;
388+ }
389+
390+ struct cbor_pair * it = cbor_map_handle (item );
391+ for (size_t i = 0 ; i < cbor_map_size (item ); i ++ ) {
392+ cbor_item_t * key_copy = cbor_copy_definite (it [i ].key );
393+ if (key_copy == NULL ) {
394+ cbor_decref (& res );
395+ return NULL ;
396+ }
397+ cbor_item_t * value_copy = cbor_copy_definite (it [i ].value );
398+ if (value_copy == NULL ) {
399+ cbor_decref (& res );
400+ cbor_decref (& key_copy );
401+ return NULL ;
402+ }
403+ // Cannot fail since we have a definite map preallocated
404+ // cppcheck-suppress syntaxError
405+ const bool item_added _CBOR_UNUSED = cbor_map_add (
406+ res , (struct cbor_pair ){.key = key_copy , .value = value_copy });
407+ CBOR_ASSERT (item_added );
408+ cbor_decref (& key_copy );
409+ cbor_decref (& value_copy );
410+ }
411+ return res ;
412+ }
413+ case CBOR_TYPE_TAG : {
414+ cbor_item_t * item_copy =
415+ cbor_copy_definite (cbor_move (cbor_tag_item (item )));
416+ if (item_copy == NULL ) {
417+ return NULL ;
418+ }
419+ cbor_item_t * tag = cbor_build_tag (cbor_tag_value (item ), item_copy );
420+ cbor_decref (& item_copy );
421+ return tag ;
422+ }
423+ case CBOR_TYPE_FLOAT_CTRL :
424+ return cbor_copy (item );
425+ default : // LCOV_EXCL_START
287426 _CBOR_UNREACHABLE ;
288- return NULL ;
427+ return NULL ; // LCOV_EXCL_STOP
289428 }
290429}
291430
@@ -309,6 +448,8 @@ static void _cbor_type_marquee(FILE* out, char* label, int indent) {
309448}
310449
311450static void _cbor_nested_describe (cbor_item_t * item , FILE * out , int indent ) {
451+ CBOR_ASSERT (cbor_typeof (item ) >= CBOR_TYPE_UINT &&
452+ cbor_typeof (item ) <= CBOR_TYPE_FLOAT_CTRL );
312453 const int indent_offset = 4 ;
313454 switch (cbor_typeof (item )) {
314455 case CBOR_TYPE_UINT : {
0 commit comments