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

Replaced str... with strn... methods #37690

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

kkasperczyk-no
Copy link
Contributor

Static code analysis shown that there are several places that str.. methods are used, what may lead to the bad memory access. Replaced all of them with corresponding strn... methods.

Testing

Tested in CI.

@kkasperczyk-no kkasperczyk-no requested review from a team as code owners February 20, 2025 12:47
Copy link

Review changes with  SemanticDiff

Copy link

github-actions bot commented Feb 20, 2025

PR #37690: Size comparison from 7dccded to 10698f7

Full report (17 builds for bl602, bl702, bl702l, cc13x4_26x4, cc32xx, qpg, stm32, tizen)
platform target config section 7dccded 10698f7 change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1095122 1095126 4 0.0
RAM 94802 94802 0 0.0
bl702 lighting-app bl702+eth FLASH 651568 651572 4 0.0
RAM 33509 33509 0 0.0
bl702+wifi FLASH 827732 827736 4 0.0
RAM 22233 22233 0 0.0
bl706+mfd+rpc+littlefs FLASH 1060894 1060902 8 0.0
RAM 32157 32157 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 892080 892088 8 0.0
RAM 26896 26896 0 0.0
lighting-app bl702l+mfd+littlefs FLASH 974976 974984 8 0.0
RAM 24644 24644 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 815260 815276 16 0.0
RAM 120256 120256 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 824172 824188 16 0.0
RAM 125352 125352 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 771040 771056 16 0.0
RAM 113724 113724 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 755316 755332 16 0.0
RAM 113932 113932 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 538746 538750 4 0.0
RAM 205112 205112 0 0.0
lock CC3235SF_LAUNCHXL FLASH 572902 572906 4 0.0
RAM 205360 205360 0 0.0
qpg lighting-app qpg6105+debug FLASH 662148 662148 0 0.0
RAM 105116 105116 0 0.0
lock-app qpg6105+debug FLASH 620256 620264 8 0.0
RAM 99664 99664 0 0.0
stm32 light STM32WB5MM-DK FLASH 459792 459792 0 0.0
RAM 141472 141472 0 0.0
tizen all-clusters-app arm unknown 5076 5076 0 0.0
FLASH 1750484 1750520 36 0.0
RAM 93260 93260 0 0.0
chip-tool-ubsan arm unknown 11476 11476 0 0.0
FLASH 18960910 18960982 72 0.0
RAM 8297032 8297080 48 0.0

Copy link

github-actions bot commented Feb 20, 2025

PR #37690: Size comparison from 24d61c6 to 56ebe19

Full report (3 builds for cc32xx, stm32)
platform target config section 24d61c6 56ebe19 change % change
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 538802 538806 4 0.0
RAM 205112 205112 0 0.0
lock CC3235SF_LAUNCHXL FLASH 572950 572954 4 0.0
RAM 205360 205360 0 0.0
stm32 light STM32WB5MM-DK FLASH 459784 459792 8 0.0
RAM 141472 141472 0 0.0

