diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2016-05-04 20:56:04 +0200 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2016-05-05 00:28:25 +0200 |
commit | f6940dfa4627301bbd1a24530ac3f4fe3fe8494c (patch) | |
tree | e9f6400ff0e4757ab9a9a990c4b7b9c02c08b25b | |
parent | 6db772d648d2f2a79a4426e6b06fe1de298cd80c (diff) | |
download | node-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.cc | 23 | ||||
-rw-r--r-- | src/node_crypto.cc | 6 | ||||
-rw-r--r-- | src/util-inl.h | 12 | ||||
-rw-r--r-- | src/util.h | 6 | ||||
-rw-r--r-- | test/cctest/util.cc | 18 |
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')); +} |