Issues (1507)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

PHPDaemon/Clients/MySQL/Connection.php (44 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace PHPDaemon\Clients\MySQL;
3
4
use PHPDaemon\Core\Daemon;
5
use PHPDaemon\Network\ClientConnection;
6
use PHPDaemon\Structures\StackCallbacks;
7
use PHPDaemon\Utils\Binary;
8
9
class Connection extends ClientConnection
10
{
11
12
    /**
13
     * @var integer Sequence. Pointer of packet sequence
14
     */
15
    public $seq = 0;
16
17
    /**
18
     * @var integer Client flags
19
     */
20
    public $clientFlags = 239237;
21
22
    /**
23
     * @var integer
24
     */
25
    public $threadId;
26
27
    /**
28
     * @var string
29
     */
30
    public $scramble;
31
32
    /**
33
     * @var string
34
     */
35
    public $serverver;
36
37
    /**
38
     * @var integer
39
     */
40
    public $serverCaps;
41
42
    /**
43
     * @var integer
44
     */
45
    public $serverLang;
46
47
    /**
48
     * @var integer Server flags: http://dev.mysql.com/doc/internals/en/status-flags.html
49
     */
50
    public $serverStatus;
51
52
    /**
53
     * @var integer Number of warnings generated by the command
54
     */
55
    public $warnCount;
56
57
    /**
58
     * @var string
59
     */
60
    public $message;
61
62
    /**
63
     * @var integer Charset number (see MySQL charset list)
64
     */
65
    public $charsetNumber = 0x21;
66
67
    /**
68
     * @var string User name
69
     */
70
    protected $user = 'root';
71
72
    /**
73
     * @var string Password
74
     */
75
    protected $password = '';
76
77
    /**
78
     * @var string Database name
79
     */
80
    public $dbname = '';
81
82
    /**
83
     * @TODO DESCR
84
     */
85
    const STATE_STANDBY = 0;
86
87
    /**
88
     * @TODO DESCR
89
     */
90
    const STATE_BODY = 1;
91
92
    /**
93
     * @var string Phase
94
     */
95
    protected $phase = 0;
96
97
    /**
98
     * @TODO DESCR
99
     */
100
    const PHASE_GOT_INIT = 1;
101
102
    /**
103
     * @TODO DESCR
104
     */
105
    const PHASE_AUTH_SENT = 2;
106
107
    /**
108
     * @TODO DESCR
109
     */
110
    const PHASE_AUTH_ERR = 3;
111
112
    /**
113
     * @TODO DESCR
114
     */
115
    const PHASE_HANDSHAKED = 4;
116
117
    /**
118
     * @var integer State of pointer of incoming data. 0 - Result Set Header Packet, 1 - Field Packet, 2 - Row Packet
119
     */
120
    protected $rsState = 0;
121
122
    /**
123
     * @TODO DESCR
124
     */
125
    const RS_STATE_HEADER = 0;
126
127
    /**
128
     * @TODO DESCR
129
     */
130
    const RS_STATE_FIELD = 1;
131
132
    /**
133
     * @TODO DESCR
134
     */
135
    const RS_STATE_ROW = 2;
136
137
    /**
138
     * @var integer Packet size
139
     */
140
    protected $pctSize = 0;
141
142
    /**
143
     * @var array Result rows
144
     */
145
    public $resultRows = [];
146
147
    /**
148
     * @var array Result fields
149
     */
150
    public $resultFields = [];
151
152
    /**
153
     * @var object Property holds a reference to user's object
154
     */
155
    public $context;
156
157
    /**
158
     * @var integer INSERT_ID()
159
     */
160
    public $insertId;
161
162
    /**
163
     * @var integer Affected rows
164
     */
165
    public $affectedRows;
166
167
    /**
168
     * @var integer Protocol version
169
     */
170
    public $protover = 0;
171
172
    /**
173
     * @var integer Timeout
174
     */
175
    public $timeout = 120;
176
177
    /**
178
     * @var integer Error number
179
     */
180
    public $errno = 0;
181
182
    /**
183
     * @var string Error message
184
     */
185
    public $errmsg = '';
186
187
    /**
188
     * @var integer Low mark
189
     */
190
    protected $lowMark = 4;
191
192
    /**
193
     * Executes the given callback when/if the connection is handshaked
194
     * @param  callable $cb Callback
195
     * @callback $cb ( Connection $conn, boolean $success )
196
     * @return void
197
     */
198 View Code Duplication
    public function onConnected($cb)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
199
    {
200
        if ($this->phase === self::PHASE_AUTH_ERR) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $this->phase (string) and self::PHASE_AUTH_ERR (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
201
            $cb($this, false);
202
        } elseif ($this->phase === self::PHASE_HANDSHAKED) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $this->phase (string) and self::PHASE_HANDSHAKED (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
203
            $cb($this, true);
204
        } else {
205
            if (!$this->onConnected) {
206
                $this->onConnected = new StackCallbacks();
207
            }
208
            $this->onConnected->push($cb);
209
        }
210
    }
211
212
    /**
213
     * Called when the connection is handshaked (at low-level), and peer is ready to recv. data
214
     * @return void
215
     */
216
    public function onReady()
217
    {
218
        if (mb_orig_strlen($this->path) && !mb_orig_strlen($this->dbname)) {
219
            $this->dbname = $this->path;
220
        }
221
    }
222
223
    /**
224
     * Sends a packet
225
     * @param  string $packet Data
226
     * @return boolean         Success
227
     */
228
    public function sendPacket($packet)
229
    {
230
        //Daemon::log('Client --> Server: ' . Debug::exportBytes($packet) . "\n\n");
231
        return $this->write(Binary::int2bytes(3, mb_orig_strlen($packet), true) . chr($this->seq++) . $packet);
232
    }
233
234
    /**
235
     * Builds length-encoded binary string
236
     * @param  string $s String
237
     * @return string    Resulting binary string
238
     */
239
    public function buildLenEncodedBinary($s)
240
    {
241
        if ($s === null) {
242
            return "\251";
243
        }
244
245
        $l = mb_orig_strlen($s);
246
247
        if ($l <= 250) {
248
            return chr($l) . $s;
249
        }
250
251
        if ($l <= 0xFFFF) {
252
            return "\252" . Binary::int2bytes(2, true) . $s;
0 ignored issues
show
true is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
253
        }
254
255
        if ($l <= 0xFFFFFF) {
256
            return "\254" . Binary::int2bytes(3, true) . $s;
0 ignored issues
show
true is of type boolean, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
257
        }
258
259
        return Binary::int2bytes(8, $l, true) . $s;
260
    }
261
262
    /**
263
     * Parses length-encoded binary integer
264
     * @return integer Result
0 ignored issues
show
Should the return type not be integer|null|false|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
265
     */
266
    public function parseEncodedBinary()
267
    {
268
        $f = ord($this->read(1));
269
        if ($f <= 250) {
270
            return $f;
271
        }
272
        if ($f === 251) {
273
            return null;
274
        }
275
        if ($f === 255) {
276
            return false;
277
        }
278
        if ($f === 252) {
279
            return Binary::bytes2int($this->read(2), true);
0 ignored issues
show
It seems like $this->read(2) targeting PHPDaemon\Network\IOStream::read() can also be of type false; however, PHPDaemon\Utils\Binary::bytes2int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
280
        }
281
        if ($f === 253) {
282
            return Binary::bytes2int($this->read(3), true);
0 ignored issues
show
It seems like $this->read(3) targeting PHPDaemon\Network\IOStream::read() can also be of type false; however, PHPDaemon\Utils\Binary::bytes2int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
283
        }
284
        return Binary::bytes2int($this->read(8), true);
0 ignored issues
show
It seems like $this->read(8) targeting PHPDaemon\Network\IOStream::read() can also be of type false; however, PHPDaemon\Utils\Binary::bytes2int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
285
    }
286
287
    /**
288
     * Parse length-encoded string
289
     * @return integer Result
0 ignored issues
show
Should the return type not be null|false|string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
290
     */
291
    public function parseEncodedString()
292
    {
293
        $l = $this->parseEncodedBinary();
294
        if (($l === null) || ($l === false)) {
295
            return $l;
296
        }
297
        return $this->read($l);
298
    }
299
300
    /**
301
     * Generates auth. token
302
     * @param  string $scramble Scramble string
303
     * @param  string $password Password
304
     * @return string           Result
305
     */
306
    public function getAuthToken($scramble, $password)
307
    {
308
        return sha1($scramble . sha1($hash1 = sha1($password, true), true), true) ^ $hash1;
309
    }
310
311
    /**
312
     * Sends auth. packet
313
     * @return void
314
     */
315
    public function auth()
316
    {
317
        if ($this->phase !== self::PHASE_GOT_INIT) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison !== seems to always evaluate to true as the types of $this->phase (string) and self::PHASE_GOT_INIT (integer) can never be identical. Maybe you want to use a loose comparison != instead?
Loading history...
318
            return;
319
        }
320
        $this->phase = self::PHASE_AUTH_SENT;
0 ignored issues
show
Documentation Bug introduced by
The property $phase was declared of type string, but self::PHASE_AUTH_SENT is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
321 View Code Duplication
        $this->onResponse->push(function ($conn, $result) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
322
            if ($conn->onConnected) {
323
                $conn->connected = true;
324
                $conn->onConnected->executeAll($conn, $result);
325
                $conn->onConnected = null;
326
            }
327
        });
328
        $this->clientFlags =
329
            Pool::CLIENT_LONG_PASSWORD |
330
            Pool::CLIENT_LONG_FLAG |
331
            Pool::CLIENT_LOCAL_FILES |
332
            Pool::CLIENT_PROTOCOL_41 |
333
            Pool::CLIENT_INTERACTIVE |
334
            Pool::CLIENT_TRANSACTIONS |
335
            Pool::CLIENT_SECURE_CONNECTION |
336
            Pool::CLIENT_MULTI_STATEMENTS |
337
            Pool::CLIENT_MULTI_RESULTS;
338
339
        $this->sendPacket(
340
            $packet = pack('VVc', $this->clientFlags, $this->pool->maxAllowedPacket, $this->charsetNumber)
341
                . "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
342
                . $this->user . "\x00"
343
                . ($this->password === '' ? "\x00" : $this->buildLenEncodedBinary(
344
                    $this->getAuthToken($this->scramble, $this->password)
345
                ))
346
                . ($this->path !== '' ? $this->path . "\x00" : '')
347
        );
348
    }
