From b7afc99cdeaf8d42b10617595fbd94c9ca1c4c03 Mon Sep 17 00:00:00 2001 From: "Jose F. Martinez-Rivera" Date: Fri, 9 Jul 2021 13:10:46 -0400 Subject: [PATCH] fix(decoder): Fixes buffer overflow when decoding large g729 frames --- Dockerfile | 2 +- meson.build | 10 ++++++++-- src/G729Decoder.cpp | 25 ++++++++++++++----------- src/G729Encoder.cpp | 18 +++++++++--------- 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/Dockerfile b/Dockerfile index 84f78aa..2d564a6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM registry.access.redhat.com/ubi8/ubi RUN yum update --disableplugin=subscription-manager -y && \ yum install --disableplugin=subscription-manager -y git python3 python3-pip python3-setuptools python3-wheel zip && \ - yum install --disableplugin=subscription-manager curl make automake autoconf libuv pkgconfig sudo file gcc gcc-c++ openssl-devel -y && \ + yum install --disableplugin=subscription-manager libasan libubsan curl gdb make automake autoconf procps libuv pkgconfig sudo file gcc gcc-c++ openssl-devel -y && \ yum clean all && \ rm -rf /var/cache/yum diff --git a/meson.build b/meson.build index c3b160c..de7eb12 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,11 @@ project('g729-codec-service','c', 'cpp', version: '0.0.2', default_options : ['c_std=c17', 'cpp_std=c++17']) + +#add_global_arguments('-fsanitize=address', language : 'c') +#add_global_arguments('-fsanitize=address', language : 'cpp') + +#add_global_link_arguments('-fsanitize=address', language : 'cpp') +#add_global_link_arguments('-fsanitize=address', language : 'c') + usockets = subproject('usockets') rapidjson = subproject('rapidjson') uwebsockets = subproject('uwebsockets') @@ -40,8 +47,7 @@ executable('g729-codec-service', 'src/TLSOptions.hpp', 'src/LogUtils.hpp', dependencies: [bcg729_dep, librapidjson, usockets_dep, uwebsockets_dep, zlib_dep, spdlog_dep], -install: true -) +install: true) # inc = include_directories('src') # executable('tests', diff --git a/src/G729Decoder.cpp b/src/G729Decoder.cpp index c4bd7e3..594df8d 100644 --- a/src/G729Decoder.cpp +++ b/src/G729Decoder.cpp @@ -23,15 +23,14 @@ # define MAX_DECODER_INPUT 10 # define MAX_BIT_STREAM_SIZE 10 -void decode_g729(bcg729DecoderChannelContextStruct *decoderContext, uint8_t * g729, int length, int16_t * pcm) { - int numberOfDecoderPayloads = length / MAX_DECODER_INPUT; +void decode_g729(bcg729DecoderChannelContextStruct *decoderContext, uint8_t * g729, int numberOfDecoderFrames, int payloadLength, int16_t * pcm) { - int remainingPacketLength = length; + int remainingPacketLength = payloadLength; uint8_t frameErased = 0; uint8_t sidFrame = 0; int bitStreamSize = MAX_BIT_STREAM_SIZE; - for (int i = 0; i < numberOfDecoderPayloads; i++) { + for (int i = 0; i < numberOfDecoderFrames; i++) { if (remainingPacketLength >= MAX_BIT_STREAM_SIZE) { bitStreamSize = MAX_BIT_STREAM_SIZE; } else if (remainingPacketLength == 2) { @@ -59,16 +58,20 @@ G729Decoder::~G729Decoder() { void G729Decoder::processFrame(AudioFrame& inputFrame, AudioFrame& outputFrame) { int sizeInBytes = inputFrame.size; - int16_t * pcm = new int16_t[FRAME_SIZE * 2](); - decode_g729(decoderContext, (uint8_t *) inputFrame.data, sizeInBytes, pcm); + int numberOfG729Frames = sizeInBytes / MAX_DECODER_INPUT; + + int16_t * pcm = new int16_t[FRAME_SIZE * numberOfG729Frames](); + decode_g729(decoderContext, (uint8_t *) inputFrame.data, numberOfG729Frames, sizeInBytes, pcm); outputFrame.data = (int8_t *) pcm; - outputFrame.size = (FRAME_SIZE) * 4; + outputFrame.size = (FRAME_SIZE) * numberOfG729Frames * 2; } void G729Decoder::processFrame(AudioFrame& inputFrame, AudioFrame& outputFrame, VADEvent &vadEvent) { int sizeInBytes = inputFrame.size; + int numberOfG729Frames = sizeInBytes / MAX_DECODER_INPUT; + spdlog::trace("got frame of length = {}", sizeInBytes); - if (sizeInBytes == 20 && !voiceActive) { + if (sizeInBytes >= 20 && !voiceActive) { vadEvent = VADEvent::START_OF_SPEECH; voiceActive = true; spdlog::debug("speech started"); @@ -81,9 +84,9 @@ void G729Decoder::processFrame(AudioFrame& inputFrame, AudioFrame& outputFrame, } else { vadEvent = VADEvent::NONE; } - int16_t * pcm = new int16_t[FRAME_SIZE * 2](); - decode_g729(decoderContext, (uint8_t *) inputFrame.data, sizeInBytes, pcm); + int16_t * pcm = new int16_t[FRAME_SIZE * numberOfG729Frames](); + decode_g729(decoderContext, (uint8_t *) inputFrame.data, numberOfG729Frames, sizeInBytes, pcm); outputFrame.data = (int8_t *) pcm; - outputFrame.size = (FRAME_SIZE) * 4; + outputFrame.size = (FRAME_SIZE) * numberOfG729Frames * 2; spdlog::trace("generated frame of size = {}", outputFrame.size); } diff --git a/src/G729Encoder.cpp b/src/G729Encoder.cpp index 1427685..f31fc34 100644 --- a/src/G729Encoder.cpp +++ b/src/G729Encoder.cpp @@ -23,8 +23,7 @@ # define FRAME_SIZE 80 // 80 samples per frame # define MAX_ENCODER_OUTPUT 10 //# define -int encode_g729_frame(bcg729EncoderChannelContextStruct *encoderChannelContext, int16_t * pcm, int frameSize, uint8_t * data) { - int numberOfEncodingFrames = frameSize / FRAME_SIZE; +int encode_g729_frame(bcg729EncoderChannelContextStruct *encoderChannelContext, int16_t * pcm, int numberOfEncodingFrames, uint8_t * data) { int totalSize = 0; // 160 samples // 2 frames to decode @@ -50,19 +49,20 @@ G729Encoder::~G729Encoder() { } void G729Encoder::processFrame(AudioFrame& inputFrame, AudioFrame& outputFrame) { - int samples = inputFrame.size / 2; - uint8_t * g729_frames = new uint8_t[samples * MAX_ENCODER_OUTPUT](); - int byteSize = encode_g729_frame(encoderContext, (int16_t *) inputFrame.data, samples, g729_frames); + int frameSize = inputFrame.size / 2; + int numberOfEncodingFrames = frameSize / FRAME_SIZE; + uint8_t * g729_frames = new uint8_t[numberOfEncodingFrames * MAX_ENCODER_OUTPUT](); + int byteSize = encode_g729_frame(encoderContext, (int16_t *) inputFrame.data, numberOfEncodingFrames, g729_frames); outputFrame.data = (int8_t *) g729_frames; outputFrame.size = byteSize; } void G729Encoder::processFrame(AudioFrame& inputFrame, AudioFrame& outputFrame, VADEvent &vadEvent) { - - int samples = inputFrame.size / 2; - uint8_t * g729_frames = new uint8_t[samples * MAX_ENCODER_OUTPUT](); - int byteSize = encode_g729_frame(encoderContext, (int16_t *) inputFrame.data, samples, g729_frames); + int frameSize = inputFrame.size / 2; + int numberOfEncodingFrames = frameSize / FRAME_SIZE; + uint8_t * g729_frames = new uint8_t[numberOfEncodingFrames * MAX_ENCODER_OUTPUT](); + int byteSize = encode_g729_frame(encoderContext, (int16_t *) inputFrame.data, numberOfEncodingFrames, g729_frames); vadEvent = VADEvent::NONE; if (byteSize >= 2 && byteSize <= 12) { if (voiceActive) {