From 3d69ad1cf3f2d4bed9ee9e9338e0a02f68716256 Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Thu, 9 Jun 2016 09:31:45 -0700 Subject: [PATCH] src: make Sec-WebSocket-Key check case-insensitive Current case sensitive comparison is breaking netty-based WS clients. replace strncmp with strncasecmp Fixes: https://github.com/nodejs/node/issues/7247 PR-URL: https://github.com/nodejs/node/pull/7248 Reviewed-By: Colin Ihrig Reviewed-By: Ali Ijaz Sheikh Reviewed-By: Ben Noordhuis --- src/inspector_socket.cc | 9 ++++++--- src/util-inl.h | 10 ++++++++++ src/util.h | 3 +++ test/cctest/util.cc | 15 +++++++++++++++ 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/inspector_socket.cc b/src/inspector_socket.cc index cb248ec59feb1a..fa2b6734e9e186 100644 --- a/src/inspector_socket.cc +++ b/src/inspector_socket.cc @@ -1,4 +1,6 @@ #include "inspector_socket.h" +#include "util.h" +#include "util-inl.h" #define NODE_WANT_INTERNALS 1 #include "base64.h" @@ -445,9 +447,10 @@ static int header_value_cb(http_parser* parser, const char* at, size_t length) { struct http_parsing_state_s* state = (struct http_parsing_state_s*) (reinterpret_cast(parser->data))->http_parsing_state; state->parsing_value = true; - if (state->current_header && strncmp(state->current_header, - SEC_WEBSOCKET_KEY_HEADER, - sizeof(SEC_WEBSOCKET_KEY_HEADER)) == 0) { + if (state->current_header && + node::StringEqualNoCaseN(state->current_header, + SEC_WEBSOCKET_KEY_HEADER, + sizeof(SEC_WEBSOCKET_KEY_HEADER))) { append(&state->ws_key, at, length); } return 0; diff --git a/src/util-inl.h b/src/util-inl.h index 67fe0bd26c3f16..a167a57c5ab67d 100644 --- a/src/util-inl.h +++ b/src/util-inl.h @@ -219,6 +219,16 @@ bool StringEqualNoCase(const char* a, const char* b) { return false; } +bool StringEqualNoCaseN(const char* a, const char* b, size_t length) { + for (size_t i = 0; i < length; i++) { + if (ToLower(a[i]) != ToLower(b[i])) + return false; + if (a[i] == '\0') + return true; + } + return true; +} + } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS diff --git a/src/util.h b/src/util.h index 077b7beb4d4ac3..9ad0f6c5ed0aae 100644 --- a/src/util.h +++ b/src/util.h @@ -206,6 +206,9 @@ inline char ToLower(char c); // strcasecmp() is locale-sensitive. Use StringEqualNoCase() instead. inline bool StringEqualNoCase(const char* a, const char* b); +// strncasecmp() is locale-sensitive. Use StringEqualNoCaseN() instead. +inline bool StringEqualNoCaseN(const char* a, const char* b, size_t length); + // Allocates an array of member type T. For up to kStackStorageSize items, // the stack is used, otherwise malloc(). template diff --git a/test/cctest/util.cc b/test/cctest/util.cc index 37133aca562b72..862024aff33d6f 100644 --- a/test/cctest/util.cc +++ b/test/cctest/util.cc @@ -68,6 +68,21 @@ TEST(UtilTest, StringEqualNoCase) { EXPECT_FALSE(StringEqualNoCase("equals", "equal")); } +TEST(UtilTest, StringEqualNoCaseN) { + using node::StringEqualNoCaseN; + EXPECT_FALSE(StringEqualNoCaseN("a", "b", strlen("a"))); + EXPECT_TRUE(StringEqualNoCaseN("", "", strlen(""))); + EXPECT_TRUE(StringEqualNoCaseN("equal", "equal", strlen("equal"))); + EXPECT_TRUE(StringEqualNoCaseN("equal", "EQUAL", strlen("equal"))); + EXPECT_TRUE(StringEqualNoCaseN("EQUAL", "EQUAL", strlen("equal"))); + EXPECT_TRUE(StringEqualNoCaseN("equal", "equals", strlen("equal"))); + EXPECT_FALSE(StringEqualNoCaseN("equal", "equals", strlen("equals"))); + EXPECT_TRUE(StringEqualNoCaseN("equals", "equal", strlen("equal"))); + EXPECT_FALSE(StringEqualNoCaseN("equals", "equal", strlen("equals"))); + EXPECT_TRUE(StringEqualNoCaseN("abc\0abc", "abc\0efg", strlen("abcdefgh"))); + EXPECT_FALSE(StringEqualNoCaseN("abc\0abc", "abcd\0efg", strlen("abcdefgh"))); +} + TEST(UtilTest, ToLower) { using node::ToLower; EXPECT_EQ('0', ToLower('0'));