From d546ebac6f8fe0e7ddb7588413ad014e90e33bae Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Mon, 1 Mar 2021 16:52:05 +0100 Subject: [PATCH] - restrict maximum recursion depth in BerDecoder_decodeLength when indefinite length encoding is used to avoid stack overflow when receiving malformed messages --- src/mms/asn1/ber_decode.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/mms/asn1/ber_decode.c b/src/mms/asn1/ber_decode.c index f19ecdca..12078610 100644 --- a/src/mms/asn1/ber_decode.c +++ b/src/mms/asn1/ber_decode.c @@ -25,8 +25,16 @@ #include "ber_decode.h" static int -getIndefiniteLength(uint8_t* buffer, int bufPos, int maxBufPos) +BerDecoder_decodeLengthRecursive(uint8_t* buffer, int* length, int bufPos, int maxBufPos, int depth, int maxDepth); + +static int +getIndefiniteLength(uint8_t* buffer, int bufPos, int maxBufPos, int depth, int maxDepth) { + depth++; + + if (depth > maxDepth) + return -1; + int length = 0; while (bufPos < maxBufPos) { @@ -44,7 +52,7 @@ getIndefiniteLength(uint8_t* buffer, int bufPos, int maxBufPos) int subLength = -1; - int newBufPos = BerDecoder_decodeLength(buffer, &subLength, bufPos, maxBufPos); + int newBufPos = BerDecoder_decodeLengthRecursive(buffer, &subLength, bufPos, maxBufPos, depth, maxDepth); if (newBufPos == -1) return -1; @@ -58,8 +66,8 @@ getIndefiniteLength(uint8_t* buffer, int bufPos, int maxBufPos) return -1; } -int -BerDecoder_decodeLength(uint8_t* buffer, int* length, int bufPos, int maxBufPos) +static int +BerDecoder_decodeLengthRecursive(uint8_t* buffer, int* length, int bufPos, int maxBufPos, int depth, int maxDepth) { if (bufPos >= maxBufPos) return -1; @@ -70,7 +78,7 @@ BerDecoder_decodeLength(uint8_t* buffer, int* length, int bufPos, int maxBufPos) int lenLength = len1 & 0x7f; if (lenLength == 0) { /* indefinite length form */ - *length = getIndefiniteLength(buffer, bufPos, maxBufPos); + *length = getIndefiniteLength(buffer, bufPos, maxBufPos, depth, maxDepth); } else { *length = 0; @@ -105,6 +113,12 @@ BerDecoder_decodeLength(uint8_t* buffer, int* length, int bufPos, int maxBufPos) return bufPos; } +int +BerDecoder_decodeLength(uint8_t* buffer, int* length, int bufPos, int maxBufPos) +{ + return BerDecoder_decodeLengthRecursive(buffer, length, bufPos, maxBufPos, 0, 50); +} + char* BerDecoder_decodeString(uint8_t* buffer, int strlen, int bufPos, int maxBufPos) {