Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/cbor.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ typedef enum CborError {

/* errors in all modes */
CborUnknownError,
CborErrorOutOfMemory,
CborErrorUnknownLength, /* request for length in array, map, or string with indeterminate length */
CborErrorAdvancePastEOF,
CborErrorIO,
Expand All @@ -131,7 +130,9 @@ typedef enum CborError {
/* internal implementation errors */
CborErrorDataTooLarge = 1024,
CborErrorNestingTooDeep,
CborErrorInternalError = ~0U
CborErrorInternalError = ~0U,

CborErrorOutOfMemory = ~0U / 2 + 1
} CborError;

CBOR_API const char *cbor_error_string(CborError error);
Expand Down
36 changes: 32 additions & 4 deletions src/cborencoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ static inline void put16(void *where, uint16_t v)
memcpy(where, &v, sizeof(v));
}

// Note: Since this is currently only used in situations where OOM is the only
// valid error, we KNOW this to be true. Thus, this function now returns just 'true',
// but if in the future, any function starts returning a non-OOM error, this will need
// to be changed to the test. At the moment, this is done to prevent more branches
// being created in the tinycbor output
static inline bool isOomError(CborError err)
{
return true;
}

static inline void put32(void *where, uint32_t v)
{
v = cbor_htonl(v);
Expand All @@ -60,17 +70,34 @@ static inline void put64(void *where, uint64_t v)

static inline CborError append_to_buffer(CborEncoder *encoder, const void *data, size_t len)
{
if (encoder->ptr + len > encoder->end)
if (encoder->end - encoder->ptr - (ptrdiff_t)len < 0) {

if(encoder->end != NULL) {
len -= encoder->end - encoder->ptr;
encoder->end = encoder->ptr = NULL;
}

encoder->ptr += len;
return CborErrorOutOfMemory;
}

memcpy(encoder->ptr, data, len);
encoder->ptr += len;
return CborNoError;
}

static inline CborError append_byte_to_buffer(CborEncoder *encoder, uint8_t byte)
{
if (encoder->ptr == encoder->end)
if (encoder->end <= encoder->ptr) {

if(encoder->end != NULL) {
encoder->end = encoder->ptr = NULL;
}

++encoder->ptr;
return CborErrorOutOfMemory;
}

*encoder->ptr++ = byte;
return CborNoError;
}
Expand Down Expand Up @@ -152,7 +179,7 @@ CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag)
static CborError encode_string(CborEncoder *encoder, size_t length, uint8_t shiftedMajorType, const void *string)
{
CborError err = encode_number(encoder, length, shiftedMajorType);
if (err)
if (err && !isOomError(err))
return err;
return append_to_buffer(encoder, string, length);
}
Expand All @@ -174,7 +201,7 @@ static CborError create_container(CborEncoder *encoder, size_t length, uint8_t s
err = append_byte_to_buffer(encoder, shiftedMajorType + IndefiniteLength);
else
err = encode_number(encoder, length, shiftedMajorType);
if (err)
if (err && !isOomError(err))
return err;

*container = *encoder;
Expand All @@ -195,6 +222,7 @@ CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder,
CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder)
{
encoder->ptr = containerEncoder->ptr;
encoder->end = containerEncoder->end;
if (containerEncoder->flags & CborIteratorFlag_UnknownLength)
return append_byte_to_buffer(encoder, BreakByte);
return CborNoError;
Expand Down
30 changes: 18 additions & 12 deletions tests/encoder/tst_encoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ QVariant make_ilmap(const std::initializer_list<QPair<QVariant, QVariant>> &list
return QVariant::fromValue(IndeterminateLengthMap(list));
}

static inline bool isOomError(CborError err)
{
return err == CborErrorOutOfMemory;
}

CborError encodeVariant(CborEncoder *encoder, const QVariant &v)
{
int type = v.userType();
Expand Down Expand Up @@ -132,9 +137,9 @@ CborError encodeVariant(CborEncoder *encoder, const QVariant &v)
return cbor_encode_half_float(encoder, v.constData());
if (type == qMetaTypeId<Tag>()) {
CborError err = cbor_encode_tag(encoder, v.value<Tag>().tag);
if (err)
if (err && !isOomError(err))
return err;
return encodeVariant(encoder, v.value<Tag>().tagged);
return static_cast<CborError>(err | encodeVariant(encoder, v.value<Tag>().tagged));
}
if (type == QVariant::List || type == qMetaTypeId<IndeterminateLengthArray>()) {
CborEncoder sub;
Expand All @@ -145,14 +150,14 @@ CborError encodeVariant(CborEncoder *encoder, const QVariant &v)
list = v.value<IndeterminateLengthArray>();
}
CborError err = cbor_encoder_create_array(encoder, &sub, len);
if (err)
if (err && !isOomError(err))
return err;
foreach (const QVariant &v2, list) {
err = encodeVariant(&sub, v2);
if (err)
err = static_cast<CborError>(err | encodeVariant(&sub, v2));
if (err && !isOomError(err))
return err;
}
return cbor_encoder_close_container(encoder, &sub);
return static_cast<CborError>(err | cbor_encoder_close_container(encoder, &sub));
}
if (type == qMetaTypeId<Map>() || type == qMetaTypeId<IndeterminateLengthMap>()) {
CborEncoder sub;
Expand All @@ -163,17 +168,17 @@ CborError encodeVariant(CborEncoder *encoder, const QVariant &v)
map = v.value<IndeterminateLengthMap>();
}
CborError err = cbor_encoder_create_map(encoder, &sub, len);
if (err)
if (err && !isOomError(err))
return err;
for (auto pair : map) {
err = encodeVariant(&sub, pair.first);
if (err)
err = static_cast<CborError>(err | encodeVariant(&sub, pair.first));
if (err && !isOomError(err))
return err;
err = encodeVariant(&sub, pair.second);
if (err)
err = static_cast<CborError>(err | encodeVariant(&sub, pair.second));
if (err && !isOomError(err))
return err;
}
return cbor_encoder_close_container(encoder, &sub);
return (CborError)(err | cbor_encoder_close_container(encoder, &sub));
}
}
return CborErrorUnknownType;
Expand Down Expand Up @@ -527,6 +532,7 @@ void tst_Encoder::shortBuffer()
CborEncoder encoder;
cbor_encoder_init(&encoder, reinterpret_cast<quint8 *>(buffer.data()), len, 0);
QCOMPARE(int(encodeVariant(&encoder, input)), int(CborErrorOutOfMemory));
QCOMPARE(len + int(encoder.ptr - encoder.end), output.length());
}
}

Expand Down