Merge "fread: cope with >2GiB totals."

This commit is contained in:
Elliott Hughes 2022-07-29 16:16:27 +00:00 committed by Gerrit Code Review
commit 6f4bb0771e
2 changed files with 28 additions and 1 deletions

View File

@ -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;

View File

@ -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()));
}