Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add stream size checks #270

Merged
merged 2 commits into from
Mar 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/Stream/Reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ namespace Stream
// passing vector into this function to ensure proper vector size is read
template<typename T, typename A>
inline void Read(std::vector<T, A>& vector) {
// Size calculation can't possibly overflow since the vector size necessarily fits in memory
ReadImplementation(vector.data(), vector.size() * sizeof(T));
}

Expand All @@ -52,9 +53,14 @@ namespace Stream
void Read(std::vector<T, A>& vector) {
SizeType vectorSize;
Read(vectorSize);
// This check is trivially false for unsigned SizeType
if (vectorSize < 0) {
throw std::runtime_error("Vector's size may not be a negative number");
}
// This check may be trivially false when SizeType is much smaller than max vector size
if (vectorSize > vector.max_size()) {
throw std::runtime_error("Vector's size is too big to fit in memory");
}
vector.clear();
vector.resize(vectorSize);
Read(vector);
Expand All @@ -65,6 +71,7 @@ namespace Stream
// passing string into this function to ensure proper string size is read
template<typename CharT, typename Traits, typename Allocator>
void Read(std::basic_string<CharT, Traits, Allocator>& string) {
// Size calculation can't possibly overflow since the string size necessarily fits in memory
Read(&string[0], string.size() * sizeof(CharT));
}

Expand All @@ -74,9 +81,14 @@ namespace Stream
void Read(std::basic_string<CharT, Traits, Allocator>& string) {
SizeType stringSize;
Read(stringSize);
// This check is trivially false for unsigned SizeType
if (stringSize < 0) {
throw std::runtime_error("String's size may not be a negative number");
}
// This check may be trivially false when SizeType is too small to overflow string size for CharT types
if (stringSize > string.max_size()) {
throw std::runtime_error("String's size is too big to fit in memory");
}

string.clear();
string.resize(stringSize);
Expand Down
6 changes: 6 additions & 0 deletions src/Stream/Writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace Stream
// Vector data types
template<typename T, typename A>
inline void Write(const std::vector<T, A>& vector) {
// Size calculation can't possibly overflow since the vector size necessarily fits in memory
WriteImplementation(vector.data(), vector.size() * sizeof(T));
}

Expand All @@ -46,9 +47,11 @@ namespace Stream
template<typename SizeType, typename T, typename A>
void Write(const std::vector<T, A>& vector) {
auto vectorSize = vector.size();
// This check is trivially false if SizeType is larger than max vector size
if (vectorSize > std::numeric_limits<SizeType>::max()) {
throw std::runtime_error("Vector too large to save size field");
}
// This can't overflow due to check above
auto typedSize = static_cast<SizeType>(vectorSize);
Write(typedSize);
Write(vector);
Expand All @@ -58,6 +61,7 @@ namespace Stream
// Does not write null terminator unless specifically included in string
template<typename CharT, typename Traits, typename Allocator>
void Write(const std::basic_string<CharT, Traits, Allocator>& string) {
// Size calculation can't possibly overflow since the string size necessarily fits in memory
Write(&string[0], string.size() * sizeof(CharT));
}

Expand All @@ -67,9 +71,11 @@ namespace Stream
template<typename SizeType, typename CharT, typename Traits, typename Allocator>
void Write(const std::basic_string<CharT, Traits, Allocator>& string) {
auto stringSize = string.size();
// This check is trivially false if SizeType is larger than max string size
if (stringSize > std::numeric_limits<SizeType>::max()) {
throw std::runtime_error("String's size is too large to write in provided size field");
}
// This can't overflow due to check above
Write(static_cast<SizeType>(stringSize));
Write(string);
}
Expand Down