Merge "fread: cope with >2GiB totals."
This commit is contained in:
commit
6f4bb0771e
|
@ -1129,7 +1129,9 @@ size_t fread_unlocked(void* buf, size_t size, size_t count, FILE* fp) {
|
|||
|
||||
// Read directly into the caller's buffer.
|
||||
while (total > 0) {
|
||||
ssize_t bytes_read = (*fp->_read)(fp->_cookie, dst, total);
|
||||
// The _read function pointer takes an int instead of a size_t.
|
||||
int chunk_size = MIN(total, INT_MAX);
|
||||
ssize_t bytes_read = (*fp->_read)(fp->_cookie, dst, chunk_size);
|
||||
if (bytes_read <= 0) {
|
||||
fp->_flags |= (bytes_read == 0) ? __SEOF : __SERR;
|
||||
break;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <sys/cdefs.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <wchar.h>
|
||||
|
@ -2938,3 +2939,27 @@ TEST(STDIO_TEST, freopen_null_filename_mode) {
|
|||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static int64_t GetTotalRamGiB() {
|
||||
struct sysinfo si;
|
||||
sysinfo(&si);
|
||||
return (static_cast<int64_t>(si.totalram) * si.mem_unit) / 1024 / 1024 / 1024;
|
||||
}
|
||||
|
||||
TEST(STDIO_TEST, fread_int_overflow) {
|
||||
if (GetTotalRamGiB() <= 4) GTEST_SKIP() << "not enough memory";
|
||||
|
||||
const size_t too_big_for_an_int = 0x80000000ULL;
|
||||
std::vector<char> buf(too_big_for_an_int);
|
||||
std::unique_ptr<FILE, decltype(&fclose)> fp{fopen("/dev/zero", "re"), fclose};
|
||||
ASSERT_EQ(too_big_for_an_int, fread(&buf[0], 1, too_big_for_an_int, fp.get()));
|
||||
}
|
||||
|
||||
TEST(STDIO_TEST, fwrite_int_overflow) {
|
||||
if (GetTotalRamGiB() <= 4) GTEST_SKIP() << "not enough memory";
|
||||
|
||||
const size_t too_big_for_an_int = 0x80000000ULL;
|
||||
std::vector<char> buf(too_big_for_an_int);
|
||||
std::unique_ptr<FILE, decltype(&fclose)> fp{fopen("/dev/null", "we"), fclose};
|
||||
ASSERT_EQ(too_big_for_an_int, fwrite(&buf[0], 1, too_big_for_an_int, fp.get()));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue