Adjust the implementation of strncpy_s() for Linux

This change:
- prevents writing memory out of the range of the destination buffer
- prevents calling strlen() with non-null terminated c-string
- corrects the logic, which validates passed range to proceed
when real length fits the destination buffer

Related-To: NEO-7264
Signed-off-by: Wrobel, Patryk <patryk.wrobel@intel.com>
This commit is contained in:
Wrobel, Patryk
2022-08-17 15:46:39 +00:00
committed by Compute-Runtime-Automation
parent 5bdf758049
commit dda5b19859
8 changed files with 88 additions and 71 deletions

View File

@@ -140,7 +140,7 @@ ze_result_t DriverHandleImp::getExtensionProperties(uint32_t *pCount,
for (uint32_t i = 0; i < *pCount; i++) {
auto extension = this->extensionsSupported[i];
strncpy_s(pExtensionProperties[i].name, ZE_MAX_EXTENSION_NAME,
extension.first.c_str(), extension.first.length() + 1);
extension.first.c_str(), extension.first.length());
pExtensionProperties[i].version = extension.second;
}

View File

@@ -474,9 +474,9 @@ ze_result_t KernelImp::getSourceAttributes(uint32_t *pSize, char **pString) {
if (pString == nullptr) {
*pSize = (uint32_t)desc.kernelMetadata.kernelLanguageAttributes.length() + 1;
} else {
strncpy_s(*pString, desc.kernelMetadata.kernelLanguageAttributes.length() + 1,
strncpy_s(*pString, *pSize,
desc.kernelMetadata.kernelLanguageAttributes.c_str(),
desc.kernelMetadata.kernelLanguageAttributes.length() + 1);
desc.kernelMetadata.kernelLanguageAttributes.length());
}
return ZE_RESULT_SUCCESS;
}
@@ -721,7 +721,8 @@ ze_result_t KernelImp::getKernelName(size_t *pSize, char *pName) {
*pSize = std::min(*pSize, kernelNameSize);
strncpy_s(pName, *pSize,
this->kernelImmData->getDescriptor().kernelMetadata.kernelName.c_str(), kernelNameSize);
this->kernelImmData->getDescriptor().kernelMetadata.kernelName.c_str(),
this->kernelImmData->getDescriptor().kernelMetadata.kernelName.size());
return ZE_RESULT_SUCCESS;
}

View File

@@ -51,7 +51,7 @@ bool LinuxFirmwareImp::isFirmwareSupported(void) {
void LinuxFirmwareImp::osGetFwProperties(zes_firmware_properties_t *pProperties) {
if (ZE_RESULT_SUCCESS != getFirmwareVersion(osFwType, pProperties)) {
strncpy_s(static_cast<char *>(pProperties->version), ZES_STRING_PROPERTY_SIZE, unknown.c_str(), ZES_STRING_PROPERTY_SIZE);
strncpy_s(static_cast<char *>(pProperties->version), ZES_STRING_PROPERTY_SIZE, unknown.c_str(), ZES_STRING_PROPERTY_SIZE - 1);
}
pProperties->canControl = true; //Assuming that user has permission to flash the firmware
}

View File

@@ -14,9 +14,9 @@ ze_result_t LinuxFirmwareImp::getFirmwareVersion(std::string fwType, zes_firmwar
std::string fwVersion;
ze_result_t result = pFwInterface->getFwVersion(fwType, fwVersion);
if (ZE_RESULT_SUCCESS == result) {
strncpy_s(static_cast<char *>(pProperties->version), ZES_STRING_PROPERTY_SIZE, fwVersion.c_str(), ZES_STRING_PROPERTY_SIZE);
strncpy_s(static_cast<char *>(pProperties->version), ZES_STRING_PROPERTY_SIZE, fwVersion.c_str(), ZES_STRING_PROPERTY_SIZE - 1);
}
return result;
}
} // namespace L0
} // namespace L0

View File

@@ -43,15 +43,15 @@ ze_result_t LinuxFirmwareImp::getFirmwareVersion(std::string fwType, zes_firmwar
// not able to read PSC version from iaf.x
return result;
}
strncpy_s(static_cast<char *>(pProperties->version), ZES_STRING_PROPERTY_SIZE, pscVersion.c_str(), ZES_STRING_PROPERTY_SIZE);
strncpy_s(static_cast<char *>(pProperties->version), ZES_STRING_PROPERTY_SIZE, pscVersion.c_str(), ZES_STRING_PROPERTY_SIZE - 1);
return result;
}
ze_result_t result = pFwInterface->getFwVersion(fwType, fwVersion);
if (result == ZE_RESULT_SUCCESS) {
strncpy_s(static_cast<char *>(pProperties->version), ZES_STRING_PROPERTY_SIZE, fwVersion.c_str(), ZES_STRING_PROPERTY_SIZE);
strncpy_s(static_cast<char *>(pProperties->version), ZES_STRING_PROPERTY_SIZE, fwVersion.c_str(), ZES_STRING_PROPERTY_SIZE - 1);
}
return result;
}
} // namespace L0
} // namespace L0

