@@ -36,6 +36,9 @@ class BinaryStream{
36
36
/** @var string */
37
37
protected $ buffer ;
38
38
39
+ private int $ readOps = 0 ;
40
+ private int $ readOpsLimit = 0 ;
41
+
39
42
public function __construct (string $ buffer = "" , int $ offset = 0 ){
40
43
$ this ->buffer = $ buffer ;
41
44
$ this ->offset = $ offset ;
@@ -56,6 +59,45 @@ public function getOffset() : int{
56
59
return $ this ->offset ;
57
60
}
58
61
62
+ /**
63
+ * @internal Experimental, may be removed
64
+ * Returns the total number of operations done on this BinaryStream so far
65
+ * When this value exceeds the read cost limit (if set to a value > 0), a BinaryDataException will be thrown
66
+ */
67
+ public function getReadOps () : int {
68
+ return $ this ->readOps ;
69
+ }
70
+
71
+ /**
72
+ * @internal Experimental, may be removed
73
+ */
74
+ public function setReadOps (int $ readOps ) : void {
75
+ $ this ->readOps = $ readOps ;
76
+ }
77
+
78
+ private function addReadOps (int $ amount ) : void {
79
+ if ($ this ->readOpsLimit > 0 ){
80
+ $ this ->readOps += $ amount ;
81
+ if ($ this ->readOps > $ this ->readOpsLimit ){
82
+ throw new BinaryDataException ("Operations limit of $ this ->readOpsLimit exceeded, cannot process any more data " );
83
+ }
84
+ }
85
+ }
86
+
87
+ /**
88
+ * @internal Experimental, may be removed
89
+ */
90
+ public function getReadOpsLimit () : int {
91
+ return $ this ->readOpsLimit ;
92
+ }
93
+
94
+ /**
95
+ * @internal Experimental, may be removed
96
+ */
97
+ public function setReadOpsLimit (int $ readOpsLimit ) : void {
98
+ $ this ->readOpsLimit = $ readOpsLimit ;
99
+ }
100
+
59
101
public function getBuffer () : string {
60
102
return $ this ->buffer ;
61
103
}
@@ -71,6 +113,7 @@ public function get(int $len) : string{
71
113
if ($ len < 0 ){
72
114
throw new \InvalidArgumentException ("Length must be positive " );
73
115
}
116
+ $ this ->addReadOps (1 );
74
117
75
118
$ remaining = strlen ($ this ->buffer ) - $ this ->offset ;
76
119
if ($ remaining < $ len ){
@@ -89,6 +132,7 @@ public function getRemaining() : string{
89
132
if ($ this ->offset >= $ buflen ){
90
133
throw new BinaryDataException ("No bytes left to read " );
91
134
}
135
+ $ this ->addReadOps (1 );
92
136
$ str = substr ($ this ->buffer , $ this ->offset );
93
137
$ this ->offset = $ buflen ;
94
138
return $ str ;
@@ -305,6 +349,7 @@ public function putLLong(int $v) : void{
305
349
* @throws BinaryDataException
306
350
*/
307
351
public function getUnsignedVarInt () : int {
352
+ $ this ->addReadOps (5 ); //technically this could be 1-5, but varints are costly in any case
308
353
return Binary::readUnsignedVarInt ($ this ->buffer , $ this ->offset );
309
354
}
310
355
@@ -322,6 +367,7 @@ public function putUnsignedVarInt(int $v) : void{
322
367
* @throws BinaryDataException
323
368
*/
324
369
public function getVarInt () : int {
370
+ $ this ->addReadOps (5 );
325
371
return Binary::readVarInt ($ this ->buffer , $ this ->offset );
326
372
}
327
373
@@ -339,13 +385,15 @@ public function putVarInt(int $v) : void{
339
385
* @throws BinaryDataException
340
386
*/
341
387
public function getUnsignedVarLong () : int {
388
+ $ this ->addReadOps (10 );
342
389
return Binary::readUnsignedVarLong ($ this ->buffer , $ this ->offset );
343
390
}
344
391
345
392
/**
346
393
* Writes a 64-bit variable-length integer to the end of the buffer.
347
394
*/
348
395
public function putUnsignedVarLong (int $ v ) : void {
396
+ $ this ->addReadOps (10 );
349
397
$ this ->buffer .= Binary::writeUnsignedVarLong ($ v );
350
398
}
351
399
0 commit comments