CodedInputStream.cs 44 KB

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