Skip to content

Commit 477e61d

Browse files
bnoordhuisevanlucas
authored andcommitted
src: don't use locale-sensitive strcasecmp()
strcasecmp() is affected by the current locale as configured through e.g. the LC_ALL environment variable and the setlocale() libc function. It can result in unpredictable results across systems so replace it with a function that isn't susceptible to that. PR-URL: #6582 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 1e99643 commit 477e61d

File tree

5 files changed

+48
-17
lines changed

5 files changed

+48
-17
lines changed

src/node.cc

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@
6969
#if defined(_MSC_VER)
7070
#include <direct.h>
7171
#include <io.h>
72-
#define strcasecmp _stricmp
7372
#define getpid GetCurrentProcessId
7473
#define umask _umask
7574
typedef int mode_t;
@@ -1381,27 +1380,27 @@ enum encoding ParseEncoding(const char* encoding,
13811380
break;
13821381
}
13831382

1384-
if (strcasecmp(encoding, "utf8") == 0) {
1383+
if (StringEqualNoCase(encoding, "utf8")) {
13851384
return UTF8;
1386-
} else if (strcasecmp(encoding, "utf-8") == 0) {
1385+
} else if (StringEqualNoCase(encoding, "utf-8")) {
13871386
return UTF8;
1388-
} else if (strcasecmp(encoding, "ascii") == 0) {
1387+
} else if (StringEqualNoCase(encoding, "ascii")) {
13891388
return ASCII;
1390-
} else if (strcasecmp(encoding, "base64") == 0) {
1389+
} else if (StringEqualNoCase(encoding, "base64")) {
13911390
return BASE64;
1392-
} else if (strcasecmp(encoding, "ucs2") == 0) {
1391+
} else if (StringEqualNoCase(encoding, "ucs2")) {
13931392
return UCS2;
1394-
} else if (strcasecmp(encoding, "ucs-2") == 0) {
1393+
} else if (StringEqualNoCase(encoding, "ucs-2")) {
13951394
return UCS2;
1396-
} else if (strcasecmp(encoding, "utf16le") == 0) {
1395+
} else if (StringEqualNoCase(encoding, "utf16le")) {
13971396
return UCS2;
1398-
} else if (strcasecmp(encoding, "utf-16le") == 0) {
1397+
} else if (StringEqualNoCase(encoding, "utf-16le")) {
13991398
return UCS2;
1400-
} else if (strcasecmp(encoding, "binary") == 0) {
1399+
} else if (StringEqualNoCase(encoding, "binary")) {
14011400
return BINARY;
1402-
} else if (strcasecmp(encoding, "buffer") == 0) {
1401+
} else if (StringEqualNoCase(encoding, "buffer")) {
14031402
return BUFFER;
1404-
} else if (strcasecmp(encoding, "hex") == 0) {
1403+
} else if (StringEqualNoCase(encoding, "hex")) {
14051404
return HEX;
14061405
} else {
14071406
return default_encoding;

src/node_crypto.cc

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@
2424
#include <stdlib.h>
2525
#include <string.h>
2626

27-
#if defined(_MSC_VER)
28-
#define strcasecmp _stricmp
29-
#endif
30-
3127
#define THROW_AND_RETURN_IF_NOT_STRING_OR_BUFFER(val, prefix) \
3228
do { \
3329
if (!Buffer::HasInstance(val) && !val->IsString()) { \
@@ -4446,7 +4442,7 @@ void DiffieHellman::DiffieHellmanGroup(
44464442
for (size_t i = 0; i < arraysize(modp_groups); ++i) {
44474443
const modp_group* it = modp_groups + i;
44484444

4449-
if (strcasecmp(*group_name, it->name) != 0)
4445+
if (!StringEqualNoCase(*group_name, it->name))
44504446
continue;
44514447

44524448
initialized = diffieHellman->Init(it->prime,

src/util-inl.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,19 @@ void SwapBytes(uint16_t* dst, const uint16_t* src, size_t buflen) {
203203
dst[i] = (src[i] << 8) | (src[i] >> 8);
204204
}
205205

206+
char ToLower(char c) {
207+
return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c;
208+
}
206209

210+
bool StringEqualNoCase(const char* a, const char* b) {
211+
do {
212+
if (*a == '\0')
213+
return *b == '\0';
214+
if (*b == '\0')
215+
return *a == '\0';
216+
} while (ToLower(*a++) == ToLower(*b++));
217+
return false;
218+
}
207219

208220
} // namespace node
209221

src/util.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ inline TypeName* Unwrap(v8::Local<v8::Object> object);
178178

179179
inline void SwapBytes(uint16_t* dst, const uint16_t* src, size_t buflen);
180180

181+
// tolower() is locale-sensitive. Use ToLower() instead.
182+
inline char ToLower(char c);
183+
184+
// strcasecmp() is locale-sensitive. Use StringEqualNoCase() instead.
185+
inline bool StringEqualNoCase(const char* a, const char* b);
186+
181187
// Allocates an array of member type T. For up to kStackStorageSize items,
182188
// the stack is used, otherwise malloc().
183189
template <typename T, size_t kStackStorageSize = 1024>

test/cctest/util.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,21 @@ TEST(UtilTest, ListHead) {
5656
EXPECT_TRUE(list.IsEmpty());
5757
EXPECT_FALSE(list.begin() != list.end());
5858
}
59+
60+
TEST(UtilTest, StringEqualNoCase) {
61+
using node::StringEqualNoCase;
62+
EXPECT_FALSE(StringEqualNoCase("a", "b"));
63+
EXPECT_TRUE(StringEqualNoCase("", ""));
64+
EXPECT_TRUE(StringEqualNoCase("equal", "equal"));
65+
EXPECT_TRUE(StringEqualNoCase("equal", "EQUAL"));
66+
EXPECT_TRUE(StringEqualNoCase("EQUAL", "EQUAL"));
67+
EXPECT_FALSE(StringEqualNoCase("equal", "equals"));
68+
EXPECT_FALSE(StringEqualNoCase("equals", "equal"));
69+
}
70+
71+
TEST(UtilTest, ToLower) {
72+
using node::ToLower;
73+
EXPECT_EQ('0', ToLower('0'));
74+
EXPECT_EQ('a', ToLower('a'));
75+
EXPECT_EQ('a', ToLower('A'));
76+
}

0 commit comments

Comments
 (0)