CodedInputStream.cs 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189
  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. /// Attempts to peek at the next field tag.
  233. /// </summary>
  234. public bool PeekNextTag(out uint fieldTag)
  235. {
  236. if (hasNextTag)
  237. {
  238. fieldTag = nextTag;
  239. return true;
  240. }
  241. uint savedLast = lastTag;
  242. hasNextTag = ReadTag(out nextTag);
  243. lastTag = savedLast;
  244. fieldTag = nextTag;
  245. return hasNextTag;
  246. }
  247. /// <summary>
  248. /// Attempts to read a field tag, returning false if we have reached the end
  249. /// of the input data.
  250. /// </summary>
  251. /// <param name="fieldTag">The 'tag' of the field (id * 8 + wire-format)</param>
  252. /// <returns>true if the next fieldTag was read</returns>
  253. public bool ReadTag(out uint fieldTag)
  254. {
  255. if (hasNextTag)
  256. {
  257. fieldTag = nextTag;
  258. lastTag = fieldTag;
  259. hasNextTag = false;
  260. return true;
  261. }
  262. // Optimize for the incredibly common case of having at least two bytes left in the buffer,
  263. // and those two bytes being enough to get the tag. This will be true for fields up to 4095.
  264. if (bufferPos + 2 <= bufferSize)
  265. {
  266. int tmp = buffer[bufferPos++];
  267. if (tmp < 128)
  268. {
  269. fieldTag = (uint)tmp;
  270. }
  271. else
  272. {
  273. int result = tmp & 0x7f;
  274. if ((tmp = buffer[bufferPos++]) < 128)
  275. {
  276. result |= tmp << 7;
  277. fieldTag = (uint) result;
  278. }
  279. else
  280. {
  281. // Nope, rewind and go the potentially slow route.
  282. bufferPos -= 2;
  283. fieldTag = ReadRawVarint32();
  284. }
  285. }
  286. }
  287. else
  288. {
  289. if (IsAtEnd)
  290. {
  291. fieldTag = 0;
  292. lastTag = fieldTag;
  293. return false;
  294. }
  295. fieldTag = ReadRawVarint32();
  296. }
  297. lastTag = fieldTag;
  298. if (lastTag == 0)
  299. {
  300. // If we actually read zero, that's not a valid tag.
  301. throw InvalidProtocolBufferException.InvalidTag();
  302. }
  303. return true;
  304. }
  305. /// <summary>
  306. /// Consumes the data for the field with the tag we've just read.
  307. /// This should be called directly after <see cref="ReadTag"/>, when
  308. /// the caller wishes to skip an unknown field.
  309. /// </summary>
  310. public void ConsumeLastField()
  311. {
  312. if (lastTag == 0)
  313. {
  314. throw new InvalidOperationException("ConsumeLastField cannot be called at the end of a stream");
  315. }
  316. switch (WireFormat.GetTagWireType(lastTag))
  317. {
  318. case WireFormat.WireType.StartGroup:
  319. case WireFormat.WireType.EndGroup:
  320. // TODO: Work out how to skip them instead? See issue 688.
  321. throw new InvalidProtocolBufferException("Group tags not supported by proto3 C# implementation");
  322. case WireFormat.WireType.Fixed32:
  323. ReadFixed32();
  324. break;
  325. case WireFormat.WireType.Fixed64:
  326. ReadFixed64();
  327. break;
  328. case WireFormat.WireType.LengthDelimited:
  329. var length = ReadLength();
  330. SkipRawBytes(length);
  331. break;
  332. case WireFormat.WireType.Varint:
  333. ReadRawVarint32();
  334. break;
  335. }
  336. }
  337. /// <summary>
  338. /// Reads a double field from the stream.
  339. /// </summary>
  340. public double ReadDouble()
  341. {
  342. return BitConverter.Int64BitsToDouble((long) ReadRawLittleEndian64());
  343. }
  344. /// <summary>
  345. /// Reads a float field from the stream.
  346. /// </summary>
  347. public float ReadFloat()
  348. {
  349. if (BitConverter.IsLittleEndian && 4 <= bufferSize - bufferPos)
  350. {
  351. float ret = BitConverter.ToSingle(buffer, bufferPos);
  352. bufferPos += 4;
  353. return ret;
  354. }
  355. else
  356. {
  357. byte[] rawBytes = ReadRawBytes(4);
  358. if (!BitConverter.IsLittleEndian)
  359. {
  360. ByteArray.Reverse(rawBytes);
  361. }
  362. return BitConverter.ToSingle(rawBytes, 0);
  363. }
  364. }
  365. /// <summary>
  366. /// Reads a uint64 field from the stream.
  367. /// </summary>
  368. public ulong ReadUInt64()
  369. {
  370. return ReadRawVarint64();
  371. }
  372. /// <summary>
  373. /// Reads an int64 field from the stream.
  374. /// </summary>
  375. public long ReadInt64()
  376. {
  377. return (long) ReadRawVarint64();
  378. }
  379. /// <summary>
  380. /// Reads an int32 field from the stream.
  381. /// </summary>
  382. public int ReadInt32()
  383. {
  384. return (int) ReadRawVarint32();
  385. }
  386. /// <summary>
  387. /// Reads a fixed64 field from the stream.
  388. /// </summary>
  389. public ulong ReadFixed64()
  390. {
  391. return ReadRawLittleEndian64();
  392. }
  393. /// <summary>
  394. /// Reads a fixed32 field from the stream.
  395. /// </summary>
  396. public uint ReadFixed32()
  397. {
  398. return ReadRawLittleEndian32();
  399. }
  400. /// <summary>
  401. /// Reads a bool field from the stream.
  402. /// </summary>
  403. public bool ReadBool()
  404. {
  405. return ReadRawVarint32() != 0;
  406. }
  407. /// <summary>
  408. /// Reads a string field from the stream.
  409. /// </summary>
  410. public string ReadString()
  411. {
  412. int length = ReadLength();
  413. // No need to read any data for an empty string.
  414. if (length == 0)
  415. {
  416. return "";
  417. }
  418. if (length <= bufferSize - bufferPos)
  419. {
  420. // Fast path: We already have the bytes in a contiguous buffer, so
  421. // just copy directly from it.
  422. String result = CodedOutputStream.Utf8Encoding.GetString(buffer, bufferPos, length);
  423. bufferPos += length;
  424. return result;
  425. }
  426. // Slow path: Build a byte array first then copy it.
  427. return CodedOutputStream.Utf8Encoding.GetString(ReadRawBytes(length), 0, length);
  428. }
  429. /// <summary>
  430. /// Reads an embedded message field value from the stream.
  431. /// </summary>
  432. public void ReadMessage(IMessage builder)
  433. {
  434. int length = ReadLength();
  435. if (recursionDepth >= recursionLimit)
  436. {
  437. throw InvalidProtocolBufferException.RecursionLimitExceeded();
  438. }
  439. int oldLimit = PushLimit(length);
  440. ++recursionDepth;
  441. builder.MergeFrom(this);
  442. CheckLastTagWas(0);
  443. // Check that we've read exactly as much data as expected.
  444. if (!ReachedLimit)
  445. {
  446. throw InvalidProtocolBufferException.TruncatedMessage();
  447. }
  448. --recursionDepth;
  449. PopLimit(oldLimit);
  450. }
  451. /// <summary>
  452. /// Reads a bytes field value from the stream.
  453. /// </summary>
  454. public ByteString ReadBytes()
  455. {
  456. int length = ReadLength();
  457. if (length <= bufferSize - bufferPos && length > 0)
  458. {
  459. // Fast path: We already have the bytes in a contiguous buffer, so
  460. // just copy directly from it.
  461. ByteString result = ByteString.CopyFrom(buffer, bufferPos, length);
  462. bufferPos += length;
  463. return result;
  464. }
  465. else
  466. {
  467. // Slow path: Build a byte array and attach it to a new ByteString.
  468. return ByteString.AttachBytes(ReadRawBytes(length));
  469. }
  470. }
  471. /// <summary>
  472. /// Reads a uint32 field value from the stream.
  473. /// </summary>
  474. public uint ReadUInt32()
  475. {
  476. return ReadRawVarint32();
  477. }
  478. /// <summary>
  479. /// Reads an enum field value from the stream. If the enum is valid for type T,
  480. /// then the ref value is set and it returns true. Otherwise the unknown output
  481. /// value is set and this method returns false.
  482. /// </summary>
  483. public int ReadEnum()
  484. {
  485. // Currently just a pass-through, but it's nice to separate it logically from WriteInt32.
  486. return (int) ReadRawVarint32();
  487. }
  488. /// <summary>
  489. /// Reads an sfixed32 field value from the stream.
  490. /// </summary>
  491. public int ReadSFixed32()
  492. {
  493. return (int) ReadRawLittleEndian32();
  494. }
  495. /// <summary>
  496. /// Reads an sfixed64 field value from the stream.
  497. /// </summary>
  498. public long ReadSFixed64()
  499. {
  500. return (long) ReadRawLittleEndian64();
  501. }
  502. /// <summary>
  503. /// Reads an sint32 field value from the stream.
  504. /// </summary>
  505. public int ReadSInt32()
  506. {
  507. return DecodeZigZag32(ReadRawVarint32());
  508. }
  509. /// <summary>
  510. /// Reads an sint64 field value from the stream.
  511. /// </summary>
  512. public long ReadSInt64()
  513. {
  514. return DecodeZigZag64(ReadRawVarint64());
  515. }
  516. /// <summary>
  517. /// Reads a length for length-delimited data.
  518. /// </summary>
  519. /// <remarks>
  520. /// This is internally just reading a varint, but this method exists
  521. /// to make the calling code clearer.
  522. /// </remarks>
  523. public int ReadLength()
  524. {
  525. return (int) ReadRawVarint32();
  526. }
  527. /// <summary>
  528. /// Peeks at the next tag in the stream. If it matches <paramref name="tag"/>,
  529. /// the tag is consumed and the method returns <c>true</c>; otherwise, the
  530. /// stream is left in the original position and the method returns <c>false</c>.
  531. /// </summary>
  532. public bool MaybeConsumeTag(uint tag)
  533. {
  534. uint next;
  535. if (PeekNextTag(out next))
  536. {
  537. if (next == tag)
  538. {
  539. hasNextTag = false;
  540. return true;
  541. }
  542. }
  543. return false;
  544. }
  545. #endregion
  546. #region Underlying reading primitives
  547. /// <summary>
  548. /// Same code as ReadRawVarint32, but read each byte individually, checking for
  549. /// buffer overflow.
  550. /// </summary>
  551. private uint SlowReadRawVarint32()
  552. {
  553. int tmp = ReadRawByte();
  554. if (tmp < 128)
  555. {
  556. return (uint) tmp;
  557. }
  558. int result = tmp & 0x7f;
  559. if ((tmp = ReadRawByte()) < 128)
  560. {
  561. result |= tmp << 7;
  562. }
  563. else
  564. {
  565. result |= (tmp & 0x7f) << 7;
  566. if ((tmp = ReadRawByte()) < 128)
  567. {
  568. result |= tmp << 14;
  569. }
  570. else
  571. {
  572. result |= (tmp & 0x7f) << 14;
  573. if ((tmp = ReadRawByte()) < 128)
  574. {
  575. result |= tmp << 21;
  576. }
  577. else
  578. {
  579. result |= (tmp & 0x7f) << 21;
  580. result |= (tmp = ReadRawByte()) << 28;
  581. if (tmp >= 128)
  582. {
  583. // Discard upper 32 bits.
  584. for (int i = 0; i < 5; i++)
  585. {
  586. if (ReadRawByte() < 128)
  587. {
  588. return (uint) result;
  589. }
  590. }
  591. throw InvalidProtocolBufferException.MalformedVarint();
  592. }
  593. }
  594. }
  595. }
  596. return (uint) result;
  597. }
  598. /// <summary>
  599. /// Reads a raw Varint from the stream. If larger than 32 bits, discard the upper bits.
  600. /// This method is optimised for the case where we've got lots of data in the buffer.
  601. /// That means we can check the size just once, then just read directly from the buffer
  602. /// without constant rechecking of the buffer length.
  603. /// </summary>
  604. internal uint ReadRawVarint32()
  605. {
  606. if (bufferPos + 5 > bufferSize)
  607. {
  608. return SlowReadRawVarint32();
  609. }
  610. int tmp = buffer[bufferPos++];
  611. if (tmp < 128)
  612. {
  613. return (uint) tmp;
  614. }
  615. int result = tmp & 0x7f;
  616. if ((tmp = buffer[bufferPos++]) < 128)
  617. {
  618. result |= tmp << 7;
  619. }
  620. else
  621. {
  622. result |= (tmp & 0x7f) << 7;
  623. if ((tmp = buffer[bufferPos++]) < 128)
  624. {
  625. result |= tmp << 14;
  626. }
  627. else
  628. {
  629. result |= (tmp & 0x7f) << 14;
  630. if ((tmp = buffer[bufferPos++]) < 128)
  631. {
  632. result |= tmp << 21;
  633. }
  634. else
  635. {
  636. result |= (tmp & 0x7f) << 21;
  637. result |= (tmp = buffer[bufferPos++]) << 28;
  638. if (tmp >= 128)
  639. {
  640. // Discard upper 32 bits.
  641. // Note that this has to use ReadRawByte() as we only ensure we've
  642. // got at least 5 bytes at the start of the method. This lets us
  643. // use the fast path in more cases, and we rarely hit this section of code.
  644. for (int i = 0; i < 5; i++)
  645. {
  646. if (ReadRawByte() < 128)
  647. {
  648. return (uint) result;
  649. }
  650. }
  651. throw InvalidProtocolBufferException.MalformedVarint();
  652. }
  653. }
  654. }
  655. }
  656. return (uint) result;
  657. }
  658. /// <summary>
  659. /// Reads a varint from the input one byte at a time, so that it does not
  660. /// read any bytes after the end of the varint. If you simply wrapped the
  661. /// stream in a CodedInputStream and used ReadRawVarint32(Stream)
  662. /// then you would probably end up reading past the end of the varint since
  663. /// CodedInputStream buffers its input.
  664. /// </summary>
  665. /// <param name="input"></param>
  666. /// <returns></returns>
  667. internal static uint ReadRawVarint32(Stream input)
  668. {
  669. int result = 0;
  670. int offset = 0;
  671. for (; offset < 32; offset += 7)
  672. {
  673. int b = input.ReadByte();
  674. if (b == -1)
  675. {
  676. throw InvalidProtocolBufferException.TruncatedMessage();
  677. }
  678. result |= (b & 0x7f) << offset;
  679. if ((b & 0x80) == 0)
  680. {
  681. return (uint) result;
  682. }
  683. }
  684. // Keep reading up to 64 bits.
  685. for (; offset < 64; offset += 7)
  686. {
  687. int b = input.ReadByte();
  688. if (b == -1)
  689. {
  690. throw InvalidProtocolBufferException.TruncatedMessage();
  691. }
  692. if ((b & 0x80) == 0)
  693. {
  694. return (uint) result;
  695. }
  696. }
  697. throw InvalidProtocolBufferException.MalformedVarint();
  698. }
  699. /// <summary>
  700. /// Reads a raw varint from the stream.
  701. /// </summary>
  702. internal ulong ReadRawVarint64()
  703. {
  704. int shift = 0;
  705. ulong result = 0;
  706. while (shift < 64)
  707. {
  708. byte b = ReadRawByte();
  709. result |= (ulong) (b & 0x7F) << shift;
  710. if ((b & 0x80) == 0)
  711. {
  712. return result;
  713. }
  714. shift += 7;
  715. }
  716. throw InvalidProtocolBufferException.MalformedVarint();
  717. }
  718. /// <summary>
  719. /// Reads a 32-bit little-endian integer from the stream.
  720. /// </summary>
  721. internal uint ReadRawLittleEndian32()
  722. {
  723. uint b1 = ReadRawByte();
  724. uint b2 = ReadRawByte();
  725. uint b3 = ReadRawByte();
  726. uint b4 = ReadRawByte();
  727. return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
  728. }
  729. /// <summary>
  730. /// Reads a 64-bit little-endian integer from the stream.
  731. /// </summary>
  732. internal ulong ReadRawLittleEndian64()
  733. {
  734. ulong b1 = ReadRawByte();
  735. ulong b2 = ReadRawByte();
  736. ulong b3 = ReadRawByte();
  737. ulong b4 = ReadRawByte();
  738. ulong b5 = ReadRawByte();
  739. ulong b6 = ReadRawByte();
  740. ulong b7 = ReadRawByte();
  741. ulong b8 = ReadRawByte();
  742. return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24)
  743. | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56);
  744. }
  745. /// <summary>
  746. /// Decode a 32-bit value with ZigZag encoding.
  747. /// </summary>
  748. /// <remarks>
  749. /// ZigZag encodes signed integers into values that can be efficiently
  750. /// encoded with varint. (Otherwise, negative values must be
  751. /// sign-extended to 64 bits to be varint encoded, thus always taking
  752. /// 10 bytes on the wire.)
  753. /// </remarks>
  754. internal static int DecodeZigZag32(uint n)
  755. {
  756. return (int)(n >> 1) ^ -(int)(n & 1);
  757. }
  758. /// <summary>
  759. /// Decode a 32-bit value with ZigZag encoding.
  760. /// </summary>
  761. /// <remarks>
  762. /// ZigZag encodes signed integers into values that can be efficiently
  763. /// encoded with varint. (Otherwise, negative values must be
  764. /// sign-extended to 64 bits to be varint encoded, thus always taking
  765. /// 10 bytes on the wire.)
  766. /// </remarks>
  767. internal static long DecodeZigZag64(ulong n)
  768. {
  769. return (long)(n >> 1) ^ -(long)(n & 1);
  770. }
  771. #endregion
  772. #region Internal reading and buffer management
  773. /// <summary>
  774. /// Sets currentLimit to (current position) + byteLimit. This is called
  775. /// when descending into a length-delimited embedded message. The previous
  776. /// limit is returned.
  777. /// </summary>
  778. /// <returns>The old limit.</returns>
  779. internal int PushLimit(int byteLimit)
  780. {
  781. if (byteLimit < 0)
  782. {
  783. throw InvalidProtocolBufferException.NegativeSize();
  784. }
  785. byteLimit += totalBytesRetired + bufferPos;
  786. int oldLimit = currentLimit;
  787. if (byteLimit > oldLimit)
  788. {
  789. throw InvalidProtocolBufferException.TruncatedMessage();
  790. }
  791. currentLimit = byteLimit;
  792. RecomputeBufferSizeAfterLimit();
  793. return oldLimit;
  794. }
  795. private void RecomputeBufferSizeAfterLimit()
  796. {
  797. bufferSize += bufferSizeAfterLimit;
  798. int bufferEnd = totalBytesRetired + bufferSize;
  799. if (bufferEnd > currentLimit)
  800. {
  801. // Limit is in current buffer.
  802. bufferSizeAfterLimit = bufferEnd - currentLimit;
  803. bufferSize -= bufferSizeAfterLimit;
  804. }
  805. else
  806. {
  807. bufferSizeAfterLimit = 0;
  808. }
  809. }
  810. /// <summary>
  811. /// Discards the current limit, returning the previous limit.
  812. /// </summary>
  813. internal void PopLimit(int oldLimit)
  814. {
  815. currentLimit = oldLimit;
  816. RecomputeBufferSizeAfterLimit();
  817. }
  818. /// <summary>
  819. /// Returns whether or not all the data before the limit has been read.
  820. /// </summary>
  821. /// <returns></returns>
  822. internal bool ReachedLimit
  823. {
  824. get
  825. {
  826. if (currentLimit == int.MaxValue)
  827. {
  828. return false;
  829. }
  830. int currentAbsolutePosition = totalBytesRetired + bufferPos;
  831. return currentAbsolutePosition >= currentLimit;
  832. }
  833. }
  834. /// <summary>
  835. /// Returns true if the stream has reached the end of the input. This is the
  836. /// case if either the end of the underlying input source has been reached or
  837. /// the stream has reached a limit created using PushLimit.
  838. /// </summary>
  839. public bool IsAtEnd
  840. {
  841. get { return bufferPos == bufferSize && !RefillBuffer(false); }
  842. }
  843. /// <summary>
  844. /// Called when buffer is empty to read more bytes from the
  845. /// input. If <paramref name="mustSucceed"/> is true, RefillBuffer() gurantees that
  846. /// either there will be at least one byte in the buffer when it returns
  847. /// or it will throw an exception. If <paramref name="mustSucceed"/> is false,
  848. /// RefillBuffer() returns false if no more bytes were available.
  849. /// </summary>
  850. /// <param name="mustSucceed"></param>
  851. /// <returns></returns>
  852. private bool RefillBuffer(bool mustSucceed)
  853. {
  854. if (bufferPos < bufferSize)
  855. {
  856. throw new InvalidOperationException("RefillBuffer() called when buffer wasn't empty.");
  857. }
  858. if (totalBytesRetired + bufferSize == currentLimit)
  859. {
  860. // Oops, we hit a limit.
  861. if (mustSucceed)
  862. {
  863. throw InvalidProtocolBufferException.TruncatedMessage();
  864. }
  865. else
  866. {
  867. return false;
  868. }
  869. }
  870. totalBytesRetired += bufferSize;
  871. bufferPos = 0;
  872. bufferSize = (input == null) ? 0 : input.Read(buffer, 0, buffer.Length);
  873. if (bufferSize < 0)
  874. {
  875. throw new InvalidOperationException("Stream.Read returned a negative count");
  876. }
  877. if (bufferSize == 0)
  878. {
  879. if (mustSucceed)
  880. {
  881. throw InvalidProtocolBufferException.TruncatedMessage();
  882. }
  883. else
  884. {
  885. return false;
  886. }
  887. }
  888. else
  889. {
  890. RecomputeBufferSizeAfterLimit();
  891. int totalBytesRead =
  892. totalBytesRetired + bufferSize + bufferSizeAfterLimit;
  893. if (totalBytesRead > sizeLimit || totalBytesRead < 0)
  894. {
  895. throw InvalidProtocolBufferException.SizeLimitExceeded();
  896. }
  897. return true;
  898. }
  899. }
  900. /// <summary>
  901. /// Read one byte from the input.
  902. /// </summary>
  903. /// <exception cref="InvalidProtocolBufferException">
  904. /// the end of the stream or the current limit was reached
  905. /// </exception>
  906. internal byte ReadRawByte()
  907. {
  908. if (bufferPos == bufferSize)
  909. {
  910. RefillBuffer(true);
  911. }
  912. return buffer[bufferPos++];
  913. }
  914. /// <summary>
  915. /// Reads a fixed size of bytes from the input.
  916. /// </summary>
  917. /// <exception cref="InvalidProtocolBufferException">
  918. /// the end of the stream or the current limit was reached
  919. /// </exception>
  920. internal byte[] ReadRawBytes(int size)
  921. {
  922. if (size < 0)
  923. {
  924. throw InvalidProtocolBufferException.NegativeSize();
  925. }
  926. if (totalBytesRetired + bufferPos + size > currentLimit)
  927. {
  928. // Read to the end of the stream (up to the current limit) anyway.
  929. // TODO(jonskeet): This is the only usage of SkipRawBytes. Do we really need to do it?
  930. SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
  931. // Then fail.
  932. throw InvalidProtocolBufferException.TruncatedMessage();
  933. }
  934. if (size <= bufferSize - bufferPos)
  935. {
  936. // We have all the bytes we need already.
  937. byte[] bytes = new byte[size];
  938. ByteArray.Copy(buffer, bufferPos, bytes, 0, size);
  939. bufferPos += size;
  940. return bytes;
  941. }
  942. else if (size < buffer.Length)
  943. {
  944. // Reading more bytes than are in the buffer, but not an excessive number
  945. // of bytes. We can safely allocate the resulting array ahead of time.
  946. // First copy what we have.
  947. byte[] bytes = new byte[size];
  948. int pos = bufferSize - bufferPos;
  949. ByteArray.Copy(buffer, bufferPos, bytes, 0, pos);
  950. bufferPos = bufferSize;
  951. // We want to use RefillBuffer() and then copy from the buffer into our
  952. // byte array rather than reading directly into our byte array because
  953. // the input may be unbuffered.
  954. RefillBuffer(true);
  955. while (size - pos > bufferSize)
  956. {
  957. Buffer.BlockCopy(buffer, 0, bytes, pos, bufferSize);
  958. pos += bufferSize;
  959. bufferPos = bufferSize;
  960. RefillBuffer(true);
  961. }
  962. ByteArray.Copy(buffer, 0, bytes, pos, size - pos);
  963. bufferPos = size - pos;
  964. return bytes;
  965. }
  966. else
  967. {
  968. // The size is very large. For security reasons, we can't allocate the
  969. // entire byte array yet. The size comes directly from the input, so a
  970. // maliciously-crafted message could provide a bogus very large size in
  971. // order to trick the app into allocating a lot of memory. We avoid this
  972. // by allocating and reading only a small chunk at a time, so that the
  973. // malicious message must actually *be* extremely large to cause
  974. // problems. Meanwhile, we limit the allowed size of a message elsewhere.
  975. // Remember the buffer markers since we'll have to copy the bytes out of
  976. // it later.
  977. int originalBufferPos = bufferPos;
  978. int originalBufferSize = bufferSize;
  979. // Mark the current buffer consumed.
  980. totalBytesRetired += bufferSize;
  981. bufferPos = 0;
  982. bufferSize = 0;
  983. // Read all the rest of the bytes we need.
  984. int sizeLeft = size - (originalBufferSize - originalBufferPos);
  985. List<byte[]> chunks = new List<byte[]>();
  986. while (sizeLeft > 0)
  987. {
  988. byte[] chunk = new byte[Math.Min(sizeLeft, buffer.Length)];
  989. int pos = 0;
  990. while (pos < chunk.Length)
  991. {
  992. int n = (input == null) ? -1 : input.Read(chunk, pos, chunk.Length - pos);
  993. if (n <= 0)
  994. {
  995. throw InvalidProtocolBufferException.TruncatedMessage();
  996. }
  997. totalBytesRetired += n;
  998. pos += n;
  999. }
  1000. sizeLeft -= chunk.Length;
  1001. chunks.Add(chunk);
  1002. }
  1003. // OK, got everything. Now concatenate it all into one buffer.
  1004. byte[] bytes = new byte[size];
  1005. // Start by copying the leftover bytes from this.buffer.
  1006. int newPos = originalBufferSize - originalBufferPos;
  1007. ByteArray.Copy(buffer, originalBufferPos, bytes, 0, newPos);
  1008. // And now all the chunks.
  1009. foreach (byte[] chunk in chunks)
  1010. {
  1011. Buffer.BlockCopy(chunk, 0, bytes, newPos, chunk.Length);
  1012. newPos += chunk.Length;
  1013. }
  1014. // Done.
  1015. return bytes;
  1016. }
  1017. }
  1018. /// <summary>
  1019. /// Reads and discards <paramref name="size"/> bytes.
  1020. /// </summary>
  1021. /// <exception cref="InvalidProtocolBufferException">the end of the stream
  1022. /// or the current limit was reached</exception>
  1023. private void SkipRawBytes(int size)
  1024. {
  1025. if (size < 0)
  1026. {
  1027. throw InvalidProtocolBufferException.NegativeSize();
  1028. }
  1029. if (totalBytesRetired + bufferPos + size > currentLimit)
  1030. {
  1031. // Read to the end of the stream anyway.
  1032. SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
  1033. // Then fail.
  1034. throw InvalidProtocolBufferException.TruncatedMessage();
  1035. }
  1036. if (size <= bufferSize - bufferPos)
  1037. {
  1038. // We have all the bytes we need already.
  1039. bufferPos += size;
  1040. }
  1041. else
  1042. {
  1043. // Skipping more bytes than are in the buffer. First skip what we have.
  1044. int pos = bufferSize - bufferPos;
  1045. // ROK 5/7/2013 Issue #54: should retire all bytes in buffer (bufferSize)
  1046. // totalBytesRetired += pos;
  1047. totalBytesRetired += bufferSize;
  1048. bufferPos = 0;
  1049. bufferSize = 0;
  1050. // Then skip directly from the InputStream for the rest.
  1051. if (pos < size)
  1052. {
  1053. if (input == null)
  1054. {
  1055. throw InvalidProtocolBufferException.TruncatedMessage();
  1056. }
  1057. SkipImpl(size - pos);
  1058. totalBytesRetired += size - pos;
  1059. }
  1060. }
  1061. }
  1062. /// <summary>
  1063. /// Abstraction of skipping to cope with streams which can't really skip.
  1064. /// </summary>
  1065. private void SkipImpl(int amountToSkip)
  1066. {
  1067. if (input.CanSeek)
  1068. {
  1069. long previousPosition = input.Position;
  1070. input.Position += amountToSkip;
  1071. if (input.Position != previousPosition + amountToSkip)
  1072. {
  1073. throw InvalidProtocolBufferException.TruncatedMessage();
  1074. }
  1075. }
  1076. else
  1077. {
  1078. byte[] skipBuffer = new byte[Math.Min(1024, amountToSkip)];
  1079. while (amountToSkip > 0)
  1080. {
  1081. int bytesRead = input.Read(skipBuffer, 0, Math.Min(skipBuffer.Length, amountToSkip));
  1082. if (bytesRead <= 0)
  1083. {
  1084. throw InvalidProtocolBufferException.TruncatedMessage();
  1085. }
  1086. amountToSkip -= bytesRead;
  1087. }
  1088. }
  1089. }
  1090. #endregion
  1091. }
  1092. }