View File

@@ -169,7 +169,7 @@ TEST_P(PrintfInt8Test, GivenFormatContainingIntWhenPrintingThenValueIsInserted)
char referenceOutput[maxPrintfOutputLength];
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
snprintf(referenceOutput, sizeof(referenceOutput), input.format.c_str(), input.value);
@@ -209,7 +209,7 @@ TEST_P(PrintfInt32Test, GivenFormatContainingIntWhenPrintingThenValueIsInserted)
char referenceOutput[maxPrintfOutputLength];
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
snprintf(referenceOutput, sizeof(referenceOutput), input.format.c_str(), input.value);
@@ -250,7 +250,7 @@ TEST_P(PrintfUint32Test, GivenFormatContainingUintWhenPrintingThenValueIsInserte
char referenceOutput[maxPrintfOutputLength];
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
snprintf(referenceOutput, sizeof(referenceOutput), input.format.c_str(), input.value);
@@ -267,7 +267,7 @@ TEST_P(PrintfUint32Test, GivenBufferSizeGreaterThanPrintBufferWhenPrintingThenBu
char referenceOutput[maxPrintfOutputLength] = "";
char actualOutput[maxPrintfOutputLength] = "";
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ(referenceOutput, actualOutput);
}
@@ -302,7 +302,7 @@ TEST_P(PrintfFloatTest, GivenFormatContainingFloatWhenPrintingThenValueIsInserte
char referenceOutput[maxPrintfOutputLength];
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
snprintf(referenceOutput, sizeof(referenceOutput), input.format.c_str(), input.value);
@@ -345,7 +345,7 @@ TEST_P(PrintfDoubleToFloatTest, GivenFormatContainingFloatAndDoubleWhenPrintingT
char referenceOutput[maxPrintfOutputLength];
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
snprintf(referenceOutput, sizeof(referenceOutput), input.format.c_str(), input.value);
@@ -390,7 +390,7 @@ TEST_P(PrintfDoubleTest, GivenFormatContainingDoubleWhenPrintingThenValueIsInser
char referenceOutput[maxPrintfOutputLength];
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
if (input.format[input.format.length() - 1] == 'F')
input.format[input.format.length() - 1] = 'f';
@@ -420,7 +420,7 @@ TEST_P(PrintfSpecialTest, GivenFormatContainingDoublePercentageWhenPrintingThenV
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ(input.second.c_str(), actualOutput);
}
@@ -450,7 +450,7 @@ TEST_P(PrintfNoArgumentsTest, GivenNoArgumentsWhenPrintingThenCharsAreEscaped) {
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ(input.second.c_str(), actualOutput);
}
@@ -478,7 +478,7 @@ TEST_P(PrintfStringTest, GivenFormatContainingStringWhenPrintingThenValueIsInser
char referenceOutput[maxPrintfOutputLength];
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
snprintf(referenceOutput, sizeof(referenceOutput), input.format.c_str(), input.value.c_str());
@@ -499,7 +499,7 @@ TEST_F(PrintFormatterTest, GivenLongStringValueWhenPrintedThenFullStringIsPrinte
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ(testedLongString, actualOutput);
}
@@ -517,7 +517,7 @@ TEST_F(PrintFormatterTest, GivenStringSpecifierWhenLongStringIsPassedAsValueThen
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ(testedLongString, actualOutput);
}
@@ -533,7 +533,7 @@ TEST_F(PrintFormatterTest, GivenTooLongStringWhenPrintedThenOutputIsTruncated) {
std::unique_ptr<char[]> actualOutput(new char[PrintFormatter::maxSinglePrintStringLength + 1024]);
printFormatter->printKernelOutput([&actualOutput](char *str) {
size_t length = strnlen_s(str, PrintFormatter::maxSinglePrintStringLength + 1024);
size_t length = strnlen_s(str, PrintFormatter::maxSinglePrintStringLength + 1023);
strncpy_s(actualOutput.get(), PrintFormatter::maxSinglePrintStringLength + 1024, str, length); });
auto testedLength = strnlen_s(testedLongString.get(), PrintFormatter::maxSinglePrintStringLength + 1024);
@@ -550,7 +550,7 @@ TEST_F(PrintFormatterTest, GivenNullTokenWhenPrintingThenNullIsInserted) {
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ("(null)", actualOutput);
}
@@ -572,7 +572,7 @@ TEST_F(PrintFormatterTest, GivenVector2WhenPrintingThenAllValuesAreInserted) {
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ("1,2", actualOutput);
}
@@ -593,7 +593,7 @@ TEST_F(PrintFormatterTest, GivenVector4WhenPrintingThenAllValuesAreInserted) {
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ("1,2,3,4", actualOutput);
}
@@ -614,7 +614,7 @@ TEST_F(PrintFormatterTest, GivenVector8WhenPrintingThenAllValuesAreInserted) {
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ("1,2,3,4,5,6,7,8", actualOutput);
}
@@ -635,7 +635,7 @@ TEST_F(PrintFormatterTest, GivenVector16WhenPrintingThenAllValuesAreInserted) {
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16", actualOutput);
}
@@ -656,7 +656,7 @@ TEST_F(PrintFormatterTest, GivenVectorOfBytesWhenPrintingThenAllValuesAreInserte
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ("1,2", actualOutput);
}
@@ -676,7 +676,7 @@ TEST_F(PrintFormatterTest, GivenVectorOfShortsWhenPrintingThenAllValuesAreInsert
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ("1,2", actualOutput);
}
@@ -696,7 +696,7 @@ TEST_F(PrintFormatterTest, GivenVectorOfIntsWhenPrintingThenAllValuesAreInserted
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ("1,2", actualOutput);
}
@@ -716,7 +716,7 @@ TEST_F(PrintFormatterTest, GivenSpecialVectorWhenPrintingThenAllValuesAreInserte
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ("1,2", actualOutput);
}
@@ -735,7 +735,7 @@ TEST_F(PrintFormatterTest, GivenVectorOfLongsWhenPrintingThenAllValuesAreInserte
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ("1,2", actualOutput);
}
@@ -755,7 +755,7 @@ TEST_F(PrintFormatterTest, GivenVectorOfFloatsWhenPrintingThenAllValuesAreInsert
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ("1.000000,2.000000", actualOutput);
}
@@ -775,7 +775,7 @@ TEST_F(PrintFormatterTest, GivenVectorOfDoublesWhenPrintingThenAllValuesAreInser
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ("1.000000,2.000000", actualOutput);
}
@@ -801,7 +801,7 @@ TEST_F(PrintFormatterTest, GivenPointerWhenPrintingThenValueIsInserted) {
snprintf(referenceOutput, sizeof(referenceOutput), "%p", reinterpret_cast<void *>(&temp));
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ(referenceOutput, actualOutput);
}
@@ -829,7 +829,7 @@ TEST_F(PrintFormatterTest, GivenPointerWith32BitKernelWhenPrintingThen32BitPoint
snprintf(referenceOutput, sizeof(referenceOutput), "%p", pointer);
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ(referenceOutput, actualOutput);
}
@@ -866,7 +866,7 @@ TEST_F(PrintFormatterTest, Given2ByteVectorsWhenPrintingThenDataBufferParsedProp
char actualOutput[maxPrintfOutputLength];
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ("1,2,3,4 1,2,3,4", actualOutput);
}
@@ -874,7 +874,7 @@ TEST_F(PrintFormatterTest, Given2ByteVectorsWhenPrintingThenDataBufferParsedProp
TEST_F(PrintFormatterTest, GivenEmptyBufferWhenPrintingThenFailSafely) {
char actualOutput[maxPrintfOutputLength];
actualOutput[0] = 0;
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&actualOutput](char *str) { strncpy_s(actualOutput, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ("", actualOutput);
}
@@ -884,7 +884,7 @@ TEST_F(PrintFormatterTest, GivenNoStringMapAndBufferWithFormatStringThenItIsPrin
storeData(formatString);
char output[maxPrintfOutputLength];
printFormatter->printKernelOutput([&output](char *str) { strncpy_s(output, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&output](char *str) { strncpy_s(output, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ(formatString, output);
}
@@ -902,7 +902,7 @@ TEST_F(PrintFormatterTest, GivenNoStringMapAndBufferWithFormatStringAnd2StringsT
const char *expectedOutput = "str1 str2";
char output[maxPrintfOutputLength];
printFormatter->printKernelOutput([&output](char *str) { strncpy_s(output, maxPrintfOutputLength, str, maxPrintfOutputLength); });
printFormatter->printKernelOutput([&output](char *str) { strncpy_s(output, maxPrintfOutputLength, str, maxPrintfOutputLength - 1); });
EXPECT_STREQ(expectedOutput, output);
}

View File

@@ -31,28 +31,6 @@ inline int strcpy_s(char *dst, size_t dstSize, const char *src) { // NOLINT(read
return 0;
}
inline int strncpy_s(char *dst, size_t numberOfElements, const char *src, size_t count) { // NOLINT(readability-identifier-naming)
if ((dst == nullptr) || (src == nullptr)) {
return -EINVAL;
}
if (numberOfElements < count) {
return -ERANGE;
}
size_t length = strlen(src);
if (length > count) {
length = count;
}
memcpy(dst, src, length);
if (length < numberOfElements) {
numberOfElements = length;
}
dst[numberOfElements] = '\0';
return 0;
}
inline size_t strnlen_s(const char *str, size_t count) { // NOLINT(readability-identifier-naming)
if (str == nullptr) {
return 0;
@@ -66,6 +44,22 @@ inline size_t strnlen_s(const char *str, size_t count) { // NOLINT(readability-i
return count;
}
inline int strncpy_s(char *dst, size_t numberOfElements, const char *src, size_t count) { // NOLINT(readability-identifier-naming)
if ((dst == nullptr) || (src == nullptr)) {
return -EINVAL;
}
size_t length = strnlen_s(src, count);
if (numberOfElements <= count && numberOfElements <= length) {
return -ERANGE;
}
memcpy(dst, src, length);
dst[length] = '\0';
return 0;
}
inline int memcpy_s(void *dst, size_t destSize, const void *src, size_t count) { // NOLINT(readability-identifier-naming)
if ((dst == nullptr) || (src == nullptr)) {
return -EINVAL;

View File

@@ -27,7 +27,7 @@ TEST(StringHelpers, GivenParamsWhenUsingStrncpyThenReturnIsCorrect) {
ret = strncpy_s(dst, 1024, nullptr, 1024);
EXPECT_EQ(ret, -EINVAL);
ret = strncpy_s(dst, 512, src, 1024);
ret = strncpy_s(dst, 10, src, 1024);
EXPECT_EQ(ret, -ERANGE);
memset(dst, 0, sizeof(dst));
@@ -37,19 +37,41 @@ TEST(StringHelpers, GivenParamsWhenUsingStrncpyThenReturnIsCorrect) {
for (size_t i = strlen(src) / 2; i < sizeof(dst); i++)
EXPECT_EQ(0, dst[i]);
memset(dst, 0, sizeof(dst));
ret = strncpy_s(dst, strlen(src) / 2, src, strlen(src) / 2);
EXPECT_EQ(ret, 0);
EXPECT_EQ(0, memcmp(dst, src, strlen(src) / 2));
for (size_t i = strlen(src) / 2; i < sizeof(dst); i++)
EXPECT_EQ(0, dst[i]);
ret = strncpy_s(dst, 1024, src, 1024);
ASSERT_EQ(0, ret);
strncpy_s(dst, 1024, src, 1024);
EXPECT_EQ(0, memcmp(dst, src, strlen(src)));
for (size_t i = strlen(src); i < sizeof(dst); i++)
EXPECT_EQ(0, dst[i]);
}
TEST(StringHelpers, GivenCountGreaterEqualToNumberOfElementsThenReturnErangeAndSetFirstStringToNullTerminator) {
// strncpy_s() copies at most COUNT bytes and appends null-terminator at dst[COUNT].
// It means, that for given COUNT, at least COUNT+1 bytes are required in dst buffer.
const size_t firstWordLength = 9;
char src[] = "c-strings are serious business!";
char dst[firstWordLength] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'};
const auto ret = strncpy_s(dst, sizeof(dst), src, firstWordLength);
EXPECT_EQ(-ERANGE, ret);
}
TEST(StringHelpers, GivenNotNullTerminatedSourceThenCopyAtMostCountBytesAndAppendNulltermination) {
// If null-terminator is missing, then strncpy_s() copies COUNT bytes and stores it at dst[COUNT].
const size_t srcLength = 8;
char src[srcLength] = {'c', '-', 's', 't', 'r', 'i', 'n', 'g'};
const size_t nullterminatorLength = 1;
char dst[srcLength + nullterminatorLength] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'};
const auto ret = strncpy_s(dst, sizeof(dst), src, srcLength);
ASSERT_EQ(0, ret);
EXPECT_STREQ("c-string", dst);
}
TEST(StringHelpers, GivenParamsWhenUsingMemmoveThenReturnIsCorrect) {
char dst[1024] = "";
char src[1024] = "HelloWorld";