mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 08:15:18 -04:00
putil: fix hang reading bam due to macOS libc++ bug in istream::eof()
Apparently eof() in older versions of libc++ returns true if the last character has just been read, whereas the proper behavior is only to return true when attempting to read past the end of the stream. Since failbit is reliably set in all cases when reading past the length of the stream, we should only trust the result of eof() if fail() also returns true.
This commit is contained in:
parent
3e5f2cf672
commit
3ccfbfaba7
@ -109,7 +109,7 @@ read_header(std::string &header, size_t num_bytes) {
|
||||
nassertr(buffer != nullptr, false);
|
||||
|
||||
_in->read(buffer, num_bytes);
|
||||
if (_in->fail() || _in->eof()) {
|
||||
if (_in->fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ get_datagram(Datagram &data) {
|
||||
// First, get the size of the upcoming datagram.
|
||||
StreamReader reader(_in, false);
|
||||
uint32_t num_bytes_32 = reader.get_uint32();
|
||||
if (_in->fail() || _in->eof()) {
|
||||
if (_in->fail()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -141,16 +141,29 @@ get_datagram(Datagram &data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_in->eof()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t num_bytes = (size_t)num_bytes_32;
|
||||
if (num_bytes_32 == (uint32_t)-1) {
|
||||
// Another special case for a value larger than 32 bits.
|
||||
uint64_t num_bytes_64 = reader.get_uint64();
|
||||
|
||||
if (_in->fail() || _in->eof()) {
|
||||
if (_in->fail()) {
|
||||
_error = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (num_bytes_64 == 0) {
|
||||
data.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_in->eof()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
num_bytes = (size_t)num_bytes_64;
|
||||
|
||||
// Make sure we have a reasonable datagram size for putting into memory.
|
||||
@ -169,6 +182,11 @@ get_datagram(Datagram &data) {
|
||||
while (bytes_read < num_bytes) {
|
||||
size_t bytes_left = num_bytes - bytes_read;
|
||||
|
||||
if (_in->eof()) {
|
||||
_error = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hold up a second - datagrams >4MB are pretty large by bam/network
|
||||
// standards. Let's take it 4MB at a time just in case the length is
|
||||
// corrupt, so we don't allocate potentially a few GBs of RAM only to
|
||||
@ -180,7 +198,7 @@ get_datagram(Datagram &data) {
|
||||
unsigned char *ptr = &buffer.p()[bytes_read];
|
||||
|
||||
_in->read((char *)ptr, (streamsize)bytes_left);
|
||||
if (_in->fail() || _in->eof()) {
|
||||
if (_in->fail()) {
|
||||
_error = true;
|
||||
return false;
|
||||
}
|
||||
@ -210,7 +228,7 @@ save_datagram(SubfileInfo &info) {
|
||||
// First, get the size of the upcoming datagram.
|
||||
StreamReader reader(_in, false);
|
||||
size_t num_bytes_32 = reader.get_uint32();
|
||||
if (_in->fail() || _in->eof()) {
|
||||
if (_in->fail() || (_in->eof() && num_bytes_32 > 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user