1ffe3c632Sopenharmony_ci<?php 2ffe3c632Sopenharmony_ci 3ffe3c632Sopenharmony_ci// Protocol Buffers - Google's data interchange format 4ffe3c632Sopenharmony_ci// Copyright 2008 Google Inc. All rights reserved. 5ffe3c632Sopenharmony_ci// https://developers.google.com/protocol-buffers/ 6ffe3c632Sopenharmony_ci// 7ffe3c632Sopenharmony_ci// Redistribution and use in source and binary forms, with or without 8ffe3c632Sopenharmony_ci// modification, are permitted provided that the following conditions are 9ffe3c632Sopenharmony_ci// met: 10ffe3c632Sopenharmony_ci// 11ffe3c632Sopenharmony_ci// * Redistributions of source code must retain the above copyright 12ffe3c632Sopenharmony_ci// notice, this list of conditions and the following disclaimer. 13ffe3c632Sopenharmony_ci// * Redistributions in binary form must reproduce the above 14ffe3c632Sopenharmony_ci// copyright notice, this list of conditions and the following disclaimer 15ffe3c632Sopenharmony_ci// in the documentation and/or other materials provided with the 16ffe3c632Sopenharmony_ci// distribution. 17ffe3c632Sopenharmony_ci// * Neither the name of Google Inc. nor the names of its 18ffe3c632Sopenharmony_ci// contributors may be used to endorse or promote products derived from 19ffe3c632Sopenharmony_ci// this software without specific prior written permission. 20ffe3c632Sopenharmony_ci// 21ffe3c632Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22ffe3c632Sopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23ffe3c632Sopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24ffe3c632Sopenharmony_ci// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25ffe3c632Sopenharmony_ci// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26ffe3c632Sopenharmony_ci// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27ffe3c632Sopenharmony_ci// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28ffe3c632Sopenharmony_ci// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29ffe3c632Sopenharmony_ci// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30ffe3c632Sopenharmony_ci// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31ffe3c632Sopenharmony_ci// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32ffe3c632Sopenharmony_ci 33ffe3c632Sopenharmony_cinamespace Google\Protobuf\Internal; 34ffe3c632Sopenharmony_ci 35ffe3c632Sopenharmony_ciuse Google\Protobuf\Internal\Uint64; 36ffe3c632Sopenharmony_ci 37ffe3c632Sopenharmony_ciclass CodedInputStream 38ffe3c632Sopenharmony_ci{ 39ffe3c632Sopenharmony_ci 40ffe3c632Sopenharmony_ci private $buffer; 41ffe3c632Sopenharmony_ci private $buffer_size_after_limit; 42ffe3c632Sopenharmony_ci private $buffer_end; 43ffe3c632Sopenharmony_ci private $current; 44ffe3c632Sopenharmony_ci private $current_limit; 45ffe3c632Sopenharmony_ci private $legitimate_message_end; 46ffe3c632Sopenharmony_ci private $recursion_budget; 47ffe3c632Sopenharmony_ci private $recursion_limit; 48ffe3c632Sopenharmony_ci private $total_bytes_limit; 49ffe3c632Sopenharmony_ci private $total_bytes_read; 50ffe3c632Sopenharmony_ci 51ffe3c632Sopenharmony_ci const MAX_VARINT_BYTES = 10; 52ffe3c632Sopenharmony_ci const DEFAULT_RECURSION_LIMIT = 100; 53ffe3c632Sopenharmony_ci const DEFAULT_TOTAL_BYTES_LIMIT = 33554432; // 32 << 20, 32MB 54ffe3c632Sopenharmony_ci 55ffe3c632Sopenharmony_ci public function __construct($buffer) 56ffe3c632Sopenharmony_ci { 57ffe3c632Sopenharmony_ci $start = 0; 58ffe3c632Sopenharmony_ci $end = strlen($buffer); 59ffe3c632Sopenharmony_ci $this->buffer = $buffer; 60ffe3c632Sopenharmony_ci $this->buffer_size_after_limit = 0; 61ffe3c632Sopenharmony_ci $this->buffer_end = $end; 62ffe3c632Sopenharmony_ci $this->current = $start; 63ffe3c632Sopenharmony_ci $this->current_limit = $end; 64ffe3c632Sopenharmony_ci $this->legitimate_message_end = false; 65ffe3c632Sopenharmony_ci $this->recursion_budget = self::DEFAULT_RECURSION_LIMIT; 66ffe3c632Sopenharmony_ci $this->recursion_limit = self::DEFAULT_RECURSION_LIMIT; 67ffe3c632Sopenharmony_ci $this->total_bytes_limit = self::DEFAULT_TOTAL_BYTES_LIMIT; 68ffe3c632Sopenharmony_ci $this->total_bytes_read = $end - $start; 69ffe3c632Sopenharmony_ci } 70ffe3c632Sopenharmony_ci 71ffe3c632Sopenharmony_ci private function advance($amount) 72ffe3c632Sopenharmony_ci { 73ffe3c632Sopenharmony_ci $this->current += $amount; 74ffe3c632Sopenharmony_ci } 75ffe3c632Sopenharmony_ci 76ffe3c632Sopenharmony_ci public function bufferSize() 77ffe3c632Sopenharmony_ci { 78ffe3c632Sopenharmony_ci return $this->buffer_end - $this->current; 79ffe3c632Sopenharmony_ci } 80ffe3c632Sopenharmony_ci 81ffe3c632Sopenharmony_ci public function current() 82ffe3c632Sopenharmony_ci { 83ffe3c632Sopenharmony_ci return $this->total_bytes_read - 84ffe3c632Sopenharmony_ci ($this->buffer_end - $this->current + 85ffe3c632Sopenharmony_ci $this->buffer_size_after_limit); 86ffe3c632Sopenharmony_ci } 87ffe3c632Sopenharmony_ci 88ffe3c632Sopenharmony_ci public function substr($start, $end) 89ffe3c632Sopenharmony_ci { 90ffe3c632Sopenharmony_ci return substr($this->buffer, $start, $end - $start); 91ffe3c632Sopenharmony_ci } 92ffe3c632Sopenharmony_ci 93ffe3c632Sopenharmony_ci private function recomputeBufferLimits() 94ffe3c632Sopenharmony_ci { 95ffe3c632Sopenharmony_ci $this->buffer_end += $this->buffer_size_after_limit; 96ffe3c632Sopenharmony_ci $closest_limit = min($this->current_limit, $this->total_bytes_limit); 97ffe3c632Sopenharmony_ci if ($closest_limit < $this->total_bytes_read) { 98ffe3c632Sopenharmony_ci // The limit position is in the current buffer. We must adjust the 99ffe3c632Sopenharmony_ci // buffer size accordingly. 100ffe3c632Sopenharmony_ci $this->buffer_size_after_limit = $this->total_bytes_read - 101ffe3c632Sopenharmony_ci $closest_limit; 102ffe3c632Sopenharmony_ci $this->buffer_end -= $this->buffer_size_after_limit; 103ffe3c632Sopenharmony_ci } else { 104ffe3c632Sopenharmony_ci $this->buffer_size_after_limit = 0; 105ffe3c632Sopenharmony_ci } 106ffe3c632Sopenharmony_ci } 107ffe3c632Sopenharmony_ci 108ffe3c632Sopenharmony_ci private function consumedEntireMessage() 109ffe3c632Sopenharmony_ci { 110ffe3c632Sopenharmony_ci return $this->legitimate_message_end; 111ffe3c632Sopenharmony_ci } 112ffe3c632Sopenharmony_ci 113ffe3c632Sopenharmony_ci /** 114ffe3c632Sopenharmony_ci * Read uint32 into $var. Advance buffer with consumed bytes. If the 115ffe3c632Sopenharmony_ci * contained varint is larger than 32 bits, discard the high order bits. 116ffe3c632Sopenharmony_ci * @param $var. 117ffe3c632Sopenharmony_ci */ 118ffe3c632Sopenharmony_ci public function readVarint32(&$var) 119ffe3c632Sopenharmony_ci { 120ffe3c632Sopenharmony_ci if (!$this->readVarint64($var)) { 121ffe3c632Sopenharmony_ci return false; 122ffe3c632Sopenharmony_ci } 123ffe3c632Sopenharmony_ci 124ffe3c632Sopenharmony_ci if (PHP_INT_SIZE == 4) { 125ffe3c632Sopenharmony_ci $var = bcmod($var, 4294967296); 126ffe3c632Sopenharmony_ci } else { 127ffe3c632Sopenharmony_ci $var &= 0xFFFFFFFF; 128ffe3c632Sopenharmony_ci } 129ffe3c632Sopenharmony_ci 130ffe3c632Sopenharmony_ci // Convert large uint32 to int32. 131ffe3c632Sopenharmony_ci if ($var > 0x7FFFFFFF) { 132ffe3c632Sopenharmony_ci if (PHP_INT_SIZE === 8) { 133ffe3c632Sopenharmony_ci $var = $var | (0xFFFFFFFF << 32); 134ffe3c632Sopenharmony_ci } else { 135ffe3c632Sopenharmony_ci $var = bcsub($var, 4294967296); 136ffe3c632Sopenharmony_ci } 137ffe3c632Sopenharmony_ci } 138ffe3c632Sopenharmony_ci 139ffe3c632Sopenharmony_ci $var = intval($var); 140ffe3c632Sopenharmony_ci return true; 141ffe3c632Sopenharmony_ci } 142ffe3c632Sopenharmony_ci 143ffe3c632Sopenharmony_ci /** 144ffe3c632Sopenharmony_ci * Read Uint64 into $var. Advance buffer with consumed bytes. 145ffe3c632Sopenharmony_ci * @param $var. 146ffe3c632Sopenharmony_ci */ 147ffe3c632Sopenharmony_ci public function readVarint64(&$var) 148ffe3c632Sopenharmony_ci { 149ffe3c632Sopenharmony_ci $count = 0; 150ffe3c632Sopenharmony_ci 151ffe3c632Sopenharmony_ci if (PHP_INT_SIZE == 4) { 152ffe3c632Sopenharmony_ci $high = 0; 153ffe3c632Sopenharmony_ci $low = 0; 154ffe3c632Sopenharmony_ci $b = 0; 155ffe3c632Sopenharmony_ci 156ffe3c632Sopenharmony_ci do { 157ffe3c632Sopenharmony_ci if ($this->current === $this->buffer_end) { 158ffe3c632Sopenharmony_ci return false; 159ffe3c632Sopenharmony_ci } 160ffe3c632Sopenharmony_ci if ($count === self::MAX_VARINT_BYTES) { 161ffe3c632Sopenharmony_ci return false; 162ffe3c632Sopenharmony_ci } 163ffe3c632Sopenharmony_ci $b = ord($this->buffer[$this->current]); 164ffe3c632Sopenharmony_ci $bits = 7 * $count; 165ffe3c632Sopenharmony_ci if ($bits >= 32) { 166ffe3c632Sopenharmony_ci $high |= (($b & 0x7F) << ($bits - 32)); 167ffe3c632Sopenharmony_ci } else if ($bits > 25){ 168ffe3c632Sopenharmony_ci // $bits is 28 in this case. 169ffe3c632Sopenharmony_ci $low |= (($b & 0x7F) << 28); 170ffe3c632Sopenharmony_ci $high = ($b & 0x7F) >> 4; 171ffe3c632Sopenharmony_ci } else { 172ffe3c632Sopenharmony_ci $low |= (($b & 0x7F) << $bits); 173ffe3c632Sopenharmony_ci } 174ffe3c632Sopenharmony_ci 175ffe3c632Sopenharmony_ci $this->advance(1); 176ffe3c632Sopenharmony_ci $count += 1; 177ffe3c632Sopenharmony_ci } while ($b & 0x80); 178ffe3c632Sopenharmony_ci 179ffe3c632Sopenharmony_ci $var = GPBUtil::combineInt32ToInt64($high, $low); 180ffe3c632Sopenharmony_ci if (bccomp($var, 0) < 0) { 181ffe3c632Sopenharmony_ci $var = bcadd($var, "18446744073709551616"); 182ffe3c632Sopenharmony_ci } 183ffe3c632Sopenharmony_ci } else { 184ffe3c632Sopenharmony_ci $result = 0; 185ffe3c632Sopenharmony_ci $shift = 0; 186ffe3c632Sopenharmony_ci 187ffe3c632Sopenharmony_ci do { 188ffe3c632Sopenharmony_ci if ($this->current === $this->buffer_end) { 189ffe3c632Sopenharmony_ci return false; 190ffe3c632Sopenharmony_ci } 191ffe3c632Sopenharmony_ci if ($count === self::MAX_VARINT_BYTES) { 192ffe3c632Sopenharmony_ci return false; 193ffe3c632Sopenharmony_ci } 194ffe3c632Sopenharmony_ci 195ffe3c632Sopenharmony_ci $byte = ord($this->buffer[$this->current]); 196ffe3c632Sopenharmony_ci $result |= ($byte & 0x7f) << $shift; 197ffe3c632Sopenharmony_ci $shift += 7; 198ffe3c632Sopenharmony_ci $this->advance(1); 199ffe3c632Sopenharmony_ci $count += 1; 200ffe3c632Sopenharmony_ci } while ($byte > 0x7f); 201ffe3c632Sopenharmony_ci 202ffe3c632Sopenharmony_ci $var = $result; 203ffe3c632Sopenharmony_ci } 204ffe3c632Sopenharmony_ci 205ffe3c632Sopenharmony_ci return true; 206ffe3c632Sopenharmony_ci } 207ffe3c632Sopenharmony_ci 208ffe3c632Sopenharmony_ci /** 209ffe3c632Sopenharmony_ci * Read int into $var. If the result is larger than the largest integer, $var 210ffe3c632Sopenharmony_ci * will be -1. Advance buffer with consumed bytes. 211ffe3c632Sopenharmony_ci * @param $var. 212ffe3c632Sopenharmony_ci */ 213ffe3c632Sopenharmony_ci public function readVarintSizeAsInt(&$var) 214ffe3c632Sopenharmony_ci { 215ffe3c632Sopenharmony_ci if (!$this->readVarint64($var)) { 216ffe3c632Sopenharmony_ci return false; 217ffe3c632Sopenharmony_ci } 218ffe3c632Sopenharmony_ci $var = (int)$var; 219ffe3c632Sopenharmony_ci return true; 220ffe3c632Sopenharmony_ci } 221ffe3c632Sopenharmony_ci 222ffe3c632Sopenharmony_ci /** 223ffe3c632Sopenharmony_ci * Read 32-bit unsigned integer to $var. If the buffer has less than 4 bytes, 224ffe3c632Sopenharmony_ci * return false. Advance buffer with consumed bytes. 225ffe3c632Sopenharmony_ci * @param $var. 226ffe3c632Sopenharmony_ci */ 227ffe3c632Sopenharmony_ci public function readLittleEndian32(&$var) 228ffe3c632Sopenharmony_ci { 229ffe3c632Sopenharmony_ci $data = null; 230ffe3c632Sopenharmony_ci if (!$this->readRaw(4, $data)) { 231ffe3c632Sopenharmony_ci return false; 232ffe3c632Sopenharmony_ci } 233ffe3c632Sopenharmony_ci $var = unpack('V', $data); 234ffe3c632Sopenharmony_ci $var = $var[1]; 235ffe3c632Sopenharmony_ci return true; 236ffe3c632Sopenharmony_ci } 237ffe3c632Sopenharmony_ci 238ffe3c632Sopenharmony_ci /** 239ffe3c632Sopenharmony_ci * Read 64-bit unsigned integer to $var. If the buffer has less than 8 bytes, 240ffe3c632Sopenharmony_ci * return false. Advance buffer with consumed bytes. 241ffe3c632Sopenharmony_ci * @param $var. 242ffe3c632Sopenharmony_ci */ 243ffe3c632Sopenharmony_ci public function readLittleEndian64(&$var) 244ffe3c632Sopenharmony_ci { 245ffe3c632Sopenharmony_ci $data = null; 246ffe3c632Sopenharmony_ci if (!$this->readRaw(4, $data)) { 247ffe3c632Sopenharmony_ci return false; 248ffe3c632Sopenharmony_ci } 249ffe3c632Sopenharmony_ci $low = unpack('V', $data)[1]; 250ffe3c632Sopenharmony_ci if (!$this->readRaw(4, $data)) { 251ffe3c632Sopenharmony_ci return false; 252ffe3c632Sopenharmony_ci } 253ffe3c632Sopenharmony_ci $high = unpack('V', $data)[1]; 254ffe3c632Sopenharmony_ci if (PHP_INT_SIZE == 4) { 255ffe3c632Sopenharmony_ci $var = GPBUtil::combineInt32ToInt64($high, $low); 256ffe3c632Sopenharmony_ci } else { 257ffe3c632Sopenharmony_ci $var = ($high << 32) | $low; 258ffe3c632Sopenharmony_ci } 259ffe3c632Sopenharmony_ci return true; 260ffe3c632Sopenharmony_ci } 261ffe3c632Sopenharmony_ci 262ffe3c632Sopenharmony_ci /** 263ffe3c632Sopenharmony_ci * Read tag into $var. Advance buffer with consumed bytes. 264ffe3c632Sopenharmony_ci * @param $var. 265ffe3c632Sopenharmony_ci */ 266ffe3c632Sopenharmony_ci public function readTag() 267ffe3c632Sopenharmony_ci { 268ffe3c632Sopenharmony_ci if ($this->current === $this->buffer_end) { 269ffe3c632Sopenharmony_ci // Make sure that it failed due to EOF, not because we hit 270ffe3c632Sopenharmony_ci // total_bytes_limit, which, unlike normal limits, is not a valid 271ffe3c632Sopenharmony_ci // place to end a message. 272ffe3c632Sopenharmony_ci $current_position = $this->total_bytes_read - 273ffe3c632Sopenharmony_ci $this->buffer_size_after_limit; 274ffe3c632Sopenharmony_ci if ($current_position >= $this->total_bytes_limit) { 275ffe3c632Sopenharmony_ci // Hit total_bytes_limit_. But if we also hit the normal limit, 276ffe3c632Sopenharmony_ci // we're still OK. 277ffe3c632Sopenharmony_ci $this->legitimate_message_end = 278ffe3c632Sopenharmony_ci ($this->current_limit === $this->total_bytes_limit); 279ffe3c632Sopenharmony_ci } else { 280ffe3c632Sopenharmony_ci $this->legitimate_message_end = true; 281ffe3c632Sopenharmony_ci } 282ffe3c632Sopenharmony_ci return 0; 283ffe3c632Sopenharmony_ci } 284ffe3c632Sopenharmony_ci 285ffe3c632Sopenharmony_ci $result = 0; 286ffe3c632Sopenharmony_ci // The largest tag is 2^29 - 1, which can be represented by int32. 287ffe3c632Sopenharmony_ci $success = $this->readVarint32($result); 288ffe3c632Sopenharmony_ci if ($success) { 289ffe3c632Sopenharmony_ci return $result; 290ffe3c632Sopenharmony_ci } else { 291ffe3c632Sopenharmony_ci return 0; 292ffe3c632Sopenharmony_ci } 293ffe3c632Sopenharmony_ci } 294ffe3c632Sopenharmony_ci 295ffe3c632Sopenharmony_ci public function readRaw($size, &$buffer) 296ffe3c632Sopenharmony_ci { 297ffe3c632Sopenharmony_ci $current_buffer_size = 0; 298ffe3c632Sopenharmony_ci if ($this->bufferSize() < $size) { 299ffe3c632Sopenharmony_ci return false; 300ffe3c632Sopenharmony_ci } 301ffe3c632Sopenharmony_ci 302ffe3c632Sopenharmony_ci if ($size === 0) { 303ffe3c632Sopenharmony_ci $buffer = ""; 304ffe3c632Sopenharmony_ci } else { 305ffe3c632Sopenharmony_ci $buffer = substr($this->buffer, $this->current, $size); 306ffe3c632Sopenharmony_ci $this->advance($size); 307ffe3c632Sopenharmony_ci } 308ffe3c632Sopenharmony_ci 309ffe3c632Sopenharmony_ci return true; 310ffe3c632Sopenharmony_ci } 311ffe3c632Sopenharmony_ci 312ffe3c632Sopenharmony_ci /* Places a limit on the number of bytes that the stream may read, starting 313ffe3c632Sopenharmony_ci * from the current position. Once the stream hits this limit, it will act 314ffe3c632Sopenharmony_ci * like the end of the input has been reached until popLimit() is called. 315ffe3c632Sopenharmony_ci * 316ffe3c632Sopenharmony_ci * As the names imply, the stream conceptually has a stack of limits. The 317ffe3c632Sopenharmony_ci * shortest limit on the stack is always enforced, even if it is not the top 318ffe3c632Sopenharmony_ci * limit. 319ffe3c632Sopenharmony_ci * 320ffe3c632Sopenharmony_ci * The value returned by pushLimit() is opaque to the caller, and must be 321ffe3c632Sopenharmony_ci * passed unchanged to the corresponding call to popLimit(). 322ffe3c632Sopenharmony_ci * 323ffe3c632Sopenharmony_ci * @param integer $byte_limit 324ffe3c632Sopenharmony_ci * @throws \Exception Fail to push limit. 325ffe3c632Sopenharmony_ci */ 326ffe3c632Sopenharmony_ci public function pushLimit($byte_limit) 327ffe3c632Sopenharmony_ci { 328ffe3c632Sopenharmony_ci // Current position relative to the beginning of the stream. 329ffe3c632Sopenharmony_ci $current_position = $this->current(); 330ffe3c632Sopenharmony_ci $old_limit = $this->current_limit; 331ffe3c632Sopenharmony_ci 332ffe3c632Sopenharmony_ci // security: byte_limit is possibly evil, so check for negative values 333ffe3c632Sopenharmony_ci // and overflow. 334ffe3c632Sopenharmony_ci if ($byte_limit >= 0 && 335ffe3c632Sopenharmony_ci $byte_limit <= PHP_INT_MAX - $current_position && 336ffe3c632Sopenharmony_ci $byte_limit <= $this->current_limit - $current_position) { 337ffe3c632Sopenharmony_ci $this->current_limit = $current_position + $byte_limit; 338ffe3c632Sopenharmony_ci $this->recomputeBufferLimits(); 339ffe3c632Sopenharmony_ci } else { 340ffe3c632Sopenharmony_ci throw new GPBDecodeException("Fail to push limit."); 341ffe3c632Sopenharmony_ci } 342ffe3c632Sopenharmony_ci 343ffe3c632Sopenharmony_ci return $old_limit; 344ffe3c632Sopenharmony_ci } 345ffe3c632Sopenharmony_ci 346ffe3c632Sopenharmony_ci /* The limit passed in is actually the *old* limit, which we returned from 347ffe3c632Sopenharmony_ci * PushLimit(). 348ffe3c632Sopenharmony_ci * 349ffe3c632Sopenharmony_ci * @param integer $byte_limit 350ffe3c632Sopenharmony_ci */ 351ffe3c632Sopenharmony_ci public function popLimit($byte_limit) 352ffe3c632Sopenharmony_ci { 353ffe3c632Sopenharmony_ci $this->current_limit = $byte_limit; 354ffe3c632Sopenharmony_ci $this->recomputeBufferLimits(); 355ffe3c632Sopenharmony_ci // We may no longer be at a legitimate message end. ReadTag() needs to 356ffe3c632Sopenharmony_ci // be called again to find out. 357ffe3c632Sopenharmony_ci $this->legitimate_message_end = false; 358ffe3c632Sopenharmony_ci } 359ffe3c632Sopenharmony_ci 360ffe3c632Sopenharmony_ci public function incrementRecursionDepthAndPushLimit( 361ffe3c632Sopenharmony_ci $byte_limit, &$old_limit, &$recursion_budget) 362ffe3c632Sopenharmony_ci { 363ffe3c632Sopenharmony_ci $old_limit = $this->pushLimit($byte_limit); 364ffe3c632Sopenharmony_ci $recursion_limit = --$this->recursion_limit; 365ffe3c632Sopenharmony_ci } 366ffe3c632Sopenharmony_ci 367ffe3c632Sopenharmony_ci public function decrementRecursionDepthAndPopLimit($byte_limit) 368ffe3c632Sopenharmony_ci { 369ffe3c632Sopenharmony_ci $result = $this->consumedEntireMessage(); 370ffe3c632Sopenharmony_ci $this->popLimit($byte_limit); 371ffe3c632Sopenharmony_ci ++$this->recursion_budget; 372ffe3c632Sopenharmony_ci return $result; 373ffe3c632Sopenharmony_ci } 374ffe3c632Sopenharmony_ci 375ffe3c632Sopenharmony_ci public function bytesUntilLimit() 376ffe3c632Sopenharmony_ci { 377ffe3c632Sopenharmony_ci if ($this->current_limit === PHP_INT_MAX) { 378ffe3c632Sopenharmony_ci return -1; 379ffe3c632Sopenharmony_ci } 380ffe3c632Sopenharmony_ci return $this->current_limit - $this->current; 381ffe3c632Sopenharmony_ci } 382ffe3c632Sopenharmony_ci} 383