Skip to content

Commit 1452ed0

Browse files
committed
FIX: Fix potential for invalid read in DbnDecoder
1 parent afa2403 commit 1452ed0

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- Added missing `StatType::Vwap` variant used in the ICE datasets
1111
- Added missing `ToString` and `operator<<` handling for `StatType::ClosePrice` and
1212
`StatType::NetChange`
13+
- Fixed potential for invalid reads when decoding C strings in `DbnDecoder`
1314

1415
## 0.15.0 - 2024-01-16
1516

src/dbn_decoder.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@ const char* Consume(std::vector<std::uint8_t>::const_iterator& byte_it,
4646
byte_it += num_bytes;
4747
return reinterpret_cast<const char*>(pos);
4848
}
49+
50+
std::string Consume(std::vector<std::uint8_t>::const_iterator& byte_it,
51+
const std::ptrdiff_t num_bytes, const char* context) {
52+
const auto cstr = Consume(byte_it, num_bytes);
53+
// strnlen isn't portable
54+
const std::size_t str_len = std::find(cstr, cstr + num_bytes, '\0') - cstr;
55+
if (str_len == num_bytes) {
56+
throw databento::DbnResponseError{std::string{"Invalid "} + context +
57+
" missing null terminator"};
58+
}
59+
return std::string{cstr, str_len};
60+
}
4961
} // namespace
5062

5163
DbnDecoder::DbnDecoder(detail::SharedChannel channel)
@@ -106,7 +118,7 @@ databento::Metadata DbnDecoder::DecodeMetadataFields(
106118
std::to_string(res.version)};
107119
}
108120
auto read_buffer_it = buffer.cbegin();
109-
res.dataset = std::string{Consume(read_buffer_it, kDatasetCstrLen)};
121+
res.dataset = Consume(read_buffer_it, kDatasetCstrLen, "dataset");
110122
const auto raw_schema = Consume<std::uint16_t>(read_buffer_it);
111123
if (raw_schema == std::numeric_limits<std::uint16_t>::max()) {
112124
res.has_mixed_schema = true;
@@ -266,8 +278,8 @@ bool DbnDecoder::DetectCompression() {
266278
std::string DbnDecoder::DecodeSymbol(
267279
std::size_t symbol_cstr_len,
268280
std::vector<std::uint8_t>::const_iterator& read_buffer_it) {
269-
return std::string{
270-
Consume(read_buffer_it, static_cast<std::ptrdiff_t>(symbol_cstr_len))};
281+
return Consume(read_buffer_it, static_cast<std::ptrdiff_t>(symbol_cstr_len),
282+
"symbol");
271283
}
272284

273285
std::vector<std::string> DbnDecoder::DecodeRepeatedSymbol(

0 commit comments

Comments
 (0)