Merge branch 'master' into dev

This commit is contained in:
Thiago Macieira
2021-01-13 09:05:42 -08:00
10 changed files with 139 additions and 68 deletions
+7 -2
View File
@@ -45,8 +45,6 @@ endif
INSTALL_TARGETS += $(bindir)/cbordump
ifeq ($(BUILD_SHARED),1)
BINLIBRARY=lib/libtinycbor.so
INSTALL_TARGETS += $(libdir)/libtinycbor.so
INSTALL_TARGETS += $(libdir)/libtinycbor.so.$(SOVERSION)
INSTALL_TARGETS += $(libdir)/libtinycbor.so.$(VERSION)
endif
ifeq ($(BUILD_STATIC),1)
@@ -192,8 +190,15 @@ install-strip:
$(MAKE) -f $(MAKEFILE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
install: $(INSTALL_TARGETS:%=$(DESTDIR)%)
ifeq ($(BUILD_SHARED),1)
ln -sf libtinycbor.so.$(VERSION) $(DESTDIR)$(libdir)/libtinycbor.so
ln -sf libtinycbor.so.$(VERSION) $(DESTDIR)$(libdir)/libtinycbor.so.$(SOVERSION)
endif
uninstall:
$(RM) $(INSTALL_TARGETS:%=$(DESTDIR)%)
$(RM) $(DESTDIR)$(libdir)/libtinycbor.so
$(RM) $(DESTDIR)$(libdir)/libtinycbor.so.$(SOVERSION)
mostlyclean:
$(RM) $(TINYCBOR_SOURCES:.c=.o)
+3 -2
View File
@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2017 Intel Corporation
** Copyright (C) 2019 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
@@ -273,7 +273,8 @@ enum CborParserIteratorFlags
CborIteratorFlag_NegativeInteger = 0x02,
CborIteratorFlag_IteratingStringChunks = 0x02,
CborIteratorFlag_UnknownLength = 0x04,
CborIteratorFlag_ContainerIsMap = 0x20
CborIteratorFlag_ContainerIsMap = 0x20,
CborIteratorFlag_NextIsMapKey = 0x40
};
struct CborParser
+24 -24
View File
@@ -65,7 +65,7 @@
* \code
* uint8_t buf[16];
* CborEncoder encoder;
* cbor_encoder_init(&encoder, &buf, sizeof(buf), 0);
* cbor_encoder_init(&encoder, buf, sizeof(buf), 0);
* cbor_encode_int(&encoder, some_value);
* \endcode
*
@@ -117,16 +117,16 @@
* CborEncoder encoder, mapEncoder;
* cbor_encoder_init(&encoder, buf, sizeof(buf), 0);
* err = cbor_encoder_create_map(&encoder, &mapEncoder, 1);
* if (!err)
* if (err)
* return err;
* err = cbor_encode_text_stringz(&mapEncoder, "foo");
* if (!err)
* if (err)
* return err;
* err = cbor_encode_boolean(&mapEncoder, some_value);
* if (!err)
* if (err)
* return err;
* err = cbor_encoder_close_container_checked(&encoder, &mapEncoder);
* if (!err)
* if (err)
* return err;
*
* size_t len = cbor_encoder_get_buffer_size(&encoder, buf);
@@ -157,7 +157,7 @@
*
* cbor_encoder_init(&encoder, buf, size, 0);
* err = cbor_encoder_create_array(&encoder, &arrayEncoder, n);
* cbor_assert(err); // can't fail, the buffer is always big enough
* cbor_assert(!err); // can't fail, the buffer is always big enough
*
* for (i = 0; i < n; ++i) {
* err = cbor_encode_text_stringz(&arrayEncoder, strings[i]);
@@ -166,7 +166,7 @@
* }
*
* err = cbor_encoder_close_container_checked(&encoder, &arrayEncoder);
* cbor_assert(err); // shouldn't fail!
* cbor_assert(!err); // shouldn't fail!
*
* more_bytes = cbor_encoder_get_extra_bytes_needed(encoder);
* if (more_size) {
@@ -210,8 +210,8 @@ void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int f
static inline void put16(void *where, uint16_t v)
{
v = cbor_htons(v);
memcpy(where, &v, sizeof(v));
uint16_t v_be = cbor_htons(v);
memcpy(where, &v_be, sizeof(v_be));
}
/* Note: Since this is currently only used in situations where OOM is the only
@@ -227,14 +227,14 @@ static inline bool isOomError(CborError err)
static inline void put32(void *where, uint32_t v)
{
v = cbor_htonl(v);
memcpy(where, &v, sizeof(v));
uint32_t v_be = cbor_htonl(v);
memcpy(where, &v_be, sizeof(v_be));
}
static inline void put64(void *where, uint64_t v)
{
v = cbor_htonll(v);
memcpy(where, &v, sizeof(v));
uint64_t v_be = cbor_htonll(v);
memcpy(where, &v_be, sizeof(v_be));
}
static inline bool would_overflow(CborEncoder *encoder, size_t len)
@@ -433,11 +433,10 @@ static CborError encode_string(CborEncoder *encoder, size_t length, uint8_t shif
*/
/**
* Appends the text string \a string of length \a length to the CBOR stream
* provided by \a encoder. CBOR requires that \a string be valid UTF-8, but
* TinyCBOR makes no verification of correctness.
* Appends the byte string \a string of length \a length to the CBOR stream
* provided by \a encoder. CBOR byte strings are arbitrary raw data.
*
* \sa CborError cbor_encode_text_stringz, cbor_encode_byte_string
* \sa cbor_encode_text_stringz, cbor_encode_text_string
*/
CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length)
{
@@ -445,10 +444,11 @@ CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, s
}
/**
* Appends the byte string \a string of length \a length to the CBOR stream
* provided by \a encoder. CBOR byte strings are arbitrary raw data.
* Appends the text string \a string of length \a length to the CBOR stream
* provided by \a encoder. CBOR requires that \a string be valid UTF-8, but
* TinyCBOR makes no verification of correctness.
*
* \sa cbor_encode_text_stringz, cbor_encode_text_string
* \sa CborError cbor_encode_text_stringz, cbor_encode_byte_string
*/
CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length)
{
@@ -540,11 +540,10 @@ CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder,
*/
CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder)
{
if (encoder->end)
encoder->data.ptr = containerEncoder->data.ptr;
else
encoder->data.bytes_needed = containerEncoder->data.bytes_needed;
// synchronise buffer state with that of the container
encoder->end = containerEncoder->end;
encoder->data = containerEncoder->data;
if (containerEncoder->flags & CborIteratorFlag_UnknownLength)
return append_byte_to_buffer(encoder, BreakByte);
@@ -553,6 +552,7 @@ CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *
if (!encoder->end)
return CborErrorOutOfMemory; /* keep the state */
return CborNoError;
}
+7 -5
View File
@@ -37,15 +37,17 @@
#endif
#ifndef CBOR_NO_HALF_FLOAT_TYPE
# ifdef __F16C__
# if defined(__F16C__) || defined(__AVX2__)
# include <immintrin.h>
static inline unsigned short encode_half(double val)
static inline unsigned short encode_half(float val)
{
return _cvtss_sh((float)val, 3);
__m128i m = _mm_cvtps_ph(_mm_set_ss(val), _MM_FROUND_CUR_DIRECTION);
return _mm_extract_epi16(m, 0);
}
static inline double decode_half(unsigned short half)
static inline float decode_half(unsigned short half)
{
return _cvtsh_ss(half);
__m128i m = _mm_cvtsi32_si128(half);
return _mm_cvtss_f32(_mm_cvtph_ps(m));
}
# else
/* software implementation of float-to-fp16 conversions */
+23 -4
View File
@@ -214,6 +214,10 @@ static bool is_fixed_type(uint8_t type)
static CborError preparse_value(CborValue *it)
{
enum {
/* flags to keep */
FlagsToKeep = CborIteratorFlag_ContainerIsMap | CborIteratorFlag_NextIsMapKey
};
const CborParser *parser = it->parser;
it->type = CborInvalidType;
@@ -224,7 +228,7 @@ static CborError preparse_value(CborValue *it)
uint8_t descriptor = *it->ptr;
uint8_t type = descriptor & MajorTypeMask;
it->type = type;
it->flags = 0;
it->flags &= FlagsToKeep;
it->extra = (descriptor &= SmallValueMask);
if (descriptor > Value64Bit) {
@@ -302,6 +306,11 @@ static CborError preparse_next_value_nodecrement(CborValue *it)
{
if (it->remaining == UINT32_MAX && it->ptr != it->parser->end && *it->ptr == (uint8_t)BreakByte) {
/* end of map or array */
if ((it->flags & CborIteratorFlag_ContainerIsMap && it->flags & CborIteratorFlag_NextIsMapKey)
|| it->type == CborTagType) {
/* but we weren't expecting it! */
return CborErrorUnexpectedBreak;
}
++it->ptr;
it->type = CborInvalidType;
it->remaining = 0;
@@ -313,13 +322,20 @@ static CborError preparse_next_value_nodecrement(CborValue *it)
static CborError preparse_next_value(CborValue *it)
{
/* tags don't count towards item totals or whether we've successfully
* read a map's key or value */
bool itemCounts = it->type != CborTagType;
if (it->remaining != UINT32_MAX) {
/* don't decrement the item count if the current item is tag: they don't count */
if (it->type != CborTagType && --it->remaining == 0) {
if (itemCounts && --it->remaining == 0) {
it->type = CborInvalidType;
return CborNoError;
}
}
if (itemCounts) {
/* toggle the flag indicating whether this was a map key */
it->flags ^= CborIteratorFlag_NextIsMapKey;
}
return preparse_next_value_nodecrement(it);
}
@@ -381,6 +397,7 @@ CborError cbor_parser_init(const uint8_t *buffer, size_t size, uint32_t flags, C
it->parser = parser;
it->ptr = buffer;
it->remaining = 1; /* there's one type altogether, usually an array or map */
it->flags = 0;
return preparse_value(it);
}
@@ -586,6 +603,7 @@ CborError cbor_value_skip_tag(CborValue *it)
*/
CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed)
{
cbor_static_assert(CborIteratorFlag_ContainerIsMap == (CborMapType & ~CborArrayType));
cbor_assert(cbor_value_is_container(it));
*recursed = *it;
@@ -618,6 +636,7 @@ CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed)
return CborNoError;
}
}
recursed->flags = (recursed->type & CborIteratorFlag_ContainerIsMap);
return preparse_next_value_nodecrement(recursed);
}
@@ -916,7 +935,7 @@ CborError cbor_value_get_int_checked(const CborValue *value, int *result)
/**
* \fn bool cbor_value_is_byte_string(const CborValue *value)
*
* Returns true if the iterator \a value is valid and points to a CBOR text
* Returns true if the iterator \a value is valid and points to a CBOR byte
* string. CBOR byte strings are binary data with no specified encoding or
* format.
*
+1 -1
View File
@@ -372,7 +372,7 @@ static CborError tagged_value_to_json(FILE *out, CborValue *it, int flags, Conve
if (type == CborByteStringType && (flags & CborConvertByteStringsToBase64Url) == 0 &&
(tag == CborNegativeBignumTag || tag == CborExpectedBase16Tag || tag == CborExpectedBase64Tag)) {
char *str;
char *pre = "";
const char *pre = "";
if (tag == CborNegativeBignumTag) {
pre = "~";
+22 -22
View File
@@ -130,112 +130,112 @@
<td>0</td>
<td>UTF-8 text string</td>
<td>Standard date/time string</td>
</td>
</tr>
<tr>
<td>1</td>
<td>integer</td>
<td>Epoch-based date/time</td>
</td>
</tr>
<tr>
<td>2</td>
<td>byte string</td>
<td>Positive bignum</td>
</td>
</tr>
<tr>
<td>3</td>
<td>byte string</td>
<td>Negative bignum</td>
</td>
</tr>
<tr>
<td>4</td>
<td>array</td>
<td>Decimal fraction</td>
</td>
</tr>
<tr>
<td>5</td>
<td>array</td>
<td>Bigfloat</td>
</td>
</tr>
<tr>
<td>16</td>
<td>array</td>
<td>COSE Single Recipient Encrypted Data Object (RFC 8152)</td>
</td>
</tr>
<tr>
<td>17</td>
<td>array</td>
<td>COSE Mac w/o Recipients Object (RFC 8152)</td>
</td>
</tr>
<tr>
<td>18</td>
<td>array</td>
<td>COSE Single Signer Data Object (RFC 8162)</td>
</td>
</tr>
<tr>
<td>21</td>
<td>byte string, array, map</td>
<td>Expected conversion to base64url encoding</td>
</td>
</tr>
<tr>
<td>22</td>
<td>byte string, array, map</td>
<td>Expected conversion to base64 encoding</td>
</td>
</tr>
<tr>
<td>23</td>
<td>byte string, array, map</td>
<td>Expected conversion to base16 encoding</td>
</td>
</tr>
<tr>
<td>24</td>
<td>byte string</td>
<td>Encoded CBOR data item</td>
</td>
</tr>
<tr>
<td>32</td>
<td>UTF-8 text string</td>
<td>URI</td>
</td>
</tr>
<tr>
<td>33</td>
<td>UTF-8 text string</td>
<td>base64url</td>
</td>
</tr>
<tr>
<td>34</td>
<td>UTF-8 text string</td>
<td>base64</td>
</td>
</tr>
<tr>
<td>35</td>
<td>UTF-8 text string</td>
<td>Regular expression</td>
</td>
</tr>
<tr>
<td>36</td>
<td>UTF-8 text string</td>
<td>MIME message</td>
</td>
</tr>
<tr>
<td>96</td>
<td>array</td>
<td>COSE Encrypted Data Object (RFC 8152)</td>
</td>
</tr>
<tr>
<td>97</td>
<td>array</td>
<td>COSE MACed Data Object (RFC 8152)</td>
</td>
</tr>
<tr>
<td>98</td>
<td>array</td>
<td>COSE Signed Data Object (RFC 8152)</td>
</td>
</tr>
<tr>
<td>55799</td>
<td>any</td>
<td>Self-describe CBOR</td>
</td>
</tr>
</table>
*/
+1 -1
View File
@@ -44,7 +44,7 @@
# include <stdbool.h>
#endif
#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L || __cpp_static_assert >= 200410
#if __STDC_VERSION__ >= 201112L || (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(__cpp_static_assert) && __cpp_static_assert >= 200410)
# define cbor_static_assert(x) static_assert(x, #x)
#elif !defined(__cplusplus) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) && (__STDC_VERSION__ > 199901L)
# define cbor_static_assert(x) _Static_assert(x, #x)
+2 -2
View File
@@ -38,7 +38,7 @@
#ifdef __APPLE__
typedef int RetType;
typedef int LenType;
#elif __GLIBC__
#elif __linux__
typedef ssize_t RetType;
typedef size_t LenType;
#else
@@ -101,7 +101,7 @@ FILE *open_memstream(char **bufptr, size_t *lenptr)
#ifdef __APPLE__
return funopen(b, NULL, write_to_buffer, NULL, close_buffer);
#elif __GLIBC__
#elif __linux__
static const cookie_io_functions_t vtable = {
NULL,
write_to_buffer,
+49 -5
View File
@@ -1107,22 +1107,44 @@ static void chunkedStringTest(const QByteArray &data, const QString &concatenate
err = cbor_value_calculate_string_length(&copy, &n);
QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
QByteArray buffer(n, Qt::Uninitialized);
size_t nn = n;
QByteArray buffer(n + 1, Qt::Uninitialized);
QByteArray buffer2(n + 1, Qt::Uninitialized);
buffer[int(n)] = 0xff;
buffer2[int(n)] = 0xff;
QString formatted;
if (cbor_value_is_byte_string(&copy)) {
err = cbor_value_copy_byte_string(&copy, (uint8_t *)buffer.data(), &n, nullptr);
err = cbor_value_copy_byte_string(&copy, (uint8_t *)buffer.data(), &nn, nullptr);
QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
QCOMPARE(int(n), buffer.size());
QCOMPARE(nn, n);
formatted = QString::fromLatin1("h'" + buffer.toHex() + '\'');
formatted = QString::fromLatin1("h'" + QByteArray::fromRawData(buffer.data(), n).toHex() + '\'');
// repeat by allowing the null termination
nn = n + 1;
err = cbor_value_copy_byte_string(&copy, (uint8_t *)buffer2.data(), &nn, nullptr);
} else {
err = cbor_value_copy_text_string(&copy, buffer.data(), &n, nullptr);
QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
QCOMPARE(int(n), buffer.size());
QCOMPARE(nn, n);
formatted = '"' + QString::fromUtf8(buffer.data(), n) + '"';
// repeat by allowing the null termination
nn = n + 1;
err = cbor_value_copy_text_string(&copy, buffer2.data(), &nn, nullptr);
}
QVERIFY2(!err, QByteArray("Got error \"") + cbor_error_string(err) + "\"");
QCOMPARE(formatted, concatenated);
// verify terminators
QCOMPARE(buffer.at(n), char(0xff));
QCOMPARE(buffer2.at(n), '\0');
QCOMPARE(nn, n);
buffer.truncate(n);
buffer2.truncate(n);
QCOMPARE(buffer2, buffer);
}
// confirm that the extra string we appended is still here
@@ -1680,6 +1702,10 @@ static void addValidationData()
QTest::newRow("array-no-break2") << raw("\x81\x9f\0") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("map-no-break1") << raw("\x81\xbf") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("map-no-break2") << raw("\x81\xbf\0\0") << 0 << CborErrorUnexpectedEOF;
QTest::newRow("map-break-after-key") << raw("\x81\xbf\0\xff") << 0 << CborErrorUnexpectedBreak;
QTest::newRow("map-break-after-second-key") << raw("\x81\xbf\x64xyzw\x04\x00\xff") << 0 << CborErrorUnexpectedBreak;
QTest::newRow("map-break-after-value-tag") << raw("\x81\xbf\0\xc0\xff") << 0 << CborErrorUnexpectedBreak;
QTest::newRow("map-break-after-value-tag2") << raw("\x81\xbf\0\xd8\x20\xff") << 0 << CborErrorUnexpectedBreak;
// check for pointer additions wrapping over the limit of the address space
CborError tooLargeOn32bit = (sizeof(void *) == 4) ? CborErrorDataTooLarge : CborErrorUnexpectedEOF;
@@ -1791,6 +1817,24 @@ void tst_Parser::validation()
QCOMPARE(err2, expectedError);
QCOMPARE(err3, expectedError);
}
// see if we've got a map
if (QByteArray(QTest::currentDataTag()).startsWith("map")) {
w.init(data, uint32_t(flags)); // reinit
QVERIFY(cbor_value_is_array(&w.first));
CborValue map;
CborError err = cbor_value_enter_container(&w.first, &map);
if (err == CborNoError) {
QVERIFY(cbor_value_is_map(&map));
CborValue element;
err = cbor_value_map_find_value(&map, "foobar", &element);
if (err == CborNoError)
QVERIFY(!cbor_value_is_valid(&element));
}
QCOMPARE(err, expectedError);
}
}
void tst_Parser::strictValidation_data()