Skip to content

Commit 2b0dce5

Browse files
bnoordhuisMyles Borins
authored and
Myles Borins
committed
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 9c31c73 commit 2b0dce5

File tree

5 files changed

+50
-19
lines changed

5 files changed

+50
-19
lines changed

src/node.cc

+13-14
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;
@@ -1350,35 +1349,35 @@ enum encoding ParseEncoding(const char* encoding,
13501349
break;
13511350
}
13521351

1353-
if (strcasecmp(encoding, "utf8") == 0) {
1352+
if (StringEqualNoCase(encoding, "utf8")) {
13541353
return UTF8;
1355-
} else if (strcasecmp(encoding, "utf-8") == 0) {
1354+
} else if (StringEqualNoCase(encoding, "utf-8")) {
13561355
return UTF8;
1357-
} else if (strcasecmp(encoding, "ascii") == 0) {
1356+
} else if (StringEqualNoCase(encoding, "ascii")) {
13581357
return ASCII;
1359-
} else if (strcasecmp(encoding, "base64") == 0) {
1358+
} else if (StringEqualNoCase(encoding, "base64")) {
13601359
return BASE64;
1361-
} else if (strcasecmp(encoding, "ucs2") == 0) {
1360+
} else if (StringEqualNoCase(encoding, "ucs2")) {
13621361
return UCS2;
1363-
} else if (strcasecmp(encoding, "ucs-2") == 0) {
1362+
} else if (StringEqualNoCase(encoding, "ucs-2")) {
13641363
return UCS2;
1365-
} else if (strcasecmp(encoding, "utf16le") == 0) {
1364+
} else if (StringEqualNoCase(encoding, "utf16le")) {
13661365
return UCS2;
1367-
} else if (strcasecmp(encoding, "utf-16le") == 0) {
1366+
} else if (StringEqualNoCase(encoding, "utf-16le")) {
13681367
return UCS2;
1369-
} else if (strcasecmp(encoding, "binary") == 0) {
1368+
} else if (StringEqualNoCase(encoding, "binary")) {
13701369
return BINARY;
1371-
} else if (strcasecmp(encoding, "buffer") == 0) {
1370+
} else if (StringEqualNoCase(encoding, "buffer")) {
13721371
return BUFFER;
1373-
} else if (strcasecmp(encoding, "hex") == 0) {
1372+
} else if (StringEqualNoCase(encoding, "hex")) {
13741373
return HEX;
1375-
} else if (strcasecmp(encoding, "raw") == 0) {
1374+
} else if (StringEqualNoCase(encoding, "raw") == 0) {
13761375
if (!no_deprecation) {
13771376
fprintf(stderr, "'raw' (array of integers) has been removed. "
13781377
"Use 'binary'.\n");
13791378
}
13801379
return BINARY;
1381-
} else if (strcasecmp(encoding, "raws") == 0) {
1380+
} else if (StringEqualNoCase(encoding, "raws") == 0) {
13821381
if (!no_deprecation) {
13831382
fprintf(stderr, "'raws' encoding has been renamed to 'binary'. "
13841383
"Please update your code.\n");

src/node_crypto.cc

+1-5
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
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
3228
#define OPENSSL_CONST const
3329
#else
@@ -4232,7 +4228,7 @@ void DiffieHellman::DiffieHellmanGroup(
42324228
for (size_t i = 0; i < arraysize(modp_groups); ++i) {
42334229
const modp_group* it = modp_groups + i;
42344230

4235-
if (strcasecmp(*group_name, it->name) != 0)
4231+
if (!StringEqualNoCase(*group_name, it->name))
42364232
continue;
42374233

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

src/util-inl.h

+12
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

+6
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
class Utf8Value {
182188
public:
183189
explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);

test/cctest/util.cc

+18
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)