@@ -102,15 +102,16 @@ static void HandleNodeBrowse(void * context, DnssdService * services, size_t ser
auto & ipAddress = services[i].mAddress;

// mType(service name) exactly matches with operational service name
bool isOperationalBrowse = strcmp(services[i].mType, kOperationalServiceName) == 0;
bool isOperationalBrowse = strncmp(services[i].mType, kOperationalServiceName, sizeof(kOperationalServiceName)) == 0;
Copy link
Contributor

@Damian-Nordic Damian-Nordic Feb 20, 2025

Choose a reason for hiding this comment

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

When you do strncmp(buffer, const, length), length should be the size of the buffer, not the size of the constant. Otherwise, strncmp(buffer, const, length) == 0 becomes "Is const a prefix of buffer?", which may change the behavior.

Overall, it seems adding the following helper in CHIPMemString.h may be less error prone than trying to use the right constant manually:

template <size_t N>
inline bool StringEquals(char (&str1)[N], const char* str2)
{
    return strncmp(str1, str2, N) == 0;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

becomes "Is const a prefix of buffer?

Ah right, good catch! So isn't it just enough to use kDnssdTypeMaxSize + 1 instead?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, it should be enough in this case. I only proposed a more generic solution as it's hard for a reviewer to catch these kinds of errors (one has to check what the actual buffer size is).

return WriteConfigValueStr(key, str, str ? strlen(str) : 0);
/* The max value size is smaller than the sector size by several ATE size, but the API to get the exact size is not available.
* The backend implementation validates the detailed size, so we don't need to do that here. */
return WriteConfigValueStr(key, str, str ? strnlen(str, sSectorSize) : 0);
Copy link
Contributor

Choose a reason for hiding this comment

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

Honestly, this code doesn't really protect from out of bounds reads as the sector size will most of the time be an order of magnitude bigger than the value provided. The API contract is that str must be null-terminated and we have no other choice than to trust it is.

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 see, thanks for the input

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 will put a comment there, as we are going to keep getting this usage as potentially error-prone from the coverity. This way we will remember it's safe to ignore it.

Copy link
Contributor

Choose a reason for hiding this comment

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

It seems you could just suppress the warning using coverity annotation: https://doclazy.wordpress.com/2011/07/14/coverity-suppressing-false-positives-with-cod/

Static code analysis shown that there are several places that
str.. methods are used, what may lead to the bad memory access.
Replaced all of them with corresponding strn... methods.
Copy link

github-actions bot commented Feb 21, 2025

PR #37690: Size comparison from 48adf65 to 42953c2

Full report (84 builds for bl602, bl702, bl702l, cc13x4_26x4, cc32xx, cyw30739, efr32, esp32, linux, nrfconnect, nxp, psoc6, qpg, stm32, telink, tizen)
platform target config section 48adf65 42953c2 change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1095140 1095144 4 0.0
RAM 94802 94802 0 0.0
bl702 lighting-app bl702+eth FLASH 651586 651590 4 0.0
RAM 33509 33509 0 0.0
bl702+wifi FLASH 827750 827754 4 0.0
RAM 22233 22233 0 0.0
bl706+mfd+rpc+littlefs FLASH 1060912 1060920 8 0.0
RAM 32157 32157 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 892098 892106 8 0.0
RAM 26896 26896 0 0.0
lighting-app bl702l+mfd+littlefs FLASH 974994 975002 8 0.0
RAM 24644 24644 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 815268 815284 16 0.0
RAM 120256 120256 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 824180 824196 16 0.0
RAM 125352 125352 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 771048 771064 16 0.0
RAM 113724 113724 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 755324 755340 16 0.0
RAM 113932 113932 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 538810 538814 4 0.0
RAM 205112 205112 0 0.0
lock CC3235SF_LAUNCHXL FLASH 572966 572970 4 0.0
RAM 205360 205360 0 0.0
cyw30739 light CYW30739B2-P5-EVK-01 unknown 2040 2040 0 0.0
FLASH 656397 656413 16 0.0
RAM 75324 75324 0 0.0
CYW30739B2-P5-EVK-02 unknown 2040 2040 0 0.0
FLASH 676257 676273 16 0.0
RAM 77964 77964 0 0.0
CYW30739B2-P5-EVK-03 unknown 2040 2040 0 0.0
FLASH 676257 676273 16 0.0
RAM 77964 77964 0 0.0
CYW930739M2EVB-02 unknown 2040 2040 0 0.0
FLASH 633181 633197 16 0.0
RAM 70392 70392 0 0.0
light-switch CYW30739B2-P5-EVK-01 unknown 2040 2040 0 0.0
FLASH 616261 616277 16 0.0
RAM 71532 71532 0 0.0
CYW30739B2-P5-EVK-02 unknown 2040 2040 0 0.0
FLASH 635897 635913 16 0.0
RAM 74076 74076 0 0.0
CYW30739B2-P5-EVK-03 unknown 2040 2040 0 0.0
FLASH 635897 635913 16 0.0
RAM 74076 74076 0 0.0
lock CYW30739B2-P5-EVK-01 unknown 2040 2040 0 0.0
FLASH 635757 635773 16 0.0
RAM 74540 74540 0 0.0
CYW30739B2-P5-EVK-02 unknown 2040 2040 0 0.0
FLASH 655473 655489 16 0.0
RAM 77084 77084 0 0.0
CYW30739B2-P5-EVK-03 unknown 2040 2040 0 0.0
FLASH 655473 655489 16 0.0
RAM 77084 77084 0 0.0
thermostat CYW30739B2-P5-EVK-01 unknown 2040 2040 0 0.0
FLASH 612105 612121 16 0.0
RAM 68628 68628 0 0.0
CYW30739B2-P5-EVK-02 unknown 2040 2040 0 0.0
FLASH 631965 631981 16 0.0
RAM 71268 71268 0 0.0
CYW30739B2-P5-EVK-03 unknown 2040 2040 0 0.0
FLASH 631965 631981 16 0.0
RAM 71268 71268 0 0.0
efr32 lock-app BRD4187C FLASH 937712 937712 0 0.0
RAM 159916 159916 0 0.0
BRD4338a FLASH 731776 731776 0 0.0
RAM 234772 234772 0 0.0
window-app BRD4187C FLASH 1030368 1030400 32 0.0
RAM 128020 128020 0 0.0
esp32 all-clusters-app c3devkit DRAM 97312 97312 0 0.0
FLASH 1581932 1581936 4 0.0
IRAM 83820 83820 0 0.0
m5stack DRAM 116100 116100 0 0.0
FLASH 1549958 1549962 4 0.0
IRAM 117039 117039 0 0.0
linux air-purifier-app debug unknown 4720 4720 0 0.0
FLASH 2649711 2649735 24 0.0
RAM 111088 111088 0 0.0
all-clusters-app debug unknown 5528 5528 0 0.0
FLASH 5921216 5921240 24 0.0
RAM 513712 513712 0 0.0
all-clusters-minimal-app debug unknown 5424 5424 0 0.0
FLASH 5266218 5266242 24 0.0
RAM 221112 221112 0 0.0
bridge-app debug unknown 5440 5440 0 0.0
FLASH 4624892 4624916 24 0.0
RAM 199816 199816 0 0.0
camera-app debug unknown 5424 5424 0 0.0
FLASH 4671672 4671696 24 0.0
RAM 194592 194592 0 0.0
chip-tool debug unknown 6096 6096 0 0.0
FLASH 13300565 13300621 56 0.0
RAM 603392 603392 0 0.0
chip-tool-ipv6only arm64 unknown 21976 21976 0 0.0
FLASH 11322144 11322176 32 0.0
RAM 655184 655184 0 0.0
fabric-admin debug unknown 5784 5784 0 0.0
FLASH 11565129 11565155 26 0.0
RAM 603176 603176 0 0.0
fabric-bridge-app debug unknown 4688 4688 0 0.0
FLASH 4450216 4450240 24 0.0
RAM 187016 187016 0 0.0
fabric-sync debug unknown 4944 4944 0 0.0
FLASH 5569029 5569061 32 0.0
RAM 470400 470400 0 0.0
lighting-app debug+rpc+ui unknown 6152 6152 0 0.0
FLASH 5514305 5514337 32 0.0
RAM 203952 203952 0 0.0
lock-app debug unknown 5392 5392 0 0.0
FLASH 4688328 4688352 24 0.0
RAM 191144 191144 0 0.0
ota-provider-app debug unknown 4728 4728 0 0.0
FLASH 4310508 4310532 24 0.0
RAM 179832 179832 0 0.0
ota-requestor-app debug unknown 4680 4680 0 0.0
FLASH 4440666 4440690 24 0.0
RAM 184320 184320 0 0.0
shell debug unknown 4216 4216 0 0.0
FLASH 2949020 2949052 32 0.0
RAM 143672 143672 0 0.0
thermostat-no-ble arm64 unknown 9448 9448 0 0.0
FLASH 4042232 4042248 16 0.0
RAM 228096 228096 0 0.0
tv-app debug unknown 5720 5720 0 0.0
FLASH 5907941 5907973 32 0.0
RAM 593832 593832 0 0.0
tv-casting-app debug unknown 5296 5296 0 0.0
FLASH 11471373 11471453 80 0.0
RAM 718656 718656 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 907364 907392 28 0.0
RAM 142315 142315 0 0.0
nrf7002dk_nrf5340_cpuapp FLASH 901732 901752 20 0.0
RAM 124663 124663 0 0.0
all-clusters-minimal-app nrf52840dk_nrf52840 FLASH 845968 845996 28 0.0
RAM 141243 141243 0 0.0
light-switch-app nrf52840dk_nrf52840 FLASH 788112 788140 28 0.0
RAM 131402 131402 0 0.0
nrf7002dk_nrf5340_cpuapp FLASH 953640 953652 12 0.0
RAM 114112 114112 0 0.0
lighting-app nrf52840dk_nrf52840+rpc FLASH 845472 845496 24 0.0
RAM 142596 142596 0 0.0
nrf52840dongle_nrf52840 FLASH 784664 784692 28 0.0
RAM 150415 150415 0 0.0
nrf5340dk_nrf5340_cpuapp FLASH 743408 743436 28 0.0
RAM 141891 141891 0 0.0
nrf7002dk_nrf5340_cpuapp FLASH 953640 953652 12 0.0
RAM 114112 114112 0 0.0
lock-app nrf52840dk_nrf52840 FLASH 776476 776500 24 0.0
RAM 131955 131955 0 0.0
nrf5340dk_nrf5340_cpuapp FLASH 704052 704080 28 0.0
RAM 132398 132398 0 0.0
nrf7002dk_nrf5340_cpuapp FLASH 942984 942996 12 0.0
RAM 114665 114665 0 0.0
pump-app nrf52840dk_nrf52840 FLASH 756084 756108 24 0.0
RAM 130636 130636 0 0.0
pump-controller-app nrf52840dk_nrf52840 FLASH 741716 741744 28 0.0
RAM 130395 130395 0 0.0
nxp contact k32w0+release FLASH 585184 585200 16 0.0
RAM 70876 70876 0 0.0
mcxw71+release FLASH 600640 600656 16 0.0
RAM 63096 63096 0 0.0
light k32w0+release FLASH 611156 611172 16 0.0
RAM 70164 70164 0 0.0
k32w1+release FLASH 685640 685656 16 0.0
RAM 48584 48584 0 0.0
lock mcxw71+release FLASH 749480 749496 16 0.0
RAM 67500 67500 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1646172 1646172 0 0.0
RAM 211472 211472 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1552940 1552940 0 0.0
RAM 208288 208288 0 0.0
light cy8ckit_062s2_43012 FLASH 1438612 1438612 0 0.0
RAM 197040 197040 0 0.0
lock cy8ckit_062s2_43012 FLASH 1467500 1467500 0 0.0
RAM 224704 224704 0 0.0
qpg lighting-app qpg6105+debug FLASH 662156 662156 0 0.0
RAM 105116 105116 0 0.0
lock-app qpg6105+debug FLASH 620264 620272 8 0.0
RAM 99664 99664 0 0.0
stm32 light STM32WB5MM-DK FLASH 459800 459800 0 0.0
RAM 141472 141472 0 0.0
telink bridge-app tl7218x FLASH 665004 665052 48 0.0
RAM 90728 90728 0 0.0
contact-sensor-app tlsr9528a_retention FLASH 622048 622096 48 0.0
RAM 31488 31488 0 0.0
light-app-ota-shell-factory-data tl3218x FLASH 745188 745216 28 0.0
RAM 40396 40396 0 0.0
tl7218x FLASH 753750 753798 48 0.0
RAM 97540 97540 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 680820 680868 48 0.0
RAM 52192 52192 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 709382 709430 48 0.0
RAM 73400 73400 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 600562 600586 24 0.0
RAM 138812 138812 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 788704 788752 48 0.0
RAM 96388 96388 0 0.0
tizen all-clusters-app arm unknown 5076 5076 0 0.0
FLASH 1750772 1750808 36 0.0
RAM 93260 93260 0 0.0
chip-tool-ubsan arm unknown 11492 11492 0 0.0
FLASH 18981598 18981670 72 0.0
RAM 8305976 8306016 40 0.0

@@ -695,7 +695,7 @@ CHIP_ERROR Server::SendUserDirectedCommissioningRequest(Transport::PeerAddress c
CHIP_ERROR err;

// only populate fields left blank by the client
if (strlen(id.GetInstanceName()) == 0)
if (strnlen(id.GetInstanceName(), Dnssd::Commission::kInstanceNameMaxLength + 1) == 0)
Copy link
Contributor

Choose a reason for hiding this comment

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

We don't care about the actual length, right? We just care whether *id.GetInstanceName() == '\0'? Does it make sense to change to that test?

@@ -738,7 +738,7 @@ CHIP_ERROR Server::SendUserDirectedCommissioningRequest(Transport::PeerAddress c
}
}

if (strlen(id.GetDeviceName()) == 0)
if (strnlen(id.GetDeviceName(), Dnssd::kKeyDeviceNameMaxLength + 1) == 0)
Copy link
Contributor

Choose a reason for hiding this comment

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

Again, this does not care about actual length....

@@ -84,7 +84,7 @@ CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) con
}
CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface)
{
if (strlen(intfName) < 3)
if (strnlen(intfName, kMaxIfNameLength) < 3)
Copy link
Contributor

Choose a reason for hiding this comment

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

This change ... does not seem to make anything safer. If there is no null-terminator before kMaxIfNameLength then nothing would change about this test and then the strtoul below will happily walk off the end of the data just like strlen would have. If there is a null-terminator before kMaxIfNameLength, then strlen would not be a problem either.

@@ -210,7 +210,7 @@ CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) con

CHIP_ERROR InterfaceId::InterfaceNameToId(const char * intfName, InterfaceId & interface)
{
if (strlen(intfName) < 3)
if (strnlen(intfName, InterfaceId::kMaxIfNameLength) < 3)
Copy link
Contributor

Choose a reason for hiding this comment

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

Again, this does not seem to actually improve safety, given the strtoul below.

@@ -445,7 +445,7 @@ CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) con
{
return CHIP_ERROR_POSIX(errno);
}
size_t nameLength = strlen(intfName);
size_t nameLength = strnlen(intfName, IF_NAMESIZE);
Copy link
Contributor

@bzbarsky-apple bzbarsky-apple Feb 21, 2025

Choose a reason for hiding this comment

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

Again, the CopyString will just walk off the end of the data, no? Worse yet, this can break the length check below and turn what would have been an out-of-bounds read into an out-of-bounds write, which is much worse.

I'm stopping here. The basic premise that strnlen is safer than strlen is only true in some cases, and so far it's not true in a bunch of cases in this PR. Making it safer requires being very careful with the data flow.

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.

4 participants