CodedInputStream.cs 43 KB

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