Skip to content

Commit 03b74bd

Browse files
authored
Merge pull request #159 from clue-labs/parser-errors
Handle parser errors by emitting error and closing connection
2 parents 60a3fae + 3bf10ac commit 03b74bd

File tree

4 files changed

+255
-116
lines changed

4 files changed

+255
-116
lines changed

src/Io/Buffer.php

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public function prepend($str)
3737
*
3838
* @param int $len length in bytes, must be positive or zero
3939
* @return string
40-
* @throws \LogicException
40+
* @throws \UnderflowException
4141
*/
4242
public function read($len)
4343
{
@@ -53,7 +53,7 @@ public function read($len)
5353

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

6464
/**
65-
* Skips binary string data with given byte length from buffer
65+
* Reads data with given byte length from buffer into a new buffer
6666
*
67-
* This method can be used instead of `read()` if you do not care about the
68-
* bytes that will be skipped.
67+
* This class keeps consumed data in memory for performance reasons and only
68+
* advances the internal buffer position by default. Reading data into a new
69+
* buffer will clear the data from the original buffer to free memory.
6970
*
70-
* @param int $len length in bytes, must be positve and non-zero
71-
* @return void
72-
* @throws \LogicException
71+
* @param int $len length in bytes, must be positive or zero
72+
* @return self
73+
* @throws \UnderflowException
7374
*/
74-
public function skip($len)
75+
public function readBuffer($len)
7576
{
76-
if ($len < 1 || !isset($this->buffer[$this->bufferPos + $len - 1])) {
77-
throw new \LogicException('Not enough data in buffer');
77+
// happy path to return empty buffer without any memory access for zero length string
78+
if ($len === 0) {
79+
return new self();
7880
}
79-
$this->bufferPos += $len;
81+
82+
// ensure buffer size contains $len bytes by checking target buffer position
83+
if ($len < 0 || !isset($this->buffer[$this->bufferPos + $len - 1])) {
84+
throw new \UnderflowException('Not enough data in buffer to read ' . $len . ' bytes');
85+
}
86+
87+
$buffer = new self();
88+
$buffer->buffer = $this->read($len);
89+
90+
if (!isset($this->buffer[$this->bufferPos])) {
91+
$this->buffer = '';
92+
} else {
93+
$this->buffer = \substr($this->buffer, $this->bufferPos);
94+
}
95+
$this->bufferPos = 0;
96+
97+
return $buffer;
98+
8099
}
81100

82101
/**
83-
* Clears all consumed data from the buffer
102+
* Skips binary string data with given byte length from buffer
84103
*
85-
* This class keeps consumed data in memory for performance reasons and only
86-
* advances the internal buffer position until this method is called.
104+
* This method can be used instead of `read()` if you do not care about the
105+
* bytes that will be skipped.
87106
*
107+
* @param int $len length in bytes, must be positve and non-zero
88108
* @return void
109+
* @throws \UnderflowException
89110
*/
90-
public function trim()
111+
public function skip($len)
91112
{
92-
if (!isset($this->buffer[$this->bufferPos])) {
93-
$this->buffer = '';
94-
} else {
95-
$this->buffer = \substr($this->buffer, $this->bufferPos);
113+
if ($len < 1 || !isset($this->buffer[$this->bufferPos + $len - 1])) {
114+
throw new \UnderflowException('Not enough data in buffer');
96115
}
97-
$this->bufferPos = 0;
116+
$this->bufferPos += $len;
98117
}
99118

100119
/**
@@ -201,13 +220,13 @@ public function readStringLen()
201220
* Reads string until NULL character
202221
*
203222
* @return string
204-
* @throws \LogicException
223+
* @throws \UnderflowException
205224
*/
206225
public function readStringNull()
207226
{
208227
$pos = \strpos($this->buffer, "\0", $this->bufferPos);
209228
if ($pos === false) {
210-
throw new \LogicException('Missing NULL character');
229+
throw new \UnderflowException('Missing NULL character');
211230
}
212231

213232
$ret = $this->read($pos - $this->bufferPos);

0 commit comments

Comments
 (0)