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

Remove explicit malloc()-family calls from first-party code. #3143

Merged
merged 7 commits into from
Oct 9, 2020

Conversation

kpschoedel
Copy link
Contributor

Problem

Embedded device-side code should only use heap through CHIPMem.h.
In particular it should not call malloc()-family functions.

Summary of Changes

  • Replace direct calls to malloc()/calloc()/realloc()/free().
  • Ensure that malloc()-family calls in non-device code are suitably
    guarded by #ifs.
  • Add a C wrapper for Platform::Memory… functions, for
    src/lwip/standalone/sys_arch.c and platform C.
  • Add a str[n]dup() equivalent, as calls are paired with free().

Fixes #2807 Remove explicit use of malloc() from first-party embedded-device code
Fixes #3092 CHIPMem.h called from C

Copy link
Contributor

@bzbarsky-apple bzbarsky-apple left a comment

Choose a reason for hiding this comment

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

There should probably be more use of ScopedBuffer here, but a separate PR for that would be better.


tmpBuf = static_cast<char *>(malloc(dataLen + 1));
tmpBuf = static_cast<char *>(chip::Platform::MemoryAlloc(dataLen + 1));
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this write to a temp buffer better than the old !HAVE_MALLOC code which directly wrote it into our buffer? Especially if we fix that code to properly length-check how much space we have left...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It isn't, but my intent is for there to be no changes in this PR beyond what's required for a straight substitution of malloc→MemoryAlloc() etc. Later PRs can try to eliminate some of those uses entirely.

@@ -282,7 +283,7 @@ void InitNetwork()
for (size_t j = 0; j < gNetworkOptions.LocalIPv6Addr.size(); j++)
{
uint64_t iid = gNetworkOptions.LocalIPv6Addr[j].InterfaceId();
char * tap_name = (char *) malloc(sizeof(gDefaultTapDeviceName));
char * tap_name = (char *) chip::Platform::MemoryAlloc(sizeof(gDefaultTapDeviceName));
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe while we change this, add an assert that this is not null?

@@ -256,9 +258,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 = strdup(arg);
char * mutableArg = chip::Platform::MemoryAllocString(arg);
Copy link
Contributor

Choose a reason for hiding this comment

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

using ScopedBuffer and asserting non-null may be useful here

if (buf == nullptr)
return CHIP_ERROR_NO_MEMORY;

CHIP_ERROR err = ReadData(buf, static_cast<uint32_t>(mElemLenOrVal));
if (err != CHIP_NO_ERROR)
{
free(buf);
chip::Platform::MemoryFree(buf);
Copy link
Contributor

Choose a reason for hiding this comment

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

should we also set buf to nullptr here as well?

if (buf == nullptr)
return CHIP_ERROR_NO_MEMORY;

CHIP_ERROR err = ReadData(reinterpret_cast<uint8_t *>(buf), static_cast<uint32_t>(mElemLenOrVal));
if (err != CHIP_NO_ERROR)
{
free(buf);
chip::Platform::MemoryFree(buf);
Copy link
Contributor

Choose a reason for hiding this comment

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

I would set buf null here as well

@@ -211,14 +212,14 @@ 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 *>(malloc(expectedLen + 1));
char * val = static_cast<char *>(chip::Platform::MemoryAlloc(expectedLen + 1));
Copy link
Contributor

Choose a reason for hiding this comment

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

I would suggest using https://github.com/project-chip/connectedhomeip/blob/master/src/lib/support/ScopedBuffer.h in here if possible, to not need to pair up alloc and free.

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'd prefer to do a 1:1 swap in this PR and all the improvements in a separate one, to keep the history clearer.

*/

#ifndef CHIP_MEM_STRING_H
#define CHIP_MEM_STRING_H
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: consider #pragma once


extern "C" {

extern int CHIPPlatformMemoryInit(void * buf, size_t bufSize)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why can't this just be in CHIPMem.h and the rest hidden by ifdef __cplusplus ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mean the declarations, or are you suggesting defining them inline in the header?

Copy link
Contributor

Choose a reason for hiding this comment

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

I meant the declarations. Not sure if it's better, perhaps separate is the way to go.

Copy link
Contributor Author

@kpschoedel kpschoedel Oct 10, 2020

Choose a reason for hiding this comment

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

The rationale for making them separate is to avoid adding non-namespaced symbols to a common header.

src/lib/support/BUILD.gn Outdated Show resolved Hide resolved
@kpschoedel
Copy link
Contributor Author

Argh, my rebase made a mess.

#### Problem

Embedded device-side code should only use heap through CHIPMem.h.
In particular it should not call malloc()-family functions.

#### Summary of Changes

- Replace direct calls to malloc()/calloc()/realloc()/free().
- Ensure that malloc()-family calls in non-device code are suitably
  guarded by #ifs.
- Add a C wrapper for Platform::Memory… functions, for
  src/lwip/standalone/sys_arch.c and platform C.
- Add a str[n]dup() equivalent, as calls are paired with free().

fixes project-chip#2807 Remove explicit use of malloc() from first-party embedded-device code
fixes project-chip#3092 CHIPMem.h called from C
@mspang mspang merged commit 41feafa into project-chip:master Oct 9, 2020
@kpschoedel kpschoedel deleted the x2899-mem-malloc branch October 13, 2020 14:45
kpschoedel added a commit to kpschoedel/connectedhomeip that referenced this pull request Oct 13, 2020
#### Problem

As part of heap memory management, a recent change (project-chip#3143) replaced
malloc()-family calls one-for-one with their "CHIPMem.h" equivalents,
but a one-to-one replacement is not always ideal.

#### Summary of Changes

- Use ScopedMemoryBuffer instead where possible.
- Added ScopedMemoryString, since this is a common case.
- Some addition safety checks.
kpschoedel added a commit to kpschoedel/connectedhomeip that referenced this pull request Oct 13, 2020
 #### Problem

As part of heap memory management, a recent change (project-chip#3143) replaced
malloc()-family calls one-for-one with their "CHIPMem.h" equivalents.
Reviewers proposed some related small safety changes.

 #### Summary of Changes

- added an assert()
- null out two dead pointers
andy31415 pushed a commit that referenced this pull request Oct 14, 2020
#### Problem

As part of heap memory management, a recent change (#3143) replaced
malloc()-family calls one-for-one with their "CHIPMem.h" equivalents.
Reviewers proposed some related small safety changes.

 #### Summary of Changes

- added an assert()
- null out two dead pointers
BroderickCarlin pushed a commit that referenced this pull request Oct 16, 2020
* Clean up ex-malloc() use of CHIPMem.h

#### Problem

As part of heap memory management, a recent change (#3143) replaced
malloc()-family calls one-for-one with their "CHIPMem.h" equivalents,
but a one-to-one replacement is not always ideal.

#### Summary of Changes

- Use ScopedMemoryBuffer instead where possible.
- Added ScopedMemoryString, since this is a common case.
- Some addition safety checks.

* Split off safety changes.

* Simplified string operations.

* Move strlen to callers

* Review
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CHIPMem.h called from C Remove explicit use of malloc() from first-party embedded-device code
7 participants