Parser: centralize checking of the available buffer size

As noted in the comment, we need to be sure we don't allow a length too
big from the stream to overflow and become smaller than the number of
bytes we're looking for.

This is also the first step in creating an API that reads from something
other than a linear buffer.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Thiago Macieira
2021-09-03 13:08:25 -07:00
parent 2d8e73ba6c
commit 5521ccf2f7
3 changed files with 23 additions and 14 deletions
+9 -1
View File
@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2017 Intel Corporation
** Copyright (C) 2021 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
@@ -157,4 +157,12 @@ enum {
CBOR_INTERNAL_API CborError CBOR_INTERNAL_API_CC _cbor_value_extract_number(const uint8_t **ptr, const uint8_t *end, uint64_t *len);
CBOR_INTERNAL_API CborError CBOR_INTERNAL_API_CC _cbor_value_prepare_string_iteration(CborValue *it);
static inline bool can_read_bytes(const CborValue *it, size_t n)
{
/* Convert the pointer subtraction to size_t since end >= ptr
* (this prevents issues with (ptrdiff_t)n becoming negative).
*/
return (size_t)(it->parser->end - it->ptr) >= n;
}
#endif /* CBORINTERNAL_P_H */
+13 -12
View File
@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2017 Intel Corporation
** Copyright (C) 2021 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
@@ -218,17 +218,15 @@ static CborError preparse_value(CborValue *it)
/* flags to keep */
FlagsToKeep = CborIteratorFlag_ContainerIsMap | CborIteratorFlag_NextIsMapKey
};
const CborParser *parser = it->parser;
it->type = CborInvalidType;
/* are we at the end? */
if (it->ptr == parser->end)
it->type = CborInvalidType;
it->flags &= FlagsToKeep;
if (!can_read_bytes(it, 1))
return CborErrorUnexpectedEOF;
uint8_t descriptor = *it->ptr;
uint8_t type = descriptor & MajorTypeMask;
it->type = type;
it->flags &= FlagsToKeep;
it->extra = (descriptor &= SmallValueMask);
if (descriptor > Value64Bit) {
@@ -244,8 +242,11 @@ static CborError preparse_value(CborValue *it)
}
size_t bytesNeeded = descriptor < Value8Bit ? 0 : (1 << (descriptor - Value8Bit));
if (bytesNeeded + 1 > (size_t)(parser->end - it->ptr))
return CborErrorUnexpectedEOF;
if (bytesNeeded) {
if (!can_read_bytes(it, bytesNeeded + 1))
return CborErrorUnexpectedEOF;
}
uint8_t majortype = type >> MajorTypeShift;
if (majortype == NegativeIntegerType) {
@@ -304,7 +305,7 @@ static CborError preparse_value(CborValue *it)
static CborError preparse_next_value_nodecrement(CborValue *it)
{
if (it->remaining == UINT32_MAX && it->ptr != it->parser->end && *it->ptr == (uint8_t)BreakByte) {
if (it->remaining == UINT32_MAX && can_read_bytes(it, 1) && *it->ptr == (uint8_t)BreakByte) {
/* end of map or array */
if ((it->flags & CborIteratorFlag_ContainerIsMap && it->flags & CborIteratorFlag_NextIsMapKey)
|| it->type == CborTagType) {
@@ -1007,7 +1008,7 @@ CborError CBOR_INTERNAL_API_CC _cbor_value_prepare_string_iteration(CborValue *i
prepare_string_iteration(it);
/* are we at the end? */
if (it->ptr == it->parser->end)
if (!can_read_bytes(it, 1))
return CborErrorUnexpectedEOF;
return CborNoError;
}
@@ -1034,7 +1035,7 @@ static CborError get_string_chunk(CborValue *it, const void **bufferptr, size_t
}
/* are we at the end? */
if (it->ptr == it->parser->end)
if (!can_read_bytes(it, 1))
return CborErrorUnexpectedEOF;
if (*it->ptr == BreakByte) {
@@ -1048,7 +1049,7 @@ last_chunk:
err = extract_length(it->parser, &it->ptr, len);
if (err)
return err;
if (*len > (size_t)(it->parser->end - it->ptr))
if (!can_read_bytes(it, *len))
return CborErrorUnexpectedEOF;
*bufferptr = it->ptr;
+1 -1
View File
@@ -647,7 +647,7 @@ CborError cbor_value_validate(const CborValue *it, uint32_t flags)
CborError err = validate_value(&value, flags, CBOR_PARSER_MAX_RECURSIONS);
if (err)
return err;
if (flags & CborValidateCompleteData && it->ptr != it->parser->end)
if (flags & CborValidateCompleteData && can_read_bytes(it, 1))
return CborErrorGarbageAtEnd;
return CborNoError;
}