The loop
1 2 3 4 5 | <?php while ($read < $n && (false !== ($buf = fread($this->sock, $n - $read)))) { /* ... */ } ?> |
contains a subtle bug. Go ahead, read the relevant function documentation and see if you can spot it.
PHP’s fread function directly maps the C library’s fread function. As TBlue explains, the C fread function returns 0 when reading at the end of a stream. PHP does the simplest possible thing with this and returns an empty string; to determine that the stream is at end of file, programs must check with feof as well.
Most modern languages realize that explicitly checking for errors is a fairly error-prone convention. Java’s InputStream.read(byte[]) methods return -1 on EOF (and only on EOF) and raise exceptions on errors. Python’s File-like objects convention supports mechanisms other than raw byte reads (primarily, iteration) that make stopping at end of file implicit, on top of only returning an empty string at end of input (as with Java, Python raises exceptions when a stream read fails). Not PHP, though! In PHP, the loop above has to look like
1 2 3 4 5 6 | <?php while ($read < $n && !feof($this->sock) && (false !== ($buf = fread($this->sock, $n - $read)))) { /* ... */ } ?> |
Encountered in the wild: php-amqplib bug #12.
This is kind of like how
str_split()behaves: