Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up ex-malloc() use of CHIPMem.h #3222

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/controller/CHIPDeviceController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <core/CHIPEncoding.h>
#include <core/CHIPSafeCasts.h>
#include <support/Base64.h>
#include <support/CHIPMem.h>
#include <support/CodeUtils.h>
#include <support/ErrorStr.h>
#include <support/TimeUtils.h>
Expand Down
7 changes: 4 additions & 3 deletions src/inet/tests/TestInetCommonOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include "TestInetCommonOptions.h"

#include <assert.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
Expand Down Expand Up @@ -258,9 +259,9 @@ bool FaultInjectionOptions::HandleOption(const char * progName, OptionSet * optS
{
#if CHIP_CONFIG_TEST || CHIP_SYSTEM_CONFIG_TEST || INET_CONFIG_TEST
case kToolCommonOpt_FaultInjection: {
char * mutableArg = chip::Platform::MemoryAllocString(arg);
bool parseRes = ParseFaultInjectionStr(mutableArg, faultMgrFnTable, faultMgrFnTableLen);
chip::Platform::MemoryFree(mutableArg);
chip::Platform::ScopedMemoryString mutableArg(arg, strlen(arg));
assert(mutableArg);
bool parseRes = ParseFaultInjectionStr(mutableArg.Get(), faultMgrFnTable, faultMgrFnTableLen);
if (!parseRes)
{
PrintArgError("%s: Invalid string specified for fault injection option: %s\n", progName, arg);
Expand Down
16 changes: 7 additions & 9 deletions src/lib/core/tests/TestCHIPTLV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <support/CHIPMem.h>
#include <support/CodeUtils.h>
#include <support/RandUtils.h>
#include <support/ScopedBuffer.h>
#include <support/TestUtils.h>

#include <string.h>
Expand Down Expand Up @@ -212,14 +213,13 @@ void TestString(nlTestSuite * inSuite, TLVReader & reader, uint64_t tag, const c
uint32_t expectedLen = strlen(expectedVal);
NL_TEST_ASSERT(inSuite, reader.GetLength() == expectedLen);

char * val = static_cast<char *>(chip::Platform::MemoryAlloc(expectedLen + 1));
chip::Platform::ScopedMemoryBuffer<char> valBuffer;
char * val = static_cast<char *>(valBuffer.Alloc(expectedLen + 1).Get());

CHIP_ERROR err = reader.GetString(val, expectedLen + 1);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

NL_TEST_ASSERT(inSuite, memcmp(val, expectedVal, expectedLen + 1) == 0);

chip::Platform::MemoryFree(val);
}

void TestDupString(nlTestSuite * inSuite, TLVReader & reader, uint64_t tag, const char * expectedVal)
Expand All @@ -230,14 +230,13 @@ void TestDupString(nlTestSuite * inSuite, TLVReader & reader, uint64_t tag, cons
uint32_t expectedLen = strlen(expectedVal);
NL_TEST_ASSERT(inSuite, reader.GetLength() == expectedLen);

char * val = static_cast<char *>(chip::Platform::MemoryAlloc(expectedLen + 1));
chip::Platform::ScopedMemoryBuffer<char> valBuffer;
char * val = static_cast<char *>(valBuffer.Alloc(expectedLen + 1).Get());
kpschoedel marked this conversation as resolved.
Show resolved Hide resolved

CHIP_ERROR err = reader.DupString(val);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

NL_TEST_ASSERT(inSuite, memcmp(val, expectedVal, expectedLen + 1) == 0);

chip::Platform::MemoryFree(val);
}

void TestDupBytes(nlTestSuite * inSuite, TLVReader & reader, uint64_t tag, const uint8_t * expectedVal, uint32_t expectedLen)
Expand All @@ -247,13 +246,12 @@ void TestDupBytes(nlTestSuite * inSuite, TLVReader & reader, uint64_t tag, const

NL_TEST_ASSERT(inSuite, reader.GetLength() == expectedLen);

uint8_t * val = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(expectedLen));
chip::Platform::ScopedMemoryBuffer<uint8_t> valBuffer;
uint8_t * val = static_cast<uint8_t *>(valBuffer.Alloc(expectedLen).Get());
CHIP_ERROR err = reader.DupBytes(val, expectedLen);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);

NL_TEST_ASSERT(inSuite, memcmp(val, expectedVal, expectedLen) == 0);

chip::Platform::MemoryFree(val);
}

void TestBufferContents(nlTestSuite * inSuite, PacketBuffer * buf, const uint8_t * expectedVal, uint32_t expectedLen)
Expand Down
1 change: 0 additions & 1 deletion src/lib/support/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ static_library("support") {
"Base64.cpp",
"CHIPArgParser.cpp",
"CHIPCounter.cpp",
"CHIPMemString.cpp",
"CHIPPlatformMemory.cpp",
"ErrorStr.cpp",
"FibonacciUtils.cpp",
Expand Down
11 changes: 4 additions & 7 deletions src/lib/support/CHIPArgParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,29 +491,26 @@ bool ParseArgs(const char * progName, int argc, char * argv[], OptionSet * optSe
bool ParseArgsFromString(const char * progName, const char * argStr, OptionSet * optSets[],
NonOptionArgHandlerFunct nonOptArgHandler, bool ignoreUnknown)
{
char * argStrCopy = nullptr;
char ** argv = nullptr;
char ** argv = nullptr;
int argc;
bool res;

argStrCopy = chip::Platform::MemoryAllocString(argStr);
if (argStrCopy == nullptr)
chip::Platform::ScopedMemoryString argStrCopy(argStr, strlen(argStr));
if (!argStrCopy)
{
PrintArgError("%s: Memory allocation failure\n", progName);
return false;
}

argc = SplitArgs(argStrCopy, argv, const_cast<char *>(progName));
argc = SplitArgs(argStrCopy.Get(), argv, const_cast<char *>(progName));
if (argc < 0)
{
PrintArgError("%s: Memory allocation failure\n", progName);
chip::Platform::MemoryFree(argStrCopy);
return false;
}

res = ParseArgs(progName, argc, argv, optSets, nonOptArgHandler, ignoreUnknown);

chip::Platform::MemoryFree(argStrCopy);
chip::Platform::MemoryFree(argv);

return res;
Expand Down
48 changes: 0 additions & 48 deletions src/lib/support/CHIPMemString.cpp

This file was deleted.

66 changes: 57 additions & 9 deletions src/lib/support/CHIPMemString.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,79 @@
* This file defines string operations that allocate heap memory.
*/

#ifndef CHIP_MEM_STRING_H
#define CHIP_MEM_STRING_H
#pragma once

#include <stdlib.h>
#include <string.h>

#include <support/ScopedBuffer.h>

namespace chip {
namespace Platform {

/**
* Copies a C-style string.
*
* This differs from `strncpy()` in some important ways:
* - `dest` can be nullptr, in which case no copy is attempted, and the function returns nullptr.
* - A non-nullptr result is always null-terminated.
*
* @param[in] dest Destination string buffer (which must be at least `length`+1 bytes)
* or nullptr.
*
* @param[in] source String to be copied.
*
* @param[in] length Length to be copied.
*
* @retval Same as `dest`.
*/
inline char * CopyString(char * dest, const char * source, size_t length)
{
if (dest)
{
memcpy(dest, source, length);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any issues if source is shorter than length? Maybe we could use strncpy internally.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was about to say no (NUL in the source is fine, NUL not in the source is fine) but there is one case where memcpy would break (NUL-terminated source closely followed by dangerous addresses).

dest[length] = 0;
}
return dest;
}

/**
* This function copies a C-style string to memory newly allocated by Platform::MemoryAlloc().
*
* @param[in] string String to be copied.
*
* @param[in] length Length of the string to be copied. If zero, `strlen(string)`
* will be used. Like `strncpy()`, if the `string` is shorter
* then the remaining space up to `length` will be filled with
* null bytes.
* @param[in] length Length to be copied. Like `strncpy()`, if the `string` is shorter
* than `length`, then the remaining space will be filled with null
* bytes. Like `strndup()` but unlike `strncpy()`, the result is always
* null-terminated.
*
* @retval Pointer to a null-terminated string in case of success.
* @retval `nullptr` if memory allocation fails.
*
*/
extern char * MemoryAllocString(const char * string, size_t length = 0);
inline char * MemoryAllocString(const char * string, size_t length)
{
return CopyString(static_cast<char *>(MemoryAlloc(length + 1)), string, length);
}

/**
* Represents a C string in a ScopedMemoryBuffer.
*/

class ScopedMemoryString : public ScopedMemoryBuffer<char>
{
public:
/**
* Create a ScopedMemoryString.
*
* @param[in] string String to be copied.
*
* @param[in] length Length to be copied. Like `strncpy()`, if the `string` is shorter than
* `length`, then the remaining space will be filled with null bytes. Like
* `strndup()` but unlike `strncpy()`, the result is always null-terminated.
*/
ScopedMemoryString(const char * string, size_t length) { CopyString(Alloc(length + 1).Get(), string, length); }
};

} // namespace Platform
} // namespace chip

#endif // CHIP_MEM_STRING_H
10 changes: 5 additions & 5 deletions src/lib/support/tests/TestCHIPArgParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -691,11 +691,11 @@ static bool HandleOption(const char * progName, OptionSet * optSet, int id, cons

VerifyOrQuit(sCallbackRecordCount < kMaxCallbackRecords, "Out of callback records");
sCallbackRecords[sCallbackRecordCount].Type = CallbackRecord::kHandleOption;
sCallbackRecords[sCallbackRecordCount].ProgName = chip::Platform::MemoryAllocString(progName);
sCallbackRecords[sCallbackRecordCount].ProgName = chip::Platform::MemoryAllocString(progName, strlen(progName));
sCallbackRecords[sCallbackRecordCount].OptSet = optSet;
sCallbackRecords[sCallbackRecordCount].Id = id;
sCallbackRecords[sCallbackRecordCount].Name = chip::Platform::MemoryAllocString(name);
sCallbackRecords[sCallbackRecordCount].Arg = (arg != nullptr) ? chip::Platform::MemoryAllocString(arg) : nullptr;
sCallbackRecords[sCallbackRecordCount].Name = chip::Platform::MemoryAllocString(name, strlen(name));
sCallbackRecords[sCallbackRecordCount].Arg = (arg != nullptr) ? chip::Platform::MemoryAllocString(arg, strlen(arg)) : nullptr;
sCallbackRecordCount++;
return true;
}
Expand All @@ -716,15 +716,15 @@ static bool HandleNonOptionArgs(const char * progName, int argc, char * argv[])

VerifyOrQuit(sCallbackRecordCount < kMaxCallbackRecords, "Out of callback records");
sCallbackRecords[sCallbackRecordCount].Type = CallbackRecord::kHandleNonOptionArgs;
sCallbackRecords[sCallbackRecordCount].ProgName = chip::Platform::MemoryAllocString(progName);
sCallbackRecords[sCallbackRecordCount].ProgName = chip::Platform::MemoryAllocString(progName, strlen(progName));
sCallbackRecords[sCallbackRecordCount].Argc = argc;
sCallbackRecordCount++;

for (int i = 0; i < argc; i++)
{
VerifyOrQuit(sCallbackRecordCount < kMaxCallbackRecords, "Out of callback records");
sCallbackRecords[sCallbackRecordCount].Type = CallbackRecord::kNonOptionArg;
sCallbackRecords[sCallbackRecordCount].Arg = chip::Platform::MemoryAllocString(argv[i]);
sCallbackRecords[sCallbackRecordCount].Arg = chip::Platform::MemoryAllocString(argv[i], strlen(argv[i]));
sCallbackRecordCount++;
}

Expand Down
14 changes: 5 additions & 9 deletions src/platform/ESP32/ESP32Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,21 +365,17 @@ CHIP_ERROR ESP32Config::WriteConfigValueStr(Key key, const char * str)
CHIP_ERROR ESP32Config::WriteConfigValueStr(Key key, const char * str, size_t strLen)
{
CHIP_ERROR err;
char * strCopy = NULL;
chip::Platform::ScopedMemoryBuffer<char> strCopy;

if (str != NULL)
{
strCopy = chip::Platform::MemoryAllocString(str, strLen);
VerifyOrExit(strCopy != NULL, err = CHIP_ERROR_NO_MEMORY);
strCopy.Calloc(strLen + 1);
VerifyOrExit(strCopy, err = CHIP_ERROR_NO_MEMORY);
strncpy(strCopy.Get(), str, strLen);
}

err = ESP32Config::WriteConfigValueStr(key, strCopy);
err = ESP32Config::WriteConfigValueStr(key, strCopy.Get());

exit:
if (strCopy != NULL)
{
chip::Platform::MemoryFree(strCopy);
}
return err;
}

Expand Down