fix backup meta-file buffer overrun

Summary:
- check most times after calling snprintf that the buffer didn't fill up. Previously we'd proceed and use `buf_size - len` as the length in subsequent calls, which underflowed as those are unsigned size_t.
- replace some memcpys with snprintf for consistency
Closes https://github.com/facebook/rocksdb/pull/3255

Differential Revision: D6541464

Pulled By: ajkr

fbshipit-source-id: 8610ea6a24f38e0a37c6d17bc65b7c712da6d932
main
Andrew Kryczka 7 years ago committed by Facebook Github Bot
parent 5a7e08468a
commit a79c7c05e8
  1. 18
      utilities/backupable/backupable_db.cc

@ -1722,23 +1722,25 @@ Status BackupEngineImpl::BackupMeta::StoreToFile(bool sync) {
if (!app_metadata_.empty()) { if (!app_metadata_.empty()) {
std::string hex_encoded_metadata = std::string hex_encoded_metadata =
Slice(app_metadata_).ToString(/* hex */ true); Slice(app_metadata_).ToString(/* hex */ true);
if (hex_encoded_metadata.size() + kMetaDataPrefix.size() + 1 > len += snprintf(buf.get() + len, buf_size - len, "%s%s\n",
buf_size - len) { kMetaDataPrefix.ToString().c_str(),
hex_encoded_metadata.c_str());
if (len >= buf_size) {
return Status::Corruption("Buffer too small to fit backup metadata"); return Status::Corruption("Buffer too small to fit backup metadata");
} }
memcpy(buf.get() + len, kMetaDataPrefix.data(), kMetaDataPrefix.size());
len += kMetaDataPrefix.size();
memcpy(buf.get() + len, hex_encoded_metadata.data(),
hex_encoded_metadata.size());
len += hex_encoded_metadata.size();
buf[len++] = '\n';
} }
len += snprintf(buf.get() + len, buf_size - len, "%" ROCKSDB_PRIszt "\n", len += snprintf(buf.get() + len, buf_size - len, "%" ROCKSDB_PRIszt "\n",
files_.size()); files_.size());
if (len >= buf_size) {
return Status::Corruption("Buffer too small to fit backup metadata");
}
for (const auto& file : files_) { for (const auto& file : files_) {
// use crc32 for now, switch to something else if needed // use crc32 for now, switch to something else if needed
len += snprintf(buf.get() + len, buf_size - len, "%s crc32 %u\n", len += snprintf(buf.get() + len, buf_size - len, "%s crc32 %u\n",
file->filename.c_str(), file->checksum_value); file->filename.c_str(), file->checksum_value);
if (len >= buf_size) {
return Status::Corruption("Buffer too small to fit backup metadata");
}
} }
s = backup_meta_file->Append(Slice(buf.get(), len)); s = backup_meta_file->Append(Slice(buf.get(), len));

Loading…
Cancel
Save