Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle parser errors by emitting error and closing connection #159

Merged
merged 2 commits into from
Sep 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 42 additions & 23 deletions src/Io/Buffer.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function prepend($str)
*
* @param int $len length in bytes, must be positive or zero
* @return string
* @throws \LogicException
* @throws \UnderflowException
*/
public function read($len)
{
Expand All @@ -53,7 +53,7 @@ public function read($len)

// ensure buffer size contains $len bytes by checking target buffer position
if ($len < 0 || !isset($this->buffer[$this->bufferPos + $len - 1])) {
throw new \LogicException('Not enough data in buffer to read ' . $len . ' bytes');
throw new \UnderflowException('Not enough data in buffer to read ' . $len . ' bytes');
}
$buffer = \substr($this->buffer, $this->bufferPos, $len);
$this->bufferPos += $len;
Expand All @@ -62,39 +62,58 @@ public function read($len)
}

/**
* Skips binary string data with given byte length from buffer
* Reads data with given byte length from buffer into a new buffer
*
* This method can be used instead of `read()` if you do not care about the
* bytes that will be skipped.
* This class keeps consumed data in memory for performance reasons and only
* advances the internal buffer position by default. Reading data into a new
* buffer will clear the data from the original buffer to free memory.
*
* @param int $len length in bytes, must be positve and non-zero
* @return void
* @throws \LogicException
* @param int $len length in bytes, must be positive or zero
* @return self
* @throws \UnderflowException
*/
public function skip($len)
public function readBuffer($len)
{
if ($len < 1 || !isset($this->buffer[$this->bufferPos + $len - 1])) {
throw new \LogicException('Not enough data in buffer');
// happy path to return empty buffer without any memory access for zero length string
if ($len === 0) {
return new self();
}
$this->bufferPos += $len;

// ensure buffer size contains $len bytes by checking target buffer position
if ($len < 0 || !isset($this->buffer[$this->bufferPos + $len - 1])) {
throw new \UnderflowException('Not enough data in buffer to read ' . $len . ' bytes');
}

$buffer = new self();
$buffer->buffer = $this->read($len);

if (!isset($this->buffer[$this->bufferPos])) {
$this->buffer = '';
} else {
$this->buffer = \substr($this->buffer, $this->bufferPos);
}
$this->bufferPos = 0;

return $buffer;

}

/**
* Clears all consumed data from the buffer
* Skips binary string data with given byte length from buffer
*
* This class keeps consumed data in memory for performance reasons and only
* advances the internal buffer position until this method is called.
* This method can be used instead of `read()` if you do not care about the
* bytes that will be skipped.
*
* @param int $len length in bytes, must be positve and non-zero
* @return void
* @throws \UnderflowException
*/
public function trim()
public function skip($len)
{
if (!isset($this->buffer[$this->bufferPos])) {
$this->buffer = '';
} else {
$this->buffer = \substr($this->buffer, $this->bufferPos);
if ($len < 1 || !isset($this->buffer[$this->bufferPos + $len - 1])) {
throw new \UnderflowException('Not enough data in buffer');
}
$this->bufferPos = 0;
$this->bufferPos += $len;
}

/**
Expand Down Expand Up @@ -201,13 +220,13 @@ public function readStringLen()
* Reads string until NULL character
*
* @return string
* @throws \LogicException
* @throws \UnderflowException
*/
public function readStringNull()
{
$pos = \strpos($this->buffer, "\0", $this->bufferPos);
if ($pos === false) {
throw new \LogicException('Missing NULL character');
throw new \UnderflowException('Missing NULL character');
}

$ret = $this->read($pos - $this->bufferPos);
Expand Down
Loading