Skip to content

Commit

Permalink
Fix unbounded stack in emberAfPrintBuffer() (#4633)
Browse files Browse the repository at this point in the history
* Fix unbounded stack in emberAfPrintBuffer()

#### Problem

emberAfPrintBuffer() allocates stack space based on an argument, with
no upper bound. This could lead to stack exhaustion on small devices.

#### Summary of Changes

Print long buffers in multiple segments.

Fixes #3662 - Unbounded stack in emberAfPrintBuffer()

* Use CHIP_DEVICE_CONFIG_LOG_MESSAGE_MAX_SIZE for buffer size

* TODO

* casts
  • Loading branch information
kpschoedel authored and pull[bot] committed Feb 10, 2021
1 parent 73a7721 commit 1438534
Showing 1 changed file with 24 additions and 18 deletions.
42 changes: 24 additions & 18 deletions src/app/util/ember-print.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
*
* Copyright (c) 2020 Project CHIP Authors
* Copyright (c) 2020-2021 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,6 +20,8 @@

#include "debug-printing.h"

#include <platform/CHIPDeviceConfig.h>
#include <support/CodeUtils.h>
#include <support/logging/CHIPLogging.h>

bool emberAfPrintReceivedMessages = true;
Expand All @@ -28,7 +30,7 @@ using namespace chip::Logging;

void emberAfPrint(int category, const char * format, ...)
{
if (format != NULL)
if (format != nullptr)
{
va_list args;
va_start(args, format);
Expand All @@ -39,7 +41,7 @@ void emberAfPrint(int category, const char * format, ...)

void emberAfPrintln(int category, const char * format, ...)
{
if (format != NULL)
if (format != nullptr)
{
va_list args;
va_start(args, format);
Expand All @@ -48,35 +50,39 @@ void emberAfPrintln(int category, const char * format, ...)
}
}

// TODO: issue #3662 - Unbounded stack in emberAfPrintBuffer()
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstack-usage="
// TODO: add unit tests.

void emberAfPrintBuffer(int category, const uint8_t * buffer, uint16_t length, bool withSpace)
{
if (buffer != NULL && length > 0)
if (buffer != nullptr && length > 0)
{
const char * perByteFormatStr = withSpace ? "%02hhX " : "%02hhX";
uint8_t perByteCharCount = withSpace ? 3 : 2;
constexpr uint16_t kBufferSize = CHIP_DEVICE_CONFIG_LOG_MESSAGE_MAX_SIZE;
const char * perByteFormatStr = withSpace ? "%02hhX " : "%02hhX";
const uint8_t perByteCharCount = withSpace ? 3 : 2;
const uint16_t bytesPerBuffer = static_cast<uint16_t>((kBufferSize - 1) / perByteCharCount);
char result[kBufferSize];

uint32_t outStringLength = length * perByteCharCount + 1;
char result[outStringLength];
for (uint32_t dst_idx = 0, index = 0; dst_idx < outStringLength - 1 && index < length; dst_idx += perByteCharCount, index++)
uint16_t index = 0;
while (index < length)
{

snprintf(result + dst_idx, outStringLength - dst_idx, perByteFormatStr, buffer[index]);
const uint16_t remainingBytes = static_cast<uint16_t>(length - index);
const uint16_t segmentLength = chip::min(bytesPerBuffer, remainingBytes);
const uint16_t segmentEnd = static_cast<uint16_t>(index + segmentLength);
const uint32_t outStringEnd = segmentLength * perByteCharCount;
for (uint32_t dst_idx = 0; dst_idx < outStringEnd && index < segmentEnd; dst_idx += perByteCharCount, index++)
{
snprintf(result + dst_idx, outStringEnd - dst_idx + 1, perByteFormatStr, buffer[index]);
}
result[outStringEnd] = 0;
emberAfPrint(category, "%s", result);
}
result[outStringLength - 1] = 0;
emberAfPrint(category, "%s", result);
}
else
{
emberAfPrint(EMBER_AF_PRINT_CORE, "NULL");
}
}

#pragma GCC diagnostic pop // -Wstack-usage

void emberAfPrintString(int category, const uint8_t * string)
{
emberAfPrint(category, "%s", string);
Expand Down

0 comments on commit 1438534

Please sign in to comment.