15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Derived from: 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mozilla/netwerk/protocol/http/src/nsHttpChunkedDecoder.cpp 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The license block is: 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* ***** BEGIN LICENSE BLOCK ***** 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Version: MPL 1.1/GPL 2.0/LGPL 2.1 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The contents of this file are subject to the Mozilla Public License Version 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1.1 (the "License"); you may not use this file except in compliance with 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the License. You may obtain a copy of the License at 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * http://www.mozilla.org/MPL/ 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Software distributed under the License is distributed on an "AS IS" basis, 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * for the specific language governing rights and limitations under the 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * License. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The Original Code is Mozilla. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The Initial Developer of the Original Code is 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Netscape Communications. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Portions created by the Initial Developer are Copyright (C) 2001 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the Initial Developer. All Rights Reserved. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Contributor(s): 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Darin Fisher <darin@netscape.com> (original author) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Alternatively, the contents of this file may be used under the terms of 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * either the GNU General Public License Version 2 or later (the "GPL"), or 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in which case the provisions of the GPL or the LGPL are applicable instead 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of those above. If you wish to allow use of your version of this file only 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * under the terms of either the GPL or the LGPL, and not to allow others to 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * use your version of this file under the terms of the MPL, indicate your 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * decision by deleting the provisions above and replace them with the notice 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and other provisions required by the GPL or the LGPL. If you do not delete 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the provisions above, a recipient may use your version of this file under 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the terms of any one of the MPL, the GPL or the LGPL. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ***** END LICENSE BLOCK ***** */ 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_chunked_decoder.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <algorithm> 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h" 527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h" 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Absurdly long size to avoid imposing a constraint on chunked encoding 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// extensions. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t HttpChunkedDecoder::kMaxLineBufLen = 16384; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpChunkedDecoder::HttpChunkedDecoder() 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : chunk_remaining_(0), 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunk_terminator_remaining_(false), 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reached_last_chunk_(false), 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reached_eof_(false), 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_after_eof_(0) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpChunkedDecoder::FilterBuf(char* buf, int buf_len) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = 0; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (buf_len) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chunk_remaining_) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num = std::min(chunk_remaining_, buf_len); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf_len -= num; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunk_remaining_ -= num; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result += num; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf += num; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // After each chunk's data there should be a CRLF 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!chunk_remaining_) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunk_terminator_remaining_ = true; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (reached_eof_) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_after_eof_ += buf_len; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; // Done! 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_consumed = ScanForChunkRemaining(buf, buf_len); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_consumed < 0) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bytes_consumed; // Error 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf_len -= bytes_consumed; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buf_len) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memmove(buf, buf + bytes_consumed, buf_len); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpChunkedDecoder::ScanForChunkRemaining(const char* buf, int buf_len) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0, chunk_remaining_); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(buf_len, 0); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_consumed = 0; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index_of_lf = base::StringPiece(buf, buf_len).find('\n'); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index_of_lf != base::StringPiece::npos) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf_len = static_cast<int>(index_of_lf); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buf_len && buf[buf_len - 1] == '\r') // Eliminate a preceding CR. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf_len--; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_consumed = static_cast<int>(index_of_lf) + 1; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make buf point to the full line buffer to parse. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!line_buf_.empty()) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) line_buf_.append(buf, buf_len); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf = line_buf_.data(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf_len = static_cast<int>(line_buf_.size()); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reached_last_chunk_) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buf_len) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "ignoring http trailer"; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reached_eof_ = true; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (chunk_terminator_remaining_) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buf_len) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "chunk data not terminated properly"; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INVALID_CHUNKED_ENCODING; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunk_terminator_remaining_ = false; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (buf_len) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore any chunk-extensions. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index_of_semicolon = base::StringPiece(buf, buf_len).find(';'); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index_of_semicolon != base::StringPiece::npos) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf_len = static_cast<int>(index_of_semicolon); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ParseChunkSize(buf, buf_len, &chunk_remaining_)) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "Failed parsing HEX from: " << 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(buf, buf_len); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INVALID_CHUNKED_ENCODING; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chunk_remaining_ == 0) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reached_last_chunk_ = true; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "missing chunk-size"; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INVALID_CHUNKED_ENCODING; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) line_buf_.clear(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the partial line; wait for more data. 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_consumed = buf_len; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore a trailing CR 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buf[buf_len - 1] == '\r') 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf_len--; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (line_buf_.length() + buf_len > kMaxLineBufLen) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "Chunked line length too long"; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INVALID_CHUNKED_ENCODING; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) line_buf_.append(buf, buf_len); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bytes_consumed; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// While the HTTP 1.1 specification defines chunk-size as 1*HEX 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// some sites rely on more lenient parsing. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://www.yahoo.com/, for example, pads chunk-size with trailing spaces 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (0x20) to be 7 characters long, such as "819b ". 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A comparison of browsers running on WindowsXP shows that 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// they will parse the following inputs (egrep syntax): 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Let \X be the character class for a hex digit: [0-9a-fA-F] 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RFC 2616: ^\X+$ 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IE7: ^\X+[^\X]*$ 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Safari 3.1: ^[\t\r ]*\X+[\t ]*$ 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Firefox 3: ^[\t\f\v\r ]*[+]?(0x)?\X+[^\X]*$ 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Opera 9.51: ^[\t\f\v ]*[+]?(0x)?\X+[^\X]*$ 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Our strategy is to be as strict as possible, while not breaking 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// known sites. 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Us: ^\X+[ ]*$ 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpChunkedDecoder::ParseChunkSize(const char* start, int len, int* out) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(len, 0); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Strip trailing spaces 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (len && start[len - 1] == ' ') 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len--; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Be more restrictive than HexStringToInt; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // don't allow inputs with leading "-", "+", "0x", "0X" 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece chunk_size(start, len); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chunk_size.find_first_not_of("0123456789abcdefABCDEF") 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) != base::StringPiece::npos) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int parsed_number; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ok = base::HexStringToInt(chunk_size, &parsed_number); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ok && parsed_number >= 0) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *out = parsed_number; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 217