Skip to content

Commit 8bea6bc

Browse files
committed
TFile: Improve handling of potential integer overflow
Raise an assertion for unexpected arguments and use size_t instead of int for the size argument which is typically sizeof(some_datatype). Signed-off-by: Stefan Weil <sw@weilnetz.de>
1 parent 45b11cd commit 8bea6bc

File tree

2 files changed

+22
-12
lines changed

2 files changed

+22
-12
lines changed

src/ccutil/serialis.cpp

+19-9
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ char* TFile::FGets(char* buffer, int buffer_size) {
9898
return size > 0 ? buffer : nullptr;
9999
}
100100

101-
int TFile::FReadEndian(void* buffer, int size, int count) {
101+
int TFile::FReadEndian(void* buffer, size_t size, int count) {
102102
int num_read = FRead(buffer, size, count);
103103
if (swap_) {
104104
char* char_buffer = static_cast<char*>(buffer);
@@ -109,12 +109,20 @@ int TFile::FReadEndian(void* buffer, int size, int count) {
109109
return num_read;
110110
}
111111

112-
int TFile::FRead(void* buffer, int size, int count) {
112+
int TFile::FRead(void* buffer, size_t size, int count) {
113113
ASSERT_HOST(!is_writing_);
114-
int required_size = size * count;
115-
if (required_size <= 0) return 0;
116-
if (data_->size() - offset_ < required_size)
114+
ASSERT_HOST(size > 0);
115+
ASSERT_HOST(count > 0);
116+
size_t required_size;
117+
if (SIZE_MAX / size <= count) {
118+
// Avoid integer overflow.
117119
required_size = data_->size() - offset_;
120+
} else {
121+
required_size = size * count;
122+
if (data_->size() - offset_ < required_size) {
123+
required_size = data_->size() - offset_;
124+
}
125+
}
118126
if (required_size > 0 && buffer != nullptr)
119127
memcpy(buffer, &(*data_)[offset_], required_size);
120128
offset_ += required_size;
@@ -149,14 +157,16 @@ bool TFile::CloseWrite(const STRING& filename, FileWriter writer) {
149157
return (*writer)(*data_, filename);
150158
}
151159

152-
int TFile::FWrite(const void* buffer, int size, int count) {
160+
int TFile::FWrite(const void* buffer, size_t size, int count) {
153161
ASSERT_HOST(is_writing_);
154-
int total = size * count;
155-
if (total <= 0) return 0;
162+
ASSERT_HOST(size > 0);
163+
ASSERT_HOST(count > 0);
164+
ASSERT_HOST(SIZE_MAX / size > count);
165+
size_t total = size * count;
156166
const char* buf = static_cast<const char*>(buffer);
157167
// This isn't very efficient, but memory is so fast compared to disk
158168
// that it is relatively unimportant, and very simple.
159-
for (int i = 0; i < total; ++i)
169+
for (size_t i = 0; i < total; ++i)
160170
data_->push_back(buf[i]);
161171
return count;
162172
}

src/ccutil/serialis.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ class TFile {
7272
// Replicates fread, followed by a swap of the bytes if needed, returning the
7373
// number of items read. If swap_ is true then the count items will each have
7474
// size bytes reversed.
75-
int FReadEndian(void* buffer, int size, int count);
75+
int FReadEndian(void* buffer, size_t size, int count);
7676
// Replicates fread, returning the number of items read.
77-
int FRead(void* buffer, int size, int count);
77+
int FRead(void* buffer, size_t size, int count);
7878
// Resets the TFile as if it has been Opened, but nothing read.
7979
// Only allowed while reading!
8080
void Rewind();
@@ -87,7 +87,7 @@ class TFile {
8787

8888
// Replicates fwrite, returning the number of items written.
8989
// To use fprintf, use snprintf and FWrite.
90-
int FWrite(const void* buffer, int size, int count);
90+
int FWrite(const void* buffer, size_t size, int count);
9191

9292
private:
9393
// The number of bytes used so far.

0 commit comments

Comments
 (0)