349
350
    /**
351
     * Sends SQL-query
352
     * @param  string $q Query
353
     * @param  callable $cb Optional. Callback called when response received
0 ignored issues
show
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
354
     * @callback $cb ( Connection $conn, boolean $success )
355
     * @return boolean            Success
356
     */
357
    public function query($q, $cb = null)
358
    {
359
        if ($this->finished) {
360
            throw new ConnectionFinished;
361
        }
362
        return $this->command(Pool::COM_QUERY, $q, $cb);
363
    }
364
365
    /**
366
     * Begins a transaction
367
     * @param  callable $cb Optional. Callback called when response received
0 ignored issues
show
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
368
     * @throws ConnectionFinished
369
     */
370
    public function begin($cb = null)
371
    {
372
        $this->query('BEGIN', $cb);
373
        $this->acquire();
374
    }
375
376
    /**
377
     * Commit a transaction
378
     * @param  callable $cb Optional. Callback called when response received
0 ignored issues
show
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
379
     * @throws ConnectionFinished
380
     */
381
    public function commit($cb = null)
382
    {
383
        $this->query('COMMIT', $cb);
384
        $this->release();
385
    }
386
387
    /**
388
     * Rollback a transaction
389
     * @throws ConnectionFinished
390
     */
391
    public function rollback($cb = null)
392
    {
393
        $this->query('ROLLBACK', $cb);
394
        $this->release();
395
    }
396
397
    /**
398
     * Sends echo-request
399
     * @param  callable $cb Optional. Callback called when response received
0 ignored issues
show
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
400
     * @callback $cb ( Connection $conn, boolean $success )
401
     * @return boolean            Success
402
     */
403
    public function ping($cb = null)
404
    {
405
        return $this->command(Pool::COM_PING, '', $cb);
406
    }
407
408
    /**
409
     * Sends arbitrary command
410
     * @param  string $cmd Command
411
     * @param  string $q Data
412
     * @param  callable $cb Optional
0 ignored issues
show
Should the type for parameter $cb not be callable|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
413
     * @throws ConnectionFinished
414
     * @callback $cb ( Connection $conn, boolean $success )
415
     * @return boolean            Success
416
     */
417 View Code Duplication
    public function command($cmd, $q = '', $cb = null)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
418
    {
419
        if ($this->phase !== self::PHASE_HANDSHAKED) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison !== seems to always evaluate to true as the types of $this->phase (string) and self::PHASE_HANDSHAKED (integer) can never be identical. Maybe you want to use a loose comparison != instead?
Loading history...
420
            return false;
421
        }
422
423
        $this->onResponse->push($cb);
0 ignored issues
show
It seems like $cb defined by parameter $cb on line 417 can also be of type null; however, PHPDaemon\Structures\StackCallbacks::push() does only seem to accept callable, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
424
        $this->seq = 0;
425
        $this->sendPacket(chr($cmd) . $q);
426
427
        return true;
428
    }
429
430
    /**
431
     * Sets default database name
432
     * @param  string $name Database name
433
     * @return boolean         Success
434
     */
435
    public function selectDB($name)
436
    {
437
        $this->dbname = $name;
438
439
        if ($this->phase !== self::PHASE_GOT_INIT) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison !== seems to always evaluate to true as the types of $this->phase (string) and self::PHASE_GOT_INIT (integer) can never be identical. Maybe you want to use a loose comparison != instead?
Loading history...
440
            return $this->query('USE `' . $name . '`');
441
        }
442
443
        return true;
444
    }
445
446
    /**
447
     * Called when new data received
448
     * @return void
449
     */
450
    public function onRead()
451
    {
452
        packet:
453
        if ($this->state === self::STATE_STANDBY) {
454
            if ($this->bev->input->length < 4) {
455
                return;
456
            }
457
            $this->pctSize = Binary::bytes2int($this->read(3), true);
0 ignored issues
show
It seems like $this->read(3) targeting PHPDaemon\Network\IOStream::read() can also be of type false; however, PHPDaemon\Utils\Binary::bytes2int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
Documentation Bug introduced by
It seems like \PHPDaemon\Utils\Binary:...t($this->read(3), true) can also be of type double. However, the property $pctSize is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
458
            $this->setWatermark($this->pctSize, $this->pctSize);
459
            $this->state = self::STATE_BODY;
460
            $this->seq = ord($this->read(1)) + 1;
461
        }
462
        /* STATE_BODY */
463
        $l = $this->bev->input->length;
464
        if ($l < $this->pctSize) {
465
            return;
466
        }
467
        $this->state = self::STATE_STANDBY;
468
        $this->setWatermark(4);
469
        if ($this->phase === 0) {
470
            $this->phase = self::PHASE_GOT_INIT;
0 ignored issues
show
Documentation Bug introduced by
The property $phase was declared of type string, but self::PHASE_GOT_INIT is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
471
            $this->protover = ord($this->read(1));
472
            if ($this->protover === 0xFF) { // error
473
                $fieldCount = $this->protover;
474
                $this->protover = 0;
475 View Code Duplication
                $this->onResponse->push(function ($conn, $result) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
476
                    if ($conn->onConnected) {
477
                        $conn->connected = true;
478
                        $conn->onConnected->executeAll($conn, $result);
479
                        $conn->onConnected = null;
480
                    }
481
                });
482
                goto field;
483
            }
484
            if (($p = $this->search("\x00")) === false) {
485
                $this->log('nul-terminator of \'serverver\' is not found');
486
                $this->finish();
487
                return;
488
            }
489
            $this->serverver = $this->read($p);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->read($p) can also be of type false. However, the property $serverver is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
490
            $this->drain(1); // drain nul-byte
491
            $this->threadId = Binary::bytes2int($this->read(4), true);
0 ignored issues
show
It seems like $this->read(4) targeting PHPDaemon\Network\IOStream::read() can also be of type false; however, PHPDaemon\Utils\Binary::bytes2int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
Documentation Bug introduced by
It seems like \PHPDaemon\Utils\Binary:...t($this->read(4), true) can also be of type double. However, the property $threadId is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
492
            $this->scramble = $this->read(8);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->read(8) can also be of type false. However, the property $scramble is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
493
            $this->drain(1); // ????
494
495
            $this->serverCaps = Binary::bytes2int($this->read(2), true);
0 ignored issues
show
It seems like $this->read(2) targeting PHPDaemon\Network\IOStream::read() can also be of type false; however, PHPDaemon\Utils\Binary::bytes2int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
Documentation Bug introduced by
It seems like \PHPDaemon\Utils\Binary:...t($this->read(2), true) can also be of type double. However, the property $serverCaps is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
496
            $this->serverLang = ord($this->read(1));
497
            $this->serverStatus = Binary::bytes2int($this->read(2), true);
0 ignored issues
show
It seems like $this->read(2) targeting PHPDaemon\Network\IOStream::read() can also be of type false; however, PHPDaemon\Utils\Binary::bytes2int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
Documentation Bug introduced by
It seems like \PHPDaemon\Utils\Binary:...t($this->read(2), true) can also be of type double. However, the property $serverStatus is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
498
            $this->drain(13);
499
            $restScramble = $this->read(12);
500
            $this->scramble .= $restScramble;
501
            $this->drain(1);
502
503
            $this->auth();
504
        } else {
505
            $fieldCount = ord($this->read(1));
506
            field:
507
            if ($fieldCount === 0xFF) {
508
                // Error packet
509
                $u = unpack('v', $this->read(2));
510
                $this->errno = $u[1];
511
                $state = $this->read(6);
0 ignored issues
show
$state is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
512
                $this->errmsg = $this->read($this->pctSize - $l + $this->bev->input->length);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->read($this->pctSi...is->bev->input->length) can also be of type false. However, the property $errmsg is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
513
                $this->onError();
514
                $this->errno = 0;
515
                $this->errmsg = '';
516
            } elseif ($fieldCount === 0x00) {
517
                // OK Packet Empty
518
                if ($this->phase === self::PHASE_AUTH_SENT) {
519
                    $this->phase = self::PHASE_HANDSHAKED;
0 ignored issues
show
Documentation Bug introduced by
The property $phase was declared of type string, but self::PHASE_HANDSHAKED is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
520
521
                    if ($this->dbname !== '') {
522
                        $this->query('USE `' . $this->dbname . '`');
523
                    }
524
                }
525
526
                $this->affectedRows = $this->parseEncodedBinary();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->parseEncodedBinary() can also be of type false or double. However, the property $affectedRows is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
527
528
                $this->insertId = $this->parseEncodedBinary();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->parseEncodedBinary() can also be of type false or double. However, the property $insertId is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
529
530
                $u = unpack('v', $this->read(2));
531
                $this->serverStatus = $u[1];
532
533
                $u = unpack('v', $this->read(2));
534
                $this->warnCount = $u[1];
535
536
                $this->message = $this->read($this->pctSize - $l + $this->bev->input->length);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->read($this->pctSi...is->bev->input->length) can also be of type false. However, the property $message is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
537
                $this->onResultDone();
538
            } elseif ($fieldCount === 0xFE) {
539
                // EOF Packet
540
                if ($this->rsState === self::RS_STATE_ROW) {
541
                    $this->onResultDone();
542
                } else {
543
                    ++$this->rsState;
544
                }
545
            } else {
546
                // Data packet
547
                $this->prependInput(chr($fieldCount));
548
549
                if ($this->rsState === self::RS_STATE_HEADER) {
550
                    // Result Set Header Packet
551
                    $extra = $this->parseEncodedBinary();
0 ignored issues
show
$extra is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
552
                    $this->rsState = self::RS_STATE_FIELD;
553
                } elseif ($this->rsState === self::RS_STATE_FIELD) {
554
                    // Field Packet
555
                    $field = [
556
                        'catalog' => $this->parseEncodedString(),
557
                        'db' => $this->parseEncodedString(),
558
                        'table' => $this->parseEncodedString(),
559
                        'org_table' => $this->parseEncodedString(),
560
                        'name' => $this->parseEncodedString(),
561
                        'org_name' => $this->parseEncodedString()
562
                    ];
563
564
                    $this->drain(1); // filler
565
566
                    $u = unpack('v', $this->read(2));
567
568
                    $field['charset'] = $u[1];
569
                    $u = unpack('V', $this->read(4));
570
                    $field['length'] = $u[1];
571
572
                    $field['type'] = ord($this->read(1));
573
574
                    $u = unpack('v', $this->read(2));
575
                    $field['flags'] = $u[1];
576
577
                    $field['decimals'] = ord($this->read(1));
578
579
                    $this->resultFields[] = $field;
580
                } elseif ($this->rsState === self::RS_STATE_ROW) {
581
                    // Row Packet
582
                    $row = [];
583
584
                    for ($i = 0, $nf = sizeof($this->resultFields); $i < $nf; ++$i) {
585
                        $row[$this->resultFields[$i]['name']] = $this->parseEncodedString();
586
                    }
587
588
                    $this->resultRows[] = $row;
589
                }
590
            }
591
        }
592
        if ($this->finished) {
593
            return;
594
        }
595
        $this->drain($this->pctSize - $l + $this->bev->input->length); // drain the rest of packet
596
        goto packet;
597
    }
598
599
    /**
600
     * Called when connection finishes
601
     * @return void
602
     */
603
    public function onFinish()
604
    {
605
        $this->command(Pool::COM_QUIT);
606
        parent::onFinish();
607
    }
608
609
    /**
610
     * Called when the whole result received
611
     * @return void
612
     */
613
    public function onResultDone()
614
    {
615
        $this->rsState = self::RS_STATE_HEADER;
616
        $this->onResponse->executeOne($this, true);
617
        $this->checkFree();
618
        $this->resultRows = [];
619
        $this->resultFields = [];
620
    }
621
622
    /**
623
     * Called when error occured
624
     * @return void
625
     */
626
    public function onError()
627
    {
628
        $this->rsState = self::RS_STATE_HEADER;
629
        $this->onResponse->executeOne($this, false);
630
        $this->checkFree();
631
        $this->resultRows = [];
632
        $this->resultFields = [];
633
634
        if (($this->phase === self::PHASE_AUTH_SENT) || ($this->phase === self::PHASE_GOT_INIT)) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $this->phase (string) and self::PHASE_AUTH_SENT (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $this->phase (string) and self::PHASE_GOT_INIT (integer) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
635
            // in case of auth error
636
            $this->phase = self::PHASE_AUTH_ERR;
0 ignored issues
show
Documentation Bug introduced by
The property $phase was declared of type string, but self::PHASE_AUTH_ERR is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
637
            $this->finish();
638
        }
639
640
        Daemon::log(__METHOD__ . ' #' . $this->errno . ': ' . $this->errmsg);
641
    }
642
}
643