summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2016-05-04 20:56:04 +0200
committerBen Noordhuis <info@bnoordhuis.nl>2016-05-05 00:28:25 +0200
commitf6940dfa4627301bbd1a24530ac3f4fe3fe8494c (patch)
treee9f6400ff0e4757ab9a9a990c4b7b9c02c08b25b
parent6db772d648d2f2a79a4426e6b06fe1de298cd80c (diff)
downloadnode-new-f6940dfa4627301bbd1a24530ac3f4fe3fe8494c.tar.gz
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: https://github.com/nodejs/node/pull/6582 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
-rw-r--r--src/node.cc23
-rw-r--r--src/node_crypto.cc6
-rw-r--r--src/util-inl.h12
-rw-r--r--src/util.h6
-rw-r--r--test/cctest/util.cc18
5 files changed, 48 insertions, 17 deletions
diff --git a/src/node.cc b/src/node.cc
index eb8805b219..0d85ce77c9 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -69,7 +69,6 @@
#if defined(_MSC_VER)
#include <direct.h>
#include <io.h>
-#define strcasecmp _stricmp
#define getpid GetCurrentProcessId
#define umask _umask
typedef int mode_t;
@@ -1381,27 +1380,27 @@ enum encoding ParseEncoding(const char* encoding,
break;
}
- if (strcasecmp(encoding, "utf8") == 0) {
+ if (StringEqualNoCase(encoding, "utf8")) {
return UTF8;
- } else if (strcasecmp(encoding, "utf-8") == 0) {
+ } else if (StringEqualNoCase(encoding, "utf-8")) {
return UTF8;
- } else if (strcasecmp(encoding, "ascii") == 0) {
+ } else if (StringEqualNoCase(encoding, "ascii")) {
return ASCII;
- } else if (strcasecmp(encoding, "base64") == 0) {
+ } else if (StringEqualNoCase(encoding, "base64")) {
return BASE64;
- } else if (strcasecmp(encoding, "ucs2") == 0) {
+ } else if (StringEqualNoCase(encoding, "ucs2")) {
return UCS2;
- } else if (strcasecmp(encoding, "ucs-2") == 0) {
+ } else if (StringEqualNoCase(encoding, "ucs-2")) {
return UCS2;
- } else if (strcasecmp(encoding, "utf16le") == 0) {
+ } else if (StringEqualNoCase(encoding, "utf16le")) {
return UCS2;
- } else if (strcasecmp(encoding, "utf-16le") == 0) {
+ } else if (StringEqualNoCase(encoding, "utf-16le")) {
return UCS2;
- } else if (strcasecmp(encoding, "binary") == 0) {
+ } else if (StringEqualNoCase(encoding, "binary")) {
return BINARY;
- } else if (strcasecmp(encoding, "buffer") == 0) {
+ } else if (StringEqualNoCase(encoding, "buffer")) {
return BUFFER;
- } else if (strcasecmp(encoding, "hex") == 0) {
+ } else if (StringEqualNoCase(encoding, "hex")) {
return HEX;
} else {
return default_encoding;
diff --git a/src/node_crypto.cc b/src/node_crypto.cc
index d50671aa76..71799d0bfa 100644
--- a/src/node_crypto.cc
+++ b/src/node_crypto.cc
@@ -24,10 +24,6 @@
#include <stdlib.h>
#include <string.h>
-#if defined(_MSC_VER)
-#define strcasecmp _stricmp
-#endif
-
#define THROW_AND_RETURN_IF_NOT_STRING_OR_BUFFER(val, prefix) \
do { \
if (!Buffer::HasInstance(val) && !val->IsString()) { \
@@ -4446,7 +4442,7 @@ void DiffieHellman::DiffieHellmanGroup(
for (size_t i = 0; i < arraysize(modp_groups); ++i) {
const modp_group* it = modp_groups + i;
- if (strcasecmp(*group_name, it->name) != 0)
+ if (!StringEqualNoCase(*group_name, it->name))
continue;
initialized = diffieHellman->Init(it->prime,
diff --git a/src/util-inl.h b/src/util-inl.h
index 7ff6e51937..355dfcdbee 100644
--- a/src/util-inl.h
+++ b/src/util-inl.h
@@ -203,7 +203,19 @@ void SwapBytes(uint16_t* dst, const uint16_t* src, size_t buflen) {
dst[i] = (src[i] << 8) | (src[i] >> 8);
}
+char ToLower(char c) {
+ return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c;
+}
+bool StringEqualNoCase(const char* a, const char* b) {
+ do {
+ if (*a == '\0')
+ return *b == '\0';
+ if (*b == '\0')
+ return *a == '\0';
+ } while (ToLower(*a++) == ToLower(*b++));
+ return false;
+}
} // namespace node
diff --git a/src/util.h b/src/util.h
index 1f9f81cfd3..dce6c343b1 100644
--- a/src/util.h
+++ b/src/util.h
@@ -178,6 +178,12 @@ inline TypeName* Unwrap(v8::Local<v8::Object> object);
inline void SwapBytes(uint16_t* dst, const uint16_t* src, size_t buflen);
+// tolower() is locale-sensitive. Use ToLower() instead.
+inline char ToLower(char c);
+
+// strcasecmp() is locale-sensitive. Use StringEqualNoCase() instead.
+inline bool StringEqualNoCase(const char* a, const char* b);
+
// Allocates an array of member type T. For up to kStackStorageSize items,
// the stack is used, otherwise malloc().
template <typename T, size_t kStackStorageSize = 1024>
diff --git a/test/cctest/util.cc b/test/cctest/util.cc
index fe966d9b34..37133aca56 100644
--- a/test/cctest/util.cc
+++ b/test/cctest/util.cc
@@ -56,3 +56,21 @@ TEST(UtilTest, ListHead) {
EXPECT_TRUE(list.IsEmpty());
EXPECT_FALSE(list.begin() != list.end());
}
+
+TEST(UtilTest, StringEqualNoCase) {
+ using node::StringEqualNoCase;
+ EXPECT_FALSE(StringEqualNoCase("a", "b"));
+ EXPECT_TRUE(StringEqualNoCase("", ""));
+ EXPECT_TRUE(StringEqualNoCase("equal", "equal"));
+ EXPECT_TRUE(StringEqualNoCase("equal", "EQUAL"));
+ EXPECT_TRUE(StringEqualNoCase("EQUAL", "EQUAL"));
+ EXPECT_FALSE(StringEqualNoCase("equal", "equals"));
+ EXPECT_FALSE(StringEqualNoCase("equals", "equal"));
+}
+
+TEST(UtilTest, ToLower) {
+ using node::ToLower;
+ EXPECT_EQ('0', ToLower('0'));
+ EXPECT_EQ('a', ToLower('a'));
+ EXPECT_EQ('a', ToLower('A'));
+}