CodedInputStream.cs 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181
  1. #region Copyright notice and license
  2. // Protocol Buffers - Google's data interchange format
  3. // Copyright 2008 Google Inc. All rights reserved.
  4. // https://developers.google.com/protocol-buffers/
  5. //
  6. // Redistribution and use in source and binary forms, with or without
  7. // modification, are permitted provided that the following conditions are
  8. // met:
  9. //
  10. // * Redistributions of source code must retain the above copyright
  11. // notice, this list of conditions and the following disclaimer.
  12. // * Redistributions in binary form must reproduce the above
  13. // copyright notice, this list of conditions and the following disclaimer
  14. // in the documentation and/or other materials provided with the
  15. // distribution.
  16. // * Neither the name of Google Inc. nor the names of its
  17. // contributors may be used to endorse or promote products derived from
  18. // this software without specific prior written permission.
  19. //
  20. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. #endregion
  32. using System;
  33. using System.Collections.Generic;
  34. using System.IO;
  35. namespace Google.Protobuf
  36. {
  37. /// <summary>
  38. /// Readings and decodes protocol message fields.
  39. /// </summary>
  40. /// <remarks>
  41. /// This class contains two kinds of methods: methods that read specific
  42. /// protocol message constructs and field types (e.g. ReadTag and
  43. /// ReadInt32) and methods that read low-level values (e.g.
  44. /// ReadRawVarint32 and ReadRawBytes). If you are reading encoded protocol
  45. /// messages, you should use the former methods, but if you are reading some
  46. /// other format of your own design, use the latter. The names of the former
  47. /// methods are taken from the protocol buffer type names, not .NET types.
  48. /// (Hence ReadFloat instead of ReadSingle, and ReadBool instead of ReadBoolean.)
  49. ///
  50. /// TODO(jonskeet): Consider whether recursion and size limits shouldn't be readonly,
  51. /// set at construction time.
  52. /// </remarks>
  53. public sealed class CodedInputStream
  54. {
  55. /// <summary>
  56. /// Buffer of data read from the stream or provided at construction time.
  57. /// </summary>
  58. private readonly byte[] buffer;
  59. /// <summary>
  60. /// The number of valid bytes in the buffer.
  61. /// </summary>
  62. private int bufferSize;
  63. private int bufferSizeAfterLimit = 0;
  64. /// <summary>
  65. /// The position within the current buffer (i.e. the next byte to read)
  66. /// </summary>
  67. private int bufferPos = 0;
  68. /// <summary>
  69. /// The stream to read further input from, or null if the byte array buffer was provided
  70. /// directly on construction, with no further data available.
  71. /// </summary>
  72. private readonly Stream input;
  73. /// <summary>
  74. /// The last tag we read. 0 indicates we've read to the end of the stream
  75. /// (or haven't read anything yet).
  76. /// </summary>
  77. private uint lastTag = 0;
  78. /// <summary>
  79. /// The next tag, used to store the value read by PeekTag.
  80. /// </summary>
  81. private uint nextTag = 0;
  82. private bool hasNextTag = false;
  83. internal const int DefaultRecursionLimit = 64;
  84. internal const int DefaultSizeLimit = 64 << 20; // 64MB
  85. internal const int BufferSize = 4096;
  86. /// <summary>
  87. /// The total number of bytes read before the current buffer. The
  88. /// total bytes read up to the current position can be computed as
  89. /// totalBytesRetired + bufferPos.
  90. /// </summary>
  91. private int totalBytesRetired = 0;
  92. /// <summary>
  93. /// The absolute position of the end of the current message.
  94. /// </summary>
  95. private int currentLimit = int.MaxValue;
  96. /// <summary>
  97. /// <see cref="SetRecursionLimit"/>
  98. /// </summary>
  99. private int recursionDepth = 0;
  100. private int recursionLimit = DefaultRecursionLimit;
  101. /// <summary>
  102. /// <see cref="SetSizeLimit"/>
  103. /// </summary>
  104. private int sizeLimit = DefaultSizeLimit;
  105. #region Construction
  106. /// <summary>
  107. /// Creates a new CodedInputStream reading data from the given
  108. /// byte array.
  109. /// </summary>
  110. public CodedInputStream(byte[] buf) : this(buf, 0, buf.Length)
  111. {
  112. }
  113. /// <summary>
  114. /// Creates a new CodedInputStream that reads from the given
  115. /// byte array slice.
  116. /// </summary>
  117. public CodedInputStream(byte[] buffer, int offset, int length)
  118. {
  119. this.buffer = buffer;
  120. this.bufferPos = offset;
  121. this.bufferSize = offset + length;
  122. this.input = null;
  123. }
  124. /// <summary>
  125. /// Creates a new CodedInputStream reading data from the given stream.
  126. /// </summary>
  127. public CodedInputStream(Stream input)
  128. {
  129. this.buffer = new byte[BufferSize];
  130. this.bufferSize = 0;
  131. this.input = input;
  132. }
  133. /// <summary>
  134. /// Creates a new CodedInputStream reading data from the given
  135. /// stream, with a pre-allocated buffer.
  136. /// </summary>
  137. internal CodedInputStream(Stream input, byte[] buffer)
  138. {
  139. this.buffer = buffer;
  140. this.bufferSize = 0;
  141. this.input = input;
  142. }
  143. #endregion
  144. /// <summary>
  145. /// Returns the current position in the input stream, or the position in the input buffer
  146. /// </summary>
  147. public long Position
  148. {
  149. get
  150. {
  151. if (input != null)
  152. {
  153. return input.Position - ((bufferSize + bufferSizeAfterLimit) - bufferPos);
  154. }
  155. return bufferPos;
  156. }
  157. }
  158. /// <summary>
  159. /// Returns the last tag read, or 0 if no tags have been read or we've read beyond
  160. /// the end of the stream.
  161. /// </summary>
  162. internal uint LastTag { get { return lastTag; } }
  163. #region Limits for recursion and length
  164. /// <summary>
  165. /// Set the maximum message recursion depth.
  166. /// </summary>
  167. /// <remarks>
  168. /// In order to prevent malicious
  169. /// messages from causing stack overflows, CodedInputStream limits
  170. /// how deeply messages may be nested. The default limit is 64.
  171. /// </remarks>
  172. public int SetRecursionLimit(int limit)
  173. {
  174. if (limit < 0)
  175. {
  176. throw new ArgumentOutOfRangeException("Recursion limit cannot be negative: " + limit);
  177. }
  178. int oldLimit = recursionLimit;
  179. recursionLimit = limit;
  180. return oldLimit;
  181. }
  182. /// <summary>
  183. /// Set the maximum message size.
  184. /// </summary>
  185. /// <remarks>
  186. /// In order to prevent malicious messages from exhausting memory or
  187. /// causing integer overflows, CodedInputStream limits how large a message may be.
  188. /// The default limit is 64MB. You should set this limit as small
  189. /// as you can without harming your app's functionality. Note that
  190. /// size limits only apply when reading from an InputStream, not
  191. /// when constructed around a raw byte array (nor with ByteString.NewCodedInput).
  192. /// If you want to read several messages from a single CodedInputStream, you
  193. /// can call ResetSizeCounter() after each message to avoid hitting the
  194. /// size limit.
  195. /// </remarks>
  196. public int SetSizeLimit(int limit)
  197. {
  198. if (limit < 0)
  199. {
  200. throw new ArgumentOutOfRangeException("Size limit cannot be negative: " + limit);
  201. }
  202. int oldLimit = sizeLimit;
  203. sizeLimit = limit;
  204. return oldLimit;
  205. }
  206. /// <summary>
  207. /// Resets the current size counter to zero (see <see cref="SetSizeLimit"/>).
  208. /// </summary>
  209. public void ResetSizeCounter()
  210. {
  211. totalBytesRetired = 0;
  212. }
  213. #endregion
  214. #region Validation
  215. /// <summary>
  216. /// Verifies that the last call to ReadTag() returned the given tag value.
  217. /// This is used to verify that a nested group ended with the correct
  218. /// end tag.
  219. /// </summary>
  220. /// <exception cref="InvalidProtocolBufferException">The last
  221. /// tag read was not the one specified</exception>
  222. internal void CheckLastTagWas(uint value)
  223. {
  224. if (lastTag != value)
  225. {
  226. throw InvalidProtocolBufferException.InvalidEndTag();
  227. }
  228. }
  229. #endregion
  230. #region Reading of tags etc
  231. /// <summary>
  232. /// Peeks at the next field tag. This is like calling <see cref="ReadTag"/>, but the
  233. /// tag is not consumed. (So a subsequent call to <see cref="ReadTag"/> will return the
  234. /// same value.)
  235. /// </summary>
  236. public uint PeekTag()
  237. {
  238. if (hasNextTag)
  239. {
  240. return nextTag;
  241. }
  242. uint savedLast = lastTag;
  243. nextTag = ReadTag();
  244. hasNextTag = true;
  245. lastTag = savedLast; // Undo the side effect of ReadTag
  246. return nextTag;
  247. }
  248. /// <summary>
  249. /// Reads a field tag, returning the tag of 0 for "end of stream".
  250. /// </summary>
  251. /// <returns>The next field tag, or 0 for end of stream. (0 is never a valid tag.)</returns>
  252. public uint ReadTag()
  253. {
  254. if (hasNextTag)
  255. {
  256. lastTag = nextTag;
  257. hasNextTag = false;
  258. return lastTag;
  259. }
  260. // Optimize for the incredibly common case of having at least two bytes left in the buffer,
  261. // and those two bytes being enough to get the tag. This will be true for fields up to 4095.
  262. if (bufferPos + 2 <= bufferSize)
  263. {
  264. int tmp = buffer[bufferPos++];
  265. if (tmp < 128)
  266. {
  267. lastTag = (uint)tmp;
  268. }
  269. else
  270. {
  271. int result = tmp & 0x7f;
  272. if ((tmp = buffer[bufferPos++]) < 128)
  273. {
  274. result |= tmp << 7;
  275. lastTag = (uint) result;
  276. }
  277. else
  278. {
  279. // Nope, rewind and go the potentially slow route.
  280. bufferPos -= 2;
  281. lastTag = ReadRawVarint32();
  282. }
  283. }
  284. }
  285. else
  286. {
  287. if (IsAtEnd)
  288. {
  289. lastTag = 0;
  290. return 0; // This is the only case in which we return 0.
  291. }
  292. lastTag = ReadRawVarint32();
  293. }
  294. if (lastTag == 0)
  295. {
  296. // If we actually read zero, that's not a valid tag.
  297. throw InvalidProtocolBufferException.InvalidTag();
  298. }
  299. return lastTag;
  300. }
  301. /// <summary>
  302. /// Consumes the data for the field with the tag we've just read.
  303. /// This should be called directly after <see cref="ReadTag"/>, when
  304. /// the caller wishes to skip an unknown field.
  305. /// </summary>
  306. public void ConsumeLastField()
  307. {
  308. if (lastTag == 0)
  309. {
  310. throw new InvalidOperationException("ConsumeLastField cannot be called at the end of a stream");
  311. }
  312. switch (WireFormat.GetTagWireType(lastTag))
  313. {
  314. case WireFormat.WireType.StartGroup:
  315. case WireFormat.WireType.EndGroup:
  316. // TODO: Work out how to skip them instead? See issue 688.
  317. throw new InvalidProtocolBufferException("Group tags not supported by proto3 C# implementation");
  318. case WireFormat.WireType.Fixed32:
  319. ReadFixed32();
  320. break;
  321. case WireFormat.WireType.Fixed64:
  322. ReadFixed64();
  323. break;
  324. case WireFormat.WireType.LengthDelimited:
  325. var length = ReadLength();
  326. SkipRawBytes(length);
  327. break;
  328. case WireFormat.WireType.Varint:
  329. ReadRawVarint32();
  330. break;
  331. }
  332. }
  333. /// <summary>
  334. /// Reads a double field from the stream.
  335. /// </summary>
  336. public double ReadDouble()
  337. {
  338. return BitConverter.Int64BitsToDouble((long) ReadRawLittleEndian64());
  339. }
  340. /// <summary>
  341. /// Reads a float field from the stream.
  342. /// </summary>
  343. public float ReadFloat()
  344. {
  345. if (BitConverter.IsLittleEndian && 4 <= bufferSize - bufferPos)
  346. {
  347. float ret = BitConverter.ToSingle(buffer, bufferPos);
  348. bufferPos += 4;
  349. return ret;
  350. }
  351. else
  352. {
  353. byte[] rawBytes = ReadRawBytes(4);
  354. if (!BitConverter.IsLittleEndian)
  355. {
  356. ByteArray.Reverse(rawBytes);
  357. }
  358. return BitConverter.ToSingle(rawBytes, 0);
  359. }
  360. }
  361. /// <summary>
  362. /// Reads a uint64 field from the stream.
  363. /// </summary>
  364. public ulong ReadUInt64()
  365. {
  366. return ReadRawVarint64();
  367. }
  368. /// <summary>
  369. /// Reads an int64 field from the stream.
  370. /// </summary>
  371. public long ReadInt64()
  372. {
  373. return (long) ReadRawVarint64();
  374. }
  375. /// <summary>
  376. /// Reads an int32 field from the stream.
  377. /// </summary>
  378. public int ReadInt32()
  379. {
  380. return (int) ReadRawVarint32();
  381. }
  382. /// <summary>
  383. /// Reads a fixed64 field from the stream.
  384. /// </summary>
  385. public ulong ReadFixed64()
  386. {
  387. return ReadRawLittleEndian64();
  388. }
  389. /// <summary>
  390. /// Reads a fixed32 field from the stream.
  391. /// </summary>
  392. public uint ReadFixed32()
  393. {
  394. return ReadRawLittleEndian32();
  395. }
  396. /// <summary>
  397. /// Reads a bool field from the stream.
  398. /// </summary>
  399. public bool ReadBool()
  400. {
  401. return ReadRawVarint32() != 0;
  402. }
  403. /// <summary>
  404. /// Reads a string field from the stream.
  405. /// </summary>
  406. public string ReadString()
  407. {
  408. int length = ReadLength();
  409. // No need to read any data for an empty string.
  410. if (length == 0)
  411. {
  412. return "";
  413. }
  414. if (length <= bufferSize - bufferPos)
  415. {
  416. // Fast path: We already have the bytes in a contiguous buffer, so
  417. // just copy directly from it.
  418. String result = CodedOutputStream.Utf8Encoding.GetString(buffer, bufferPos, length);
  419. bufferPos += length;
  420. return result;
  421. }
  422. // Slow path: Build a byte array first then copy it.
  423. return CodedOutputStream.Utf8Encoding.GetString(ReadRawBytes(length), 0, length);
  424. }
  425. /// <summary>
  426. /// Reads an embedded message field value from the stream.
  427. /// </summary>
  428. public void ReadMessage(IMessage builder)
  429. {
  430. int length = ReadLength();
  431. if (recursionDepth >= recursionLimit)
  432. {
  433. throw InvalidProtocolBufferException.RecursionLimitExceeded();
  434. }
  435. int oldLimit = PushLimit(length);
  436. ++recursionDepth;
  437. builder.MergeFrom(this);
  438. CheckLastTagWas(0);
  439. // Check that we've read exactly as much data as expected.
  440. if (!ReachedLimit)
  441. {
  442. throw InvalidProtocolBufferException.TruncatedMessage();
  443. }
  444. --recursionDepth;
  445. PopLimit(oldLimit);
  446. }
  447. /// <summary>
  448. /// Reads a bytes field value from the stream.
  449. /// </summary>
  450. public ByteString ReadBytes()
  451. {
  452. int length = ReadLength();
  453. if (length <= bufferSize - bufferPos && length > 0)
  454. {
  455. // Fast path: We already have the bytes in a contiguous buffer, so
  456. // just copy directly from it.
  457. ByteString result = ByteString.CopyFrom(buffer, bufferPos, length);
  458. bufferPos += length;
  459. return result;
  460. }
  461. else
  462. {
  463. // Slow path: Build a byte array and attach it to a new ByteString.
  464. return ByteString.AttachBytes(ReadRawBytes(length));
  465. }
  466. }
  467. /// <summary>
  468. /// Reads a uint32 field value from the stream.
  469. /// </summary>
  470. public uint ReadUInt32()
  471. {
  472. return ReadRawVarint32();
  473. }
  474. /// <summary>
  475. /// Reads an enum field value from the stream. If the enum is valid for type T,
  476. /// then the ref value is set and it returns true. Otherwise the unknown output
  477. /// value is set and this method returns false.
  478. /// </summary>
  479. public int ReadEnum()
  480. {
  481. // Currently just a pass-through, but it's nice to separate it logically from WriteInt32.
  482. return (int) ReadRawVarint32();
  483. }
  484. /// <summary>
  485. /// Reads an sfixed32 field value from the stream.
  486. /// </summary>
  487. public int ReadSFixed32()
  488. {
  489. return (int) ReadRawLittleEndian32();
  490. }
  491. /// <summary>
  492. /// Reads an sfixed64 field value from the stream.
  493. /// </summary>
  494. public long ReadSFixed64()
  495. {
  496. return (long) ReadRawLittleEndian64();
  497. }
  498. /// <summary>
  499. /// Reads an sint32 field value from the stream.
  500. /// </summary>
  501. public int ReadSInt32()
  502. {
  503. return DecodeZigZag32(ReadRawVarint32());
  504. }
  505. /// <summary>
  506. /// Reads an sint64 field value from the stream.
  507. /// </summary>
  508. public long ReadSInt64()
  509. {
  510. return DecodeZigZag64(ReadRawVarint64());
  511. }
  512. /// <summary>
  513. /// Reads a length for length-delimited data.
  514. /// </summary>
  515. /// <remarks>
  516. /// This is internally just reading a varint, but this method exists
  517. /// to make the calling code clearer.
  518. /// </remarks>
  519. public int ReadLength()
  520. {
  521. return (int) ReadRawVarint32();
  522. }
  523. /// <summary>
  524. /// Peeks at the next tag in the stream. If it matches <paramref name="tag"/>,
  525. /// the tag is consumed and the method returns <c>true</c>; otherwise, the
  526. /// stream is left in the original position and the method returns <c>false</c>.
  527. /// </summary>
  528. public bool MaybeConsumeTag(uint tag)
  529. {
  530. if (PeekTag() == tag)
  531. {
  532. hasNextTag = false;
  533. return true;
  534. }
  535. return false;
  536. }
  537. #endregion
  538. #region Underlying reading primitives
  539. /// <summary>
  540. /// Same code as ReadRawVarint32, but read each byte individually, checking for
  541. /// buffer overflow.
  542. /// </summary>
  543. private uint SlowReadRawVarint32()
  544. {
  545. int tmp = ReadRawByte();
  546. if (tmp < 128)
  547. {
  548. return (uint) tmp;
  549. }
  550. int result = tmp & 0x7f;
  551. if ((tmp = ReadRawByte()) < 128)
  552. {
  553. result |= tmp << 7;
  554. }
  555. else
  556. {
  557. result |= (tmp & 0x7f) << 7;
  558. if ((tmp = ReadRawByte()) < 128)
  559. {
  560. result |= tmp << 14;
  561. }
  562. else
  563. {
  564. result |= (tmp & 0x7f) << 14;
  565. if ((tmp = ReadRawByte()) < 128)
  566. {
  567. result |= tmp << 21;
  568. }
  569. else
  570. {
  571. result |= (tmp & 0x7f) << 21;
  572. result |= (tmp = ReadRawByte()) << 28;
  573. if (tmp >= 128)
  574. {
  575. // Discard upper 32 bits.
  576. for (int i = 0; i < 5; i++)
  577. {
  578. if (ReadRawByte() < 128)
  579. {
  580. return (uint) result;
  581. }
  582. }
  583. throw InvalidProtocolBufferException.MalformedVarint();
  584. }
  585. }
  586. }
  587. }
  588. return (uint) result;
  589. }
  590. /// <summary>
  591. /// Reads a raw Varint from the stream. If larger than 32 bits, discard the upper bits.
  592. /// This method is optimised for the case where we've got lots of data in the buffer.
  593. /// That means we can check the size just once, then just read directly from the buffer
  594. /// without constant rechecking of the buffer length.
  595. /// </summary>
  596. internal uint ReadRawVarint32()
  597. {
  598. if (bufferPos + 5 > bufferSize)
  599. {
  600. return SlowReadRawVarint32();
  601. }
  602. int tmp = buffer[bufferPos++];
  603. if (tmp < 128)
  604. {
  605. return (uint) tmp;
  606. }
  607. int result = tmp & 0x7f;
  608. if ((tmp = buffer[bufferPos++]) < 128)
  609. {
  610. result |= tmp << 7;
  611. }
  612. else
  613. {
  614. result |= (tmp & 0x7f) << 7;
  615. if ((tmp = buffer[bufferPos++]) < 128)
  616. {
  617. result |= tmp << 14;
  618. }
  619. else
  620. {
  621. result |= (tmp & 0x7f) << 14;
  622. if ((tmp = buffer[bufferPos++]) < 128)
  623. {
  624. result |= tmp << 21;
  625. }
  626. else
  627. {
  628. result |= (tmp & 0x7f) << 21;
  629. result |= (tmp = buffer[bufferPos++]) << 28;
  630. if (tmp >= 128)
  631. {
  632. // Discard upper 32 bits.
  633. // Note that this has to use ReadRawByte() as we only ensure we've
  634. // got at least 5 bytes at the start of the method. This lets us
  635. // use the fast path in more cases, and we rarely hit this section of code.
  636. for (int i = 0; i < 5; i++)
  637. {
  638. if (ReadRawByte() < 128)
  639. {
  640. return (uint) result;
  641. }
  642. }
  643. throw InvalidProtocolBufferException.MalformedVarint();
  644. }
  645. }
  646. }
  647. }
  648. return (uint) result;
  649. }
  650. /// <summary>
  651. /// Reads a varint from the input one byte at a time, so that it does not
  652. /// read any bytes after the end of the varint. If you simply wrapped the
  653. /// stream in a CodedInputStream and used ReadRawVarint32(Stream)
  654. /// then you would probably end up reading past the end of the varint since
  655. /// CodedInputStream buffers its input.
  656. /// </summary>
  657. /// <param name="input"></param>
  658. /// <returns></returns>
  659. internal static uint ReadRawVarint32(Stream input)
  660. {
  661. int result = 0;
  662. int offset = 0;
  663. for (; offset < 32; offset += 7)
  664. {
  665. int b = input.ReadByte();
  666. if (b == -1)
  667. {
  668. throw InvalidProtocolBufferException.TruncatedMessage();
  669. }
  670. result |= (b & 0x7f) << offset;
  671. if ((b & 0x80) == 0)
  672. {
  673. return (uint) result;
  674. }
  675. }
  676. // Keep reading up to 64 bits.
  677. for (; offset < 64; offset += 7)
  678. {
  679. int b = input.ReadByte();
  680. if (b == -1)
  681. {
  682. throw InvalidProtocolBufferException.TruncatedMessage();
  683. }
  684. if ((b & 0x80) == 0)
  685. {
  686. return (uint) result;
  687. }
  688. }
  689. throw InvalidProtocolBufferException.MalformedVarint();
  690. }
  691. /// <summary>
  692. /// Reads a raw varint from the stream.
  693. /// </summary>
  694. internal ulong ReadRawVarint64()
  695. {
  696. int shift = 0;
  697. ulong result = 0;
  698. while (shift < 64)
  699. {
  700. byte b = ReadRawByte();
  701. result |= (ulong) (b & 0x7F) << shift;
  702. if ((b & 0x80) == 0)
  703. {
  704. return result;
  705. }
  706. shift += 7;
  707. }
  708. throw InvalidProtocolBufferException.MalformedVarint();
  709. }
  710. /// <summary>
  711. /// Reads a 32-bit little-endian integer from the stream.
  712. /// </summary>
  713. internal uint ReadRawLittleEndian32()
  714. {
  715. uint b1 = ReadRawByte();
  716. uint b2 = ReadRawByte();
  717. uint b3 = ReadRawByte();
  718. uint b4 = ReadRawByte();
  719. return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
  720. }
  721. /// <summary>
  722. /// Reads a 64-bit little-endian integer from the stream.
  723. /// </summary>
  724. internal ulong ReadRawLittleEndian64()
  725. {
  726. ulong b1 = ReadRawByte();
  727. ulong b2 = ReadRawByte();
  728. ulong b3 = ReadRawByte();
  729. ulong b4 = ReadRawByte();
  730. ulong b5 = ReadRawByte();
  731. ulong b6 = ReadRawByte();
  732. ulong b7 = ReadRawByte();
  733. ulong b8 = ReadRawByte();
  734. return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24)
  735. | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56);
  736. }
  737. /// <summary>
  738. /// Decode a 32-bit value with ZigZag encoding.
  739. /// </summary>
  740. /// <remarks>
  741. /// ZigZag encodes signed integers into values that can be efficiently
  742. /// encoded with varint. (Otherwise, negative values must be
  743. /// sign-extended to 64 bits to be varint encoded, thus always taking
  744. /// 10 bytes on the wire.)
  745. /// </remarks>
  746. internal static int DecodeZigZag32(uint n)
  747. {
  748. return (int)(n >> 1) ^ -(int)(n & 1);
  749. }
  750. /// <summary>
  751. /// Decode a 32-bit value with ZigZag encoding.
  752. /// </summary>
  753. /// <remarks>
  754. /// ZigZag encodes signed integers into values that can be efficiently
  755. /// encoded with varint. (Otherwise, negative values must be
  756. /// sign-extended to 64 bits to be varint encoded, thus always taking
  757. /// 10 bytes on the wire.)
  758. /// </remarks>
  759. internal static long DecodeZigZag64(ulong n)
  760. {
  761. return (long)(n >> 1) ^ -(long)(n & 1);
  762. }
  763. #endregion
  764. #region Internal reading and buffer management
  765. /// <summary>
  766. /// Sets currentLimit to (current position) + byteLimit. This is called
  767. /// when descending into a length-delimited embedded message. The previous
  768. /// limit is returned.
  769. /// </summary>
  770. /// <returns>The old limit.</returns>
  771. internal int PushLimit(int byteLimit)
  772. {
  773. if (byteLimit < 0)
  774. {
  775. throw InvalidProtocolBufferException.NegativeSize();
  776. }
  777. byteLimit += totalBytesRetired + bufferPos;
  778. int oldLimit = currentLimit;
  779. if (byteLimit > oldLimit)
  780. {
  781. throw InvalidProtocolBufferException.TruncatedMessage();
  782. }
  783. currentLimit = byteLimit;
  784. RecomputeBufferSizeAfterLimit();
  785. return oldLimit;
  786. }
  787. private void RecomputeBufferSizeAfterLimit()
  788. {
  789. bufferSize += bufferSizeAfterLimit;
  790. int bufferEnd = totalBytesRetired + bufferSize;
  791. if (bufferEnd > currentLimit)
  792. {
  793. // Limit is in current buffer.
  794. bufferSizeAfterLimit = bufferEnd - currentLimit;
  795. bufferSize -= bufferSizeAfterLimit;
  796. }
  797. else
  798. {
  799. bufferSizeAfterLimit = 0;
  800. }
  801. }
  802. /// <summary>
  803. /// Discards the current limit, returning the previous limit.
  804. /// </summary>
  805. internal void PopLimit(int oldLimit)
  806. {
  807. currentLimit = oldLimit;
  808. RecomputeBufferSizeAfterLimit();
  809. }
  810. /// <summary>
  811. /// Returns whether or not all the data before the limit has been read.
  812. /// </summary>
  813. /// <returns></returns>
  814. internal bool ReachedLimit
  815. {
  816. get
  817. {
  818. if (currentLimit == int.MaxValue)
  819. {
  820. return false;
  821. }
  822. int currentAbsolutePosition = totalBytesRetired + bufferPos;
  823. return currentAbsolutePosition >= currentLimit;
  824. }
  825. }
  826. /// <summary>
  827. /// Returns true if the stream has reached the end of the input. This is the
  828. /// case if either the end of the underlying input source has been reached or
  829. /// the stream has reached a limit created using PushLimit.
  830. /// </summary>
  831. public bool IsAtEnd
  832. {
  833. get { return bufferPos == bufferSize && !RefillBuffer(false); }
  834. }
  835. /// <summary>
  836. /// Called when buffer is empty to read more bytes from the
  837. /// input. If <paramref name="mustSucceed"/> is true, RefillBuffer() gurantees that
  838. /// either there will be at least one byte in the buffer when it returns
  839. /// or it will throw an exception. If <paramref name="mustSucceed"/> is false,
  840. /// RefillBuffer() returns false if no more bytes were available.
  841. /// </summary>
  842. /// <param name="mustSucceed"></param>
  843. /// <returns></returns>
  844. private bool RefillBuffer(bool mustSucceed)
  845. {
  846. if (bufferPos < bufferSize)
  847. {
  848. throw new InvalidOperationException("RefillBuffer() called when buffer wasn't empty.");
  849. }
  850. if (totalBytesRetired + bufferSize == currentLimit)
  851. {
  852. // Oops, we hit a limit.
  853. if (mustSucceed)
  854. {
  855. throw InvalidProtocolBufferException.TruncatedMessage();
  856. }
  857. else
  858. {
  859. return false;
  860. }
  861. }
  862. totalBytesRetired += bufferSize;
  863. bufferPos = 0;
  864. bufferSize = (input == null) ? 0 : input.Read(buffer, 0, buffer.Length);
  865. if (bufferSize < 0)
  866. {
  867. throw new InvalidOperationException("Stream.Read returned a negative count");
  868. }
  869. if (bufferSize == 0)
  870. {
  871. if (mustSucceed)
  872. {
  873. throw InvalidProtocolBufferException.TruncatedMessage();
  874. }
  875. else
  876. {
  877. return false;
  878. }
  879. }
  880. else
  881. {
  882. RecomputeBufferSizeAfterLimit();
  883. int totalBytesRead =
  884. totalBytesRetired + bufferSize + bufferSizeAfterLimit;
  885. if (totalBytesRead > sizeLimit || totalBytesRead < 0)
  886. {
  887. throw InvalidProtocolBufferException.SizeLimitExceeded();
  888. }
  889. return true;
  890. }
  891. }
  892. /// <summary>
  893. /// Read one byte from the input.
  894. /// </summary>
  895. /// <exception cref="InvalidProtocolBufferException">
  896. /// the end of the stream or the current limit was reached
  897. /// </exception>
  898. internal byte ReadRawByte()
  899. {
  900. if (bufferPos == bufferSize)
  901. {
  902. RefillBuffer(true);
  903. }
  904. return buffer[bufferPos++];
  905. }
  906. /// <summary>
  907. /// Reads a fixed size of bytes from the input.
  908. /// </summary>
  909. /// <exception cref="InvalidProtocolBufferException">
  910. /// the end of the stream or the current limit was reached
  911. /// </exception>
  912. internal byte[] ReadRawBytes(int size)
  913. {
  914. if (size < 0)
  915. {
  916. throw InvalidProtocolBufferException.NegativeSize();
  917. }
  918. if (totalBytesRetired + bufferPos + size > currentLimit)
  919. {
  920. // Read to the end of the stream (up to the current limit) anyway.
  921. // TODO(jonskeet): This is the only usage of SkipRawBytes. Do we really need to do it?
  922. SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
  923. // Then fail.
  924. throw InvalidProtocolBufferException.TruncatedMessage();
  925. }
  926. if (size <= bufferSize - bufferPos)
  927. {
  928. // We have all the bytes we need already.
  929. byte[] bytes = new byte[size];
  930. ByteArray.Copy(buffer, bufferPos, bytes, 0, size);
  931. bufferPos += size;
  932. return bytes;
  933. }
  934. else if (size < buffer.Length)
  935. {
  936. // Reading more bytes than are in the buffer, but not an excessive number
  937. // of bytes. We can safely allocate the resulting array ahead of time.
  938. // First copy what we have.
  939. byte[] bytes = new byte[size];
  940. int pos = bufferSize - bufferPos;
  941. ByteArray.Copy(buffer, bufferPos, bytes, 0, pos);
  942. bufferPos = bufferSize;
  943. // We want to use RefillBuffer() and then copy from the buffer into our
  944. // byte array rather than reading directly into our byte array because
  945. // the input may be unbuffered.
  946. RefillBuffer(true);
  947. while (size - pos > bufferSize)
  948. {
  949. Buffer.BlockCopy(buffer, 0, bytes, pos, bufferSize);
  950. pos += bufferSize;
  951. bufferPos = bufferSize;
  952. RefillBuffer(true);
  953. }
  954. ByteArray.Copy(buffer, 0, bytes, pos, size - pos);
  955. bufferPos = size - pos;
  956. return bytes;
  957. }
  958. else
  959. {
  960. // The size is very large. For security reasons, we can't allocate the
  961. // entire byte array yet. The size comes directly from the input, so a
  962. // maliciously-crafted message could provide a bogus very large size in
  963. // order to trick the app into allocating a lot of memory. We avoid this
  964. // by allocating and reading only a small chunk at a time, so that the
  965. // malicious message must actually *be* extremely large to cause
  966. // problems. Meanwhile, we limit the allowed size of a message elsewhere.
  967. // Remember the buffer markers since we'll have to copy the bytes out of
  968. // it later.
  969. int originalBufferPos = bufferPos;
  970. int originalBufferSize = bufferSize;
  971. // Mark the current buffer consumed.
  972. totalBytesRetired += bufferSize;
  973. bufferPos = 0;
  974. bufferSize = 0;
  975. // Read all the rest of the bytes we need.
  976. int sizeLeft = size - (originalBufferSize - originalBufferPos);
  977. List<byte[]> chunks = new List<byte[]>();
  978. while (sizeLeft > 0)
  979. {
  980. byte[] chunk = new byte[Math.Min(sizeLeft, buffer.Length)];
  981. int pos = 0;
  982. while (pos < chunk.Length)
  983. {
  984. int n = (input == null) ? -1 : input.Read(chunk, pos, chunk.Length - pos);
  985. if (n <= 0)
  986. {
  987. throw InvalidProtocolBufferException.TruncatedMessage();
  988. }
  989. totalBytesRetired += n;
  990. pos += n;
  991. }
  992. sizeLeft -= chunk.Length;
  993. chunks.Add(chunk);
  994. }
  995. // OK, got everything. Now concatenate it all into one buffer.
  996. byte[] bytes = new byte[size];
  997. // Start by copying the leftover bytes from this.buffer.
  998. int newPos = originalBufferSize - originalBufferPos;
  999. ByteArray.Copy(buffer, originalBufferPos, bytes, 0, newPos);
  1000. // And now all the chunks.
  1001. foreach (byte[] chunk in chunks)
  1002. {
  1003. Buffer.BlockCopy(chunk, 0, bytes, newPos, chunk.Length);
  1004. newPos += chunk.Length;
  1005. }
  1006. // Done.
  1007. return bytes;
  1008. }
  1009. }
  1010. /// <summary>
  1011. /// Reads and discards <paramref name="size"/> bytes.
  1012. /// </summary>
  1013. /// <exception cref="InvalidProtocolBufferException">the end of the stream
  1014. /// or the current limit was reached</exception>
  1015. private void SkipRawBytes(int size)
  1016. {
  1017. if (size < 0)
  1018. {
  1019. throw InvalidProtocolBufferException.NegativeSize();
  1020. }
  1021. if (totalBytesRetired + bufferPos + size > currentLimit)
  1022. {
  1023. // Read to the end of the stream anyway.
  1024. SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
  1025. // Then fail.
  1026. throw InvalidProtocolBufferException.TruncatedMessage();
  1027. }
  1028. if (size <= bufferSize - bufferPos)
  1029. {
  1030. // We have all the bytes we need already.
  1031. bufferPos += size;
  1032. }
  1033. else
  1034. {
  1035. // Skipping more bytes than are in the buffer. First skip what we have.
  1036. int pos = bufferSize - bufferPos;
  1037. // ROK 5/7/2013 Issue #54: should retire all bytes in buffer (bufferSize)
  1038. // totalBytesRetired += pos;
  1039. totalBytesRetired += bufferSize;
  1040. bufferPos = 0;
  1041. bufferSize = 0;
  1042. // Then skip directly from the InputStream for the rest.
  1043. if (pos < size)
  1044. {
  1045. if (input == null)
  1046. {
  1047. throw InvalidProtocolBufferException.TruncatedMessage();
  1048. }
  1049. SkipImpl(size - pos);
  1050. totalBytesRetired += size - pos;
  1051. }
  1052. }
  1053. }
  1054. /// <summary>
  1055. /// Abstraction of skipping to cope with streams which can't really skip.
  1056. /// </summary>
  1057. private void SkipImpl(int amountToSkip)
  1058. {
  1059. if (input.CanSeek)
  1060. {
  1061. long previousPosition = input.Position;
  1062. input.Position += amountToSkip;
  1063. if (input.Position != previousPosition + amountToSkip)
  1064. {
  1065. throw InvalidProtocolBufferException.TruncatedMessage();
  1066. }
  1067. }
  1068. else
  1069. {
  1070. byte[] skipBuffer = new byte[Math.Min(1024, amountToSkip)];
  1071. while (amountToSkip > 0)
  1072. {
  1073. int bytesRead = input.Read(skipBuffer, 0, Math.Min(skipBuffer.Length, amountToSkip));
  1074. if (bytesRead <= 0)
  1075. {
  1076. throw InvalidProtocolBufferException.TruncatedMessage();
  1077. }
  1078. amountToSkip -= bytesRead;
  1079. }
  1080. }
  1081. }
  1082. #endregion
  1083. }
  1084. }