Check SFLV tuple is within stream before decoding
If the SFLV tuple being decoded goes out of the stream length
it could lead to a heap overflow. This patch adds a check to
prevent it.
Tested:
Unit tested
Signed-off-by: Kasun Athukorala <kasunath@google.com>
Change-Id: Ie018d4f3614603efc6ed8b93fa0077c612d9b481
diff --git a/src/bej_decoder_core.c b/src/bej_decoder_core.c
index 2536ed1..43f5b69 100644
--- a/src/bej_decoder_core.c
+++ b/src/bej_decoder_core.c
@@ -90,7 +90,7 @@
* params->state.encodedSubStream pointing to the start of the encoded stream
* and params->state.encodedStreamOffset pointing to the current bejTuple.
*/
-static void bejInitSFLVStruct(struct BejHandleTypeFuncParam* params)
+static bool bejInitSFLVStruct(struct BejHandleTypeFuncParam* params)
{
struct BejSFLVOffset localOffset;
// Get offsets of different SFLV fields with respect to start of the encoded
@@ -109,9 +109,30 @@
sflv->format = *(struct BejTupleF*)(params->state.encodedSubStream +
localOffset.formatOffset);
sflv->valueLength = valueLength;
- sflv->valueEndOffset = params->state.encodedStreamOffset +
- localOffset.valueOffset + valueLength;
+
+ if ((UINT32_MAX - localOffset.valueOffset) <
+ params->state.encodedStreamOffset)
+ {
+ fprintf(stderr,
+ "Overflow when adding encodedStreamOffset and valueOffset\n");
+ return false;
+ }
+
+ uint32_t valueStartLocation =
+ params->state.encodedStreamOffset + localOffset.valueOffset;
+
+ if ((UINT32_MAX - valueStartLocation) < valueLength)
+ {
+ fprintf(
+ stderr,
+ "Overflow when adding valueLength to encodedStreamOffset + valueOffset\n");
+ return false;
+ }
+
+ // Offset to the location soon after the value
+ sflv->valueEndOffset = valueStartLocation + valueLength;
sflv->value = params->state.encodedSubStream + localOffset.valueOffset;
+ return true;
}
/**
@@ -733,7 +754,21 @@
// Go to the next encoded segment in the encoded stream.
params.state.encodedSubStream =
enStream + params.state.encodedStreamOffset;
- bejInitSFLVStruct(¶ms);
+ if (!bejInitSFLVStruct(¶ms))
+ {
+ return bejErrorInvalidSize;
+ }
+
+ // Make sure that the next value segment (SFLV) is within the streamLen
+ if (params.sflv.valueEndOffset > streamLen)
+ {
+ fprintf(
+ stderr,
+ "Value goes beyond stream length. SFLV Offset: %u, valueEndOffset: %u, streamLen: %u\n",
+ params.state.encodedStreamOffset, params.sflv.valueEndOffset,
+ streamLen);
+ return bejErrorInvalidSize;
+ }
if (params.sflv.format.readOnlyProperty)
{