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

Side by Side Diff: net/cookies/parsed_cookie.cc

Issue 15897003: Added UMA measurement for how often we see control characters during cookie parsing. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added comment to file explaining UMA collection and fixed erikwright nit. Created 7 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 // Portions of this code based on Mozilla: 5 // Portions of this code based on Mozilla:
6 // (netwerk/cookie/src/nsCookieService.cpp) 6 // (netwerk/cookie/src/nsCookieService.cpp)
7 /* ***** BEGIN LICENSE BLOCK ***** 7 /* ***** BEGIN LICENSE BLOCK *****
8 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 8 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
9 * 9 *
10 * The contents of this file are subject to the Mozilla Public License Version 10 * The contents of this file are subject to the Mozilla Public License Version
(...skipping 27 matching lines...) Expand all
38 * decision by deleting the provisions above and replace them with the notice 38 * decision by deleting the provisions above and replace them with the notice
39 * and other provisions required by the GPL or the LGPL. If you do not delete 39 * and other provisions required by the GPL or the LGPL. If you do not delete
40 * the provisions above, a recipient may use your version of this file under 40 * the provisions above, a recipient may use your version of this file under
41 * the terms of any one of the MPL, the GPL or the LGPL. 41 * the terms of any one of the MPL, the GPL or the LGPL.
42 * 42 *
43 * ***** END LICENSE BLOCK ***** */ 43 * ***** END LICENSE BLOCK ***** */
44 44
45 #include "net/cookies/parsed_cookie.h" 45 #include "net/cookies/parsed_cookie.h"
46 46
47 #include "base/logging.h" 47 #include "base/logging.h"
48 #include "base/metrics/histogram.h"
48 #include "base/string_util.h" 49 #include "base/string_util.h"
49 50
51 // We are collecting several UMA statistics in this file, and they relate to
erikwright (departed) 2013/05/28 19:59:05 nit: Prefix with 'TODO(jww): Remove metrics code a
jww 2013/05/28 20:45:47 Done.
52 // http://crbug.com/238041. We are measuring stats related to control characters
53 // in cookies because, currently, we allow control characters in a variety of
54 // scenarios where various RFCs theoretically disallow them. These control
55 // characters have the potential to cause problems with certain web servers that
56 // reject HTTP requests that contain cookies with control characters. We are
57 // measuring whether disallowing such cookies would have a notable impact on our
58 // users. We want to collect these stats through 1 stable release, so these UMA
59 // stats should remain at least through the M29 branch-point.
60
50 namespace { 61 namespace {
51 62
52 const char kPathTokenName[] = "path"; 63 const char kPathTokenName[] = "path";
53 const char kDomainTokenName[] = "domain"; 64 const char kDomainTokenName[] = "domain";
54 const char kExpiresTokenName[] = "expires"; 65 const char kExpiresTokenName[] = "expires";
55 const char kMaxAgeTokenName[] = "max-age"; 66 const char kMaxAgeTokenName[] = "max-age";
56 const char kSecureTokenName[] = "secure"; 67 const char kSecureTokenName[] = "secure";
57 const char kHttpOnlyTokenName[] = "httponly"; 68 const char kHttpOnlyTokenName[] = "httponly";
58 const char kPriorityTokenName[] = "priority"; 69 const char kPriorityTokenName[] = "priority";
59 70
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 bool ParsedCookie::IsValid() const { 186 bool ParsedCookie::IsValid() const {
176 return !pairs_.empty(); 187 return !pairs_.empty();
177 } 188 }
178 189
179 CookiePriority ParsedCookie::Priority() const { 190 CookiePriority ParsedCookie::Priority() const {
180 return (priority_index_ == 0) ? COOKIE_PRIORITY_DEFAULT : 191 return (priority_index_ == 0) ? COOKIE_PRIORITY_DEFAULT :
181 StringToCookiePriority(pairs_[priority_index_].second); 192 StringToCookiePriority(pairs_[priority_index_].second);
182 } 193 }
183 194
184 bool ParsedCookie::SetName(const std::string& name) { 195 bool ParsedCookie::SetName(const std::string& name) {
185 if (!IsValidToken(name)) 196 if (!IsValidToken(name)) {
197 UMA_HISTOGRAM_BOOLEAN("Cookies.SetNameInvalidToken", true);
186 return false; 198 return false;
199 }
187 if (pairs_.empty()) 200 if (pairs_.empty())
188 pairs_.push_back(std::make_pair("", "")); 201 pairs_.push_back(std::make_pair("", ""));
189 pairs_[0].first = name; 202 pairs_[0].first = name;
203 UMA_HISTOGRAM_BOOLEAN("Cookies.SetNameInvalidToken", false);
190 return true; 204 return true;
191 } 205 }
192 206
193 bool ParsedCookie::SetValue(const std::string& value) { 207 bool ParsedCookie::SetValue(const std::string& value) {
194 if (!IsValidCookieValue(value)) 208 if (!IsValidCookieValue(value)) {
209 UMA_HISTOGRAM_BOOLEAN("Cookies.SetValueInvalidCookieValue", true);
195 return false; 210 return false;
211 }
196 if (pairs_.empty()) 212 if (pairs_.empty())
197 pairs_.push_back(std::make_pair("", "")); 213 pairs_.push_back(std::make_pair("", ""));
198 pairs_[0].second = value; 214 pairs_[0].second = value;
215 UMA_HISTOGRAM_BOOLEAN("Cookies.SetValueInvalidCookieValue", false);
199 return true; 216 return true;
200 } 217 }
201 218
202 bool ParsedCookie::SetPath(const std::string& path) { 219 bool ParsedCookie::SetPath(const std::string& path) {
203 return SetString(&path_index_, kPathTokenName, path); 220 return SetString(&path_index_, kPathTokenName, path);
204 } 221 }
205 222
206 bool ParsedCookie::SetDomain(const std::string& domain) { 223 bool ParsedCookie::SetDomain(const std::string& domain) {
207 return SetString(&domain_index_, kDomainTokenName, domain); 224 return SetString(&domain_index_, kDomainTokenName, domain);
208 } 225 }
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 std::string::const_iterator it = value.begin(); 347 std::string::const_iterator it = value.begin();
331 std::string::const_iterator end = FindFirstTerminator(value); 348 std::string::const_iterator end = FindFirstTerminator(value);
332 349
333 std::string::const_iterator value_start, value_end; 350 std::string::const_iterator value_start, value_end;
334 ParseValue(&it, end, &value_start, &value_end); 351 ParseValue(&it, end, &value_start, &value_end);
335 return std::string(value_start, value_end); 352 return std::string(value_start, value_end);
336 } 353 }
337 354
338 // Parse all token/value pairs and populate pairs_. 355 // Parse all token/value pairs and populate pairs_.
339 void ParsedCookie::ParseTokenValuePairs(const std::string& cookie_line) { 356 void ParsedCookie::ParseTokenValuePairs(const std::string& cookie_line) {
357 bool parsed_invalid_control_char = false;
358 bool parsed_invalid_token = false;
359
340 pairs_.clear(); 360 pairs_.clear();
341 361
342 // Ok, here we go. We should be expecting to be starting somewhere 362 // Ok, here we go. We should be expecting to be starting somewhere
343 // before the cookie line, not including any header name... 363 // before the cookie line, not including any header name...
344 std::string::const_iterator start = cookie_line.begin(); 364 std::string::const_iterator start = cookie_line.begin();
345 std::string::const_iterator it = start; 365 std::string::const_iterator it = start;
346 366
347 // TODO(erikwright): Make sure we're stripping \r\n in the network code. 367 // TODO(erikwright): Make sure we're stripping \r\n in the network code.
348 // Then we can log any unexpected terminators. 368 // Then we can log any unexpected terminators.
349 std::string::const_iterator end = FindFirstTerminator(cookie_line); 369 std::string::const_iterator end = FindFirstTerminator(cookie_line);
(...skipping 27 matching lines...) Expand all
377 pair.first = std::string(token_start, token_end); 397 pair.first = std::string(token_start, token_end);
378 ++it; // Skip past the '='. 398 ++it; // Skip past the '='.
379 } 399 }
380 400
381 // OK, now try to parse a value. 401 // OK, now try to parse a value.
382 std::string::const_iterator value_start, value_end; 402 std::string::const_iterator value_start, value_end;
383 ParseValue(&it, end, &value_start, &value_end); 403 ParseValue(&it, end, &value_start, &value_end);
384 // OK, we're finished with a Token/Value. 404 // OK, we're finished with a Token/Value.
385 pair.second = std::string(value_start, value_end); 405 pair.second = std::string(value_start, value_end);
386 406
407 if (!IsValidCookieAttributeValue(pair.second))
408 parsed_invalid_control_char = true;
409 if (!IsValidToken(pair.second))
410 parsed_invalid_token = true;
411
387 // From RFC2109: "Attributes (names) (attr) are case-insensitive." 412 // From RFC2109: "Attributes (names) (attr) are case-insensitive."
388 if (pair_num != 0) 413 if (pair_num != 0)
389 StringToLowerASCII(&pair.first); 414 StringToLowerASCII(&pair.first);
390 pairs_.push_back(pair); 415 pairs_.push_back(pair);
391 416
392 // We've processed a token/value pair, we're either at the end of 417 // We've processed a token/value pair, we're either at the end of
393 // the string or a ValueSeparator like ';', which we want to skip. 418 // the string or a ValueSeparator like ';', which we want to skip.
394 if (it != end) 419 if (it != end)
395 ++it; 420 ++it;
396 } 421 }
422
423 UMA_HISTOGRAM_BOOLEAN("Cookies.ParsedInvalidControlCharacter",
424 parsed_invalid_control_char);
425 UMA_HISTOGRAM_BOOLEAN("Cookies.ParsedInvalidToken", parsed_invalid_token);
397 } 426 }
398 427
399 void ParsedCookie::SetupAttributes() { 428 void ParsedCookie::SetupAttributes() {
400 // We skip over the first token/value, the user supplied one. 429 // We skip over the first token/value, the user supplied one.
401 for (size_t i = 1; i < pairs_.size(); ++i) { 430 for (size_t i = 1; i < pairs_.size(); ++i) {
402 if (pairs_[i].first == kPathTokenName) { 431 if (pairs_[i].first == kPathTokenName) {
403 path_index_ = i; 432 path_index_ = i;
404 } else if (pairs_[i].first == kDomainTokenName) { 433 } else if (pairs_[i].first == kDomainTokenName) {
405 domain_index_ = i; 434 domain_index_ = i;
406 } else if (pairs_[i].first == kExpiresTokenName) { 435 } else if (pairs_[i].first == kExpiresTokenName) {
(...skipping 30 matching lines...) Expand all
437 ClearAttributePair(*index); 466 ClearAttributePair(*index);
438 return true; 467 return true;
439 } else { 468 } else {
440 return SetAttributePair(index, key, std::string()); 469 return SetAttributePair(index, key, std::string());
441 } 470 }
442 } 471 }
443 472
444 bool ParsedCookie::SetAttributePair(size_t* index, 473 bool ParsedCookie::SetAttributePair(size_t* index,
445 const std::string& key, 474 const std::string& key,
446 const std::string& value) { 475 const std::string& value) {
447 if (!IsValidToken(key) || !IsValidCookieAttributeValue(value)) 476 if (!IsValidToken(key) || !IsValidCookieAttributeValue(value)) {
477 UMA_HISTOGRAM_BOOLEAN("Cookies.SetAttributePairInvalidChars", true);
448 return false; 478 return false;
479 }
480 UMA_HISTOGRAM_BOOLEAN("Cookies.SetAttributePairInvalidChars", false);
449 if (!IsValid()) 481 if (!IsValid())
450 return false; 482 return false;
451 if (*index) { 483 if (*index) {
452 pairs_[*index].second = value; 484 pairs_[*index].second = value;
453 } else { 485 } else {
454 pairs_.push_back(std::make_pair(key, value)); 486 pairs_.push_back(std::make_pair(key, value));
455 *index = pairs_.size() - 1; 487 *index = pairs_.size() - 1;
456 } 488 }
457 return true; 489 return true;
458 } 490 }
(...skipping 11 matching lines...) Expand all
470 for (size_t i = 0; i < arraysize(indexes); ++i) { 502 for (size_t i = 0; i < arraysize(indexes); ++i) {
471 if (*indexes[i] == index) 503 if (*indexes[i] == index)
472 *indexes[i] = 0; 504 *indexes[i] = 0;
473 else if (*indexes[i] > index) 505 else if (*indexes[i] > index)
474 --*indexes[i]; 506 --*indexes[i];
475 } 507 }
476 pairs_.erase(pairs_.begin() + index); 508 pairs_.erase(pairs_.begin() + index);
477 } 509 }
478 510
479 } // namespace 511 } // namespace
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698