This library contains code that extends and simplifies different operations
for C language based programs.
Revisión | d8bcf99ba262e287b249b97a04d0e570588417c2 (tree) |
---|---|
Tiempo | 2022-10-05 12:15:28 |
Autor | Sergey Gusarov <laborer2008@gmai...> |
Commiter | Sergey Gusarov |
std/string: No more strdup()/strndup(). Secure wrappers instead
@@ -6,7 +6,10 @@ | ||
6 | 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
7 | 7 | * |
8 | 8 | * @section DESCRIPTION |
9 | - * | |
9 | + * All string functions below are prone to undefined behaviour(observed on practice with glibc) | |
10 | + * when at least one argument is NULL. | |
11 | + * See: https://stackoverflow.com/questions/21865041/in-c-what-exactly-happens-when-you-pass-a-null-pointer-to-strcmp | |
12 | + * Each pointer represents string even if it NULL. NULL pointer is kind of empty string, not error | |
10 | 13 | */ |
11 | 14 | |
12 | 15 | #pragma once |
@@ -66,26 +69,8 @@ | ||
66 | 69 | return str ? strlen(str) : 0; |
67 | 70 | } |
68 | 71 | |
69 | -#if defined (CT_OS_WINDOWS) | |
70 | - | |
71 | -extern CT_SHARED_API char* strndup(const char* s, size_t n) CT_NOEXCEPT; | |
72 | - | |
73 | -# if defined (CT_COMPL_BCC) && defined (CT_ARCH_X86) | |
74 | -static CT_FORCEINLINE char* strdup(const char* s) CT_NOEXCEPT | |
75 | -{ | |
76 | - return strndup(s, strLenWrapper(s)); | |
77 | -} | |
78 | -# else | |
79 | -# define strdup(str) _strdup(str) | |
80 | -# endif | |
81 | -#endif | |
82 | - | |
83 | -/* | |
84 | - * Both compare functions below are prone to undefined behaviour(observed on practice with glibc) | |
85 | - * when at least one argument is NULL. | |
86 | - * See: https://stackoverflow.com/questions/21865041/in-c-what-exactly-happens-when-you-pass-a-null-pointer-to-strcmp | |
87 | - * Each pointer represents string even if it NULL. NULL pointer is kind of empty string, not error | |
88 | - */ | |
72 | +extern CT_SHARED_API char* strNDupWrapper(const char* str, size_t n) CT_NOEXCEPT; | |
73 | +extern CT_SHARED_API char* strDupWrapper(const char* str) CT_NOEXCEPT; | |
89 | 74 | |
90 | 75 | static CT_FORCEINLINE int strCmpWrapper(const char* s1, const char* s2) CT_NOEXCEPT |
91 | 76 | { |
@@ -11,6 +11,9 @@ | ||
11 | 11 | |
12 | 12 | #include "ctools/std/string.h" |
13 | 13 | |
14 | +#include "ctools/pointer.h" | |
15 | + | |
16 | + | |
14 | 17 | #if defined (CT_COMPL_SDCC) |
15 | 18 | |
16 | 19 | #include "ctools/pointer.h" |
@@ -40,7 +43,7 @@ | ||
40 | 43 | |
41 | 44 | // See also http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/strndup.c.htm |
42 | 45 | |
43 | -char* strndup(const char* s, size_t n) CT_NOEXCEPT | |
46 | +static char* strndup(const char* s, size_t n) CT_NOEXCEPT | |
44 | 47 | { |
45 | 48 | const size_t kLen = strLenWrapper(s); |
46 | 49 | char* newString = CT_NULL; |
@@ -71,3 +74,29 @@ | ||
71 | 74 | CT_END_NAMESPACE |
72 | 75 | |
73 | 76 | #endif |
77 | + | |
78 | +CT_BEGIN_NAMESPACE | |
79 | + | |
80 | +char* strNDupWrapper(const char* str, size_t n) CT_NOEXCEPT | |
81 | +{ | |
82 | + return str ? strndup(str, n) : CT_NULL; | |
83 | +} | |
84 | + | |
85 | +char* strDupWrapper(const char* str) CT_NOEXCEPT | |
86 | +{ | |
87 | +#if defined (CT_OS_WINDOWS) | |
88 | +# if defined (CT_COMPL_BCC) && defined (CT_ARCH_X86) | |
89 | + | |
90 | + return strNDupWrapper(str, strLenWrapper(str)); | |
91 | + | |
92 | +# else | |
93 | + | |
94 | + return str ? _strdup(str) : CT_NULL; | |
95 | + | |
96 | +# endif | |
97 | +#else | |
98 | + return str ? strdup(str) : CT_NULL; | |
99 | +#endif | |
100 | +} | |
101 | + | |
102 | +CT_END_NAMESPACE |
@@ -18,6 +18,7 @@ | ||
18 | 18 | CT_END_EXTERNAL_HEADERS |
19 | 19 | |
20 | 20 | #include <ctools/std/string.h> |
21 | +#include <ctools/pointer.h> | |
21 | 22 | |
22 | 23 | |
23 | 24 | void setUp(void) |
@@ -32,15 +33,15 @@ | ||
32 | 33 | { |
33 | 34 | const size_t kSize1 = 2; |
34 | 35 | const size_t kSize2 = 4; |
35 | - const char* str1 = CT_NULL; | |
36 | + const char* strEmpty = CT_NULL; | |
36 | 37 | const char* str2 = "abc"; |
37 | 38 | const char* str3 = "1234"; |
38 | 39 | char* str4; |
39 | 40 | |
40 | - TEST_ASSERT_EQUAL(strLenWrapper(str1), 0); | |
41 | + TEST_ASSERT_EQUAL(strLenWrapper(strEmpty), 0); | |
41 | 42 | TEST_ASSERT_EQUAL(strLenWrapper(str2), 3); |
42 | 43 | |
43 | - str4 = strdup(str2); | |
44 | + str4 = strDupWrapper(str2); | |
44 | 45 | TEST_ASSERT_TRUE(strCmpWrapper(str2, str4) == 0); |
45 | 46 | TEST_ASSERT_TRUE(strNCmpWrapper(str2, str4, strLenWrapper(str2)) == 0); |
46 | 47 |
@@ -49,15 +50,15 @@ | ||
49 | 50 | str4 = strerror(EINVAL); |
50 | 51 | TEST_ASSERT_TRUE(strLenWrapper(str4) > 0); |
51 | 52 | |
52 | - str4 = strndup(str2, kSize1); | |
53 | + str4 = strNDupWrapper(str2, kSize1); | |
53 | 54 | TEST_ASSERT_TRUE(strLenWrapper(str4) == kSize1); |
54 | 55 | |
55 | - str4 = strndup(str2, kSize2); | |
56 | + str4 = strNDupWrapper(str2, kSize2); | |
56 | 57 | TEST_ASSERT_TRUE(strLenWrapper(str4) == strLenWrapper(str2)); |
57 | 58 | |
58 | - str4 = strndup(str2, strLenWrapper(str2)); | |
59 | + str4 = strNDupWrapper(str2, strLenWrapper(str2)); | |
59 | 60 | TEST_ASSERT_TRUE(strCmpWrapper(str2, str4) == 0); |
60 | 61 | |
61 | - TEST_ASSERT_TRUE(strCmpWrapper(str1, strdup(str1)) == 0); | |
62 | - TEST_ASSERT_TRUE(strCmpWrapper(str2, strdup(str2)) == 0); | |
62 | + TEST_ASSERT_TRUE(strCmpWrapper(strEmpty, strDupWrapper(strEmpty)) == 0); | |
63 | + TEST_ASSERT_TRUE(strCmpWrapper(str2, strDupWrapper(str2)) == 0); | |
63 | 64 | } |