Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(192)

Side by Side Diff: net/websockets/websocket_extension_parser.cc

Issue 2344873002: WebSocketExtensionParser: reject top-bit-set characters (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/websockets/websocket_extension_parser.h" 5 #include "net/websockets/websocket_extension_parser.h"
6 6
7 #include "base/strings/string_util.h" 7 #include "base/strings/string_util.h"
8 #include "net/http/http_util.h"
8 9
9 namespace net { 10 namespace net {
10 11
12 namespace {
13 bool IsControl(char c) {
14 return (0 <= c && c <= 31) || c == 127;
15 }
16 } // namespace
17
11 WebSocketExtensionParser::WebSocketExtensionParser() {} 18 WebSocketExtensionParser::WebSocketExtensionParser() {}
12 19
13 WebSocketExtensionParser::~WebSocketExtensionParser() {} 20 WebSocketExtensionParser::~WebSocketExtensionParser() {}
14 21
15 bool WebSocketExtensionParser::Parse(const char* data, size_t size) { 22 bool WebSocketExtensionParser::Parse(const char* data, size_t size) {
16 current_ = data; 23 current_ = data;
17 end_ = data + size; 24 end_ = data + size;
18 extensions_.clear(); 25 extensions_.clear();
19 26
20 bool failed = false; 27 bool failed = false;
21 28
22 while (true) { 29 do {
23 WebSocketExtension extension; 30 WebSocketExtension extension;
24 if (!ConsumeExtension(&extension)) { 31 if (!ConsumeExtension(&extension)) {
25 failed = true; 32 failed = true;
26 break; 33 break;
27 } 34 }
28 extensions_.push_back(extension); 35 extensions_.push_back(extension);
29 36
30 ConsumeSpaces(); 37 ConsumeSpaces();
31 38 } while (ConsumeIfMatch(','));
32 if (!ConsumeIfMatch(',')) {
33 break;
34 }
35 }
36 39
37 if (!failed && current_ == end_) 40 if (!failed && current_ == end_)
38 return true; 41 return true;
39 42
40 extensions_.clear(); 43 extensions_.clear();
41 return false; 44 return false;
42 } 45 }
43 46
44 bool WebSocketExtensionParser::Consume(char c) { 47 bool WebSocketExtensionParser::Consume(char c) {
45 ConsumeSpaces(); 48 ConsumeSpaces();
46 if (current_ == end_ || c != current_[0]) { 49 if (current_ == end_ || c != *current_)
47 return false; 50 return false;
48 }
49 ++current_; 51 ++current_;
50 return true; 52 return true;
51 } 53 }
52 54
53 bool WebSocketExtensionParser::ConsumeExtension(WebSocketExtension* extension) { 55 bool WebSocketExtensionParser::ConsumeExtension(WebSocketExtension* extension) {
54 base::StringPiece name; 56 base::StringPiece name;
55 if (!ConsumeToken(&name)) 57 if (!ConsumeToken(&name))
56 return false; 58 return false;
57 *extension = WebSocketExtension(name.as_string()); 59 *extension = WebSocketExtension(name.as_string());
58 60
(...skipping 28 matching lines...) Expand all
87 return false; 89 return false;
88 value_string = value.as_string(); 90 value_string = value.as_string();
89 } 91 }
90 *parameter = WebSocketExtension::Parameter(name.as_string(), value_string); 92 *parameter = WebSocketExtension::Parameter(name.as_string(), value_string);
91 return true; 93 return true;
92 } 94 }
93 95
94 bool WebSocketExtensionParser::ConsumeToken(base::StringPiece* token) { 96 bool WebSocketExtensionParser::ConsumeToken(base::StringPiece* token) {
95 ConsumeSpaces(); 97 ConsumeSpaces();
96 const char* head = current_; 98 const char* head = current_;
97 while (current_ < end_ && 99 while (current_ < end_ && HttpUtil::IsTokenChar(*current_))
98 !IsControl(current_[0]) && !IsSeparator(current_[0]))
99 ++current_; 100 ++current_;
100 if (current_ == head) { 101 if (current_ == head)
101 return false; 102 return false;
102 }
103 *token = base::StringPiece(head, current_ - head); 103 *token = base::StringPiece(head, current_ - head);
104 return true; 104 return true;
105 } 105 }
106 106
107 bool WebSocketExtensionParser::ConsumeQuotedToken(std::string* token) { 107 bool WebSocketExtensionParser::ConsumeQuotedToken(std::string* token) {
108 if (!Consume('"')) 108 if (!Consume('"'))
109 return false; 109 return false;
110 110
111 *token = ""; 111 *token = "";
112 while (current_ < end_ && !IsControl(current_[0])) { 112 while (current_ < end_ && !IsControl(*current_)) {
tyoshino (SeeGerritForStatus) 2016/09/16 04:44:23 we can remove this IsControl() call?
Adam Rice 2016/09/16 05:57:56 Yes! I didn't notice that during refactoring it ha
113 if (UnconsumedBytes() >= 2 && current_[0] == '\\') { 113 if (*current_ == '\\') {
tyoshino (SeeGerritForStatus) 2016/09/16 04:44:23 good catch
114 char next = current_[1]; 114 ++current_;
115 if (IsControl(next) || IsSeparator(next)) break; 115 if (current_ == end_ || !HttpUtil::IsTokenChar(*current_))
116 *token += next; 116 return false;
117 current_ += 2; 117 *token += *current_;
118 } else if (IsSeparator(current_[0])) { 118 ++current_;
119 break;
120 } else { 119 } else {
121 *token += current_[0]; 120 if (!HttpUtil::IsTokenChar(*current_))
121 break;
tyoshino (SeeGerritForStatus) 2016/09/16 04:44:23 we can return with false here too?
Adam Rice 2016/09/16 05:57:56 I tried it but it doesn't work. If the character i
tyoshino (SeeGerritForStatus) 2016/09/16 06:44:23 Got it!
122 *token += *current_;
122 ++current_; 123 ++current_;
123 } 124 }
124 } 125 }
125 // We can't use Consume here because we don't want to consume spaces. 126 // We can't use Consume here because we don't want to consume spaces.
126 if (current_ >= end_ || current_[0] != '"') 127 if (current_ >= end_ || *current_ != '"')
127 return false; 128 return false;
128 129
129 ++current_; 130 ++current_;
130 131
131 return !token->empty(); 132 return !token->empty();
132 } 133 }
133 134
134 void WebSocketExtensionParser::ConsumeSpaces() { 135 void WebSocketExtensionParser::ConsumeSpaces() {
135 while (current_ < end_ && (current_[0] == ' ' || current_[0] == '\t')) 136 while (current_ < end_ && (*current_ == ' ' || *current_ == '\t'))
136 ++current_; 137 ++current_;
137 return; 138 return;
138 } 139 }
139 140
140 bool WebSocketExtensionParser::Lookahead(char c) { 141 bool WebSocketExtensionParser::Lookahead(char c) {
141 const char* head = current_; 142 const char* head = current_;
142 bool result = Consume(c); 143 bool result = Consume(c);
143 current_ = head; 144 current_ = head;
144 return result; 145 return result;
145 } 146 }
146 147
147 bool WebSocketExtensionParser::ConsumeIfMatch(char c) { 148 bool WebSocketExtensionParser::ConsumeIfMatch(char c) {
148 const char* head = current_; 149 const char* head = current_;
149 if (!Consume(c)) { 150 if (!Consume(c)) {
150 current_ = head; 151 current_ = head;
151 return false; 152 return false;
152 } 153 }
153 154
154 return true; 155 return true;
155 } 156 }
156 157
157 // static
158 bool WebSocketExtensionParser::IsControl(char c) {
159 return (0 <= c && c <= 31) || c == 127;
160 }
161
162 // static
163 bool WebSocketExtensionParser::IsSeparator(char c) {
164 const char separators[] = "()<>@,;:\\\"/[]?={} \t";
165 return strchr(separators, c) != NULL;
166 }
167
168 } // namespace net 158 } // namespace net
OLDNEW
« no previous file with comments | « net/websockets/websocket_extension_parser.h ('k') | net/websockets/websocket_extension_parser_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698