Fix clang analyzer errors

Summary:
Fixing erros reported by clang static analyzer.
* Removing some unused variables.
* Adding assertions to fix false positives reported by clang analyzer.
* Adding `__clang_analyzer__` macro to suppress false positive warnings.

Test Plan:
    USE_CLANG=1 OPT=-g make analyze -j64

Reviewers: andrewkr, sdong

Reviewed By: sdong

Subscribers: andrewkr, dhruba, leveldb

Differential Revision: https://reviews.facebook.net/D60549
This commit is contained in:
Yi Wu 2016-07-08 17:50:51 -07:00
parent 61dbfbb6ce
commit 296545a2c7
15 changed files with 42 additions and 18 deletions

View File

@ -292,9 +292,6 @@ Status FlushJob::WriteLevel0Table(const autovector<MemTable*>& mems,
} }
base->Unref(); base->Unref();
// re-acquire the most current version
base = cfd_->current();
// Note that if file_size is zero, the file has been deleted and // Note that if file_size is zero, the file has been deleted and
// should not be added to the manifest. // should not be added to the manifest.
if (s.ok() && meta->fd.GetFileSize() > 0) { if (s.ok() && meta->fd.GetFileSize() > 0) {

View File

@ -20,6 +20,8 @@ void FlushScheduler::ScheduleFlush(ColumnFamilyData* cfd) {
} }
#endif // NDEBUG #endif // NDEBUG
cfd->Ref(); cfd->Ref();
// Suppress false positive clang analyzer warnings.
#ifndef __clang_analyzer__
Node* node = new Node{cfd, head_.load(std::memory_order_relaxed)}; Node* node = new Node{cfd, head_.load(std::memory_order_relaxed)};
while (!head_.compare_exchange_strong( while (!head_.compare_exchange_strong(
node->next, node, std::memory_order_relaxed, std::memory_order_relaxed)) { node->next, node, std::memory_order_relaxed, std::memory_order_relaxed)) {
@ -28,6 +30,7 @@ void FlushScheduler::ScheduleFlush(ColumnFamilyData* cfd) {
// inter-thread synchronization, so we don't even need release // inter-thread synchronization, so we don't even need release
// semantics for this CAS // semantics for this CAS
} }
#endif // __clang_analyzer__
} }
ColumnFamilyData* FlushScheduler::TakeNextColumnFamily() { ColumnFamilyData* FlushScheduler::TakeNextColumnFamily() {

View File

@ -91,7 +91,7 @@ bool Reader::ReadRecord(Slice* record, std::string* scratch,
Slice fragment; Slice fragment;
while (true) { while (true) {
uint64_t physical_record_offset = end_of_buffer_offset_ - buffer_.size(); uint64_t physical_record_offset = end_of_buffer_offset_ - buffer_.size();
size_t drop_size; size_t drop_size = 0;
const unsigned int record_type = ReadPhysicalRecord(&fragment, &drop_size); const unsigned int record_type = ReadPhysicalRecord(&fragment, &drop_size);
switch (record_type) { switch (record_type) {
case kFullType: case kFullType:
@ -199,10 +199,11 @@ bool Reader::ReadRecord(Slice* record, std::string* scratch,
scratch->clear(); scratch->clear();
return false; return false;
} }
if (record_type == kBadRecordLen) if (record_type == kBadRecordLen) {
ReportCorruption(drop_size, "bad record length"); ReportCorruption(drop_size, "bad record length");
else } else {
ReportCorruption(drop_size, "checksum mismatch"); ReportCorruption(drop_size, "checksum mismatch");
}
if (in_fragmented_record) { if (in_fragmented_record) {
ReportCorruption(scratch->size(), "error in middle of record"); ReportCorruption(scratch->size(), "error in middle of record");
in_fragmented_record = false; in_fragmented_record = false;
@ -343,7 +344,7 @@ unsigned int Reader::ReadPhysicalRecord(Slice* result, size_t* drop_size) {
if (buffer_.size() < (size_t)kHeaderSize) { if (buffer_.size() < (size_t)kHeaderSize) {
int r; int r;
if (!ReadMore(drop_size, &r)) { if (!ReadMore(drop_size, &r)) {
return r; return r;
} }
continue; continue;
} }
@ -362,11 +363,11 @@ unsigned int Reader::ReadPhysicalRecord(Slice* result, size_t* drop_size) {
header_size = kRecyclableHeaderSize; header_size = kRecyclableHeaderSize;
// We need enough for the larger header // We need enough for the larger header
if (buffer_.size() < (size_t)kRecyclableHeaderSize) { if (buffer_.size() < (size_t)kRecyclableHeaderSize) {
int r; int r;
if (!ReadMore(drop_size, &r)) { if (!ReadMore(drop_size, &r)) {
return r; return r;
} }
continue; continue;
} }
const uint32_t log_num = DecodeFixed32(header + 7); const uint32_t log_num = DecodeFixed32(header + 7);
if (log_num != log_number_) { if (log_num != log_number_) {

View File

@ -26,6 +26,7 @@ Status MergeHelper::TimedFullMerge(const MergeOperator* merge_operator,
assert(merge_operator != nullptr); assert(merge_operator != nullptr);
if (operands.size() == 0) { if (operands.size() == 0) {
assert(value != nullptr && result != nullptr);
result->assign(value->data(), value->size()); result->assign(value->data(), value->size());
return Status::OK(); return Status::OK();
} }

View File

@ -2746,7 +2746,7 @@ Status VersionSet::Recover(
} }
} }
for (auto builder : builders) { for (auto& builder : builders) {
delete builder.second; delete builder.second;
} }

View File

@ -73,7 +73,7 @@ void BlockIter::Prev() {
const CachedPrevEntry& current_prev_entry = const CachedPrevEntry& current_prev_entry =
prev_entries_[prev_entries_idx_]; prev_entries_[prev_entries_idx_];
const char* key_ptr = current_prev_entry.key_ptr; const char* key_ptr = nullptr;
if (current_prev_entry.key_ptr != nullptr) { if (current_prev_entry.key_ptr != nullptr) {
// The key is not delta encoded and stored in the data block // The key is not delta encoded and stored in the data block
key_ptr = current_prev_entry.key_ptr; key_ptr = current_prev_entry.key_ptr;

View File

@ -1052,6 +1052,7 @@ InternalIterator* BlockBasedTable::NewIndexIterator(
Status s; Status s;
s = CreateIndexReader(&index_reader); s = CreateIndexReader(&index_reader);
if (s.ok()) { if (s.ok()) {
assert(index_reader != nullptr);
s = block_cache->Insert(key, index_reader, index_reader->usable_size(), s = block_cache->Insert(key, index_reader, index_reader->usable_size(),
&DeleteCachedIndexEntry, &cache_handle); &DeleteCachedIndexEntry, &cache_handle);
} }
@ -1062,6 +1063,9 @@ InternalIterator* BlockBasedTable::NewIndexIterator(
RecordTick(statistics, BLOCK_CACHE_BYTES_WRITE, usable_size); RecordTick(statistics, BLOCK_CACHE_BYTES_WRITE, usable_size);
RecordTick(statistics, BLOCK_CACHE_INDEX_BYTES_INSERT, usable_size); RecordTick(statistics, BLOCK_CACHE_INDEX_BYTES_INSERT, usable_size);
} else { } else {
if (index_reader != nullptr) {
delete index_reader;
}
RecordTick(statistics, BLOCK_CACHE_ADD_FAILURES); RecordTick(statistics, BLOCK_CACHE_ADD_FAILURES);
// make sure if something goes wrong, index_reader shall remain intact. // make sure if something goes wrong, index_reader shall remain intact.
if (input_iter != nullptr) { if (input_iter != nullptr) {
@ -1189,7 +1193,8 @@ InternalIterator* BlockBasedTable::NewDataBlockIterator(
} }
InternalIterator* iter; InternalIterator* iter;
if (s.ok() && block.value != nullptr) { if (s.ok()) {
assert(block.value != nullptr);
iter = block.value->NewIterator(&rep->internal_comparator, input_iter); iter = block.value->NewIterator(&rep->internal_comparator, input_iter);
if (block.cache_handle != nullptr) { if (block.cache_handle != nullptr) {
iter->RegisterCleanup(&ReleaseCachedEntry, block_cache, iter->RegisterCleanup(&ReleaseCachedEntry, block_cache,
@ -1198,6 +1203,7 @@ InternalIterator* BlockBasedTable::NewDataBlockIterator(
iter->RegisterCleanup(&DeleteHeldResource<Block>, block.value, nullptr); iter->RegisterCleanup(&DeleteHeldResource<Block>, block.value, nullptr);
} }
} else { } else {
assert(block.value == nullptr);
if (input_iter != nullptr) { if (input_iter != nullptr) {
input_iter->SetStatus(s); input_iter->SetStatus(s);
iter = input_iter; iter = input_iter;

View File

@ -136,6 +136,7 @@ class BlockPrefixIndex::Builder {
assert(prefixes_per_bucket[i]->next == nullptr); assert(prefixes_per_bucket[i]->next == nullptr);
buckets[i] = prefixes_per_bucket[i]->start_block; buckets[i] = prefixes_per_bucket[i]->start_block;
} else { } else {
assert(total_block_array_entries > 0);
assert(prefixes_per_bucket[i] != nullptr); assert(prefixes_per_bucket[i] != nullptr);
buckets[i] = EncodeIndex(offset); buckets[i] = EncodeIndex(offset);
block_array_buffer[offset] = num_blocks; block_array_buffer[offset] = num_blocks;

View File

@ -1765,7 +1765,6 @@ TEST_F(BlockBasedTableTest, FilterBlockInBlockCache) {
ASSERT_GT(props.GetCacheBytesRead(), last_cache_bytes_read); ASSERT_GT(props.GetCacheBytesRead(), last_cache_bytes_read);
ASSERT_EQ(props.GetCacheBytesWrite(), ASSERT_EQ(props.GetCacheBytesWrite(),
table_options.block_cache->GetUsage()); table_options.block_cache->GetUsage());
last_cache_bytes_read = props.GetCacheBytesRead();
} }
// release the iterator so that the block cache can reset correctly. // release the iterator so that the block cache can reset correctly.
iter.reset(); iter.reset();

View File

@ -34,6 +34,9 @@
// Sometimes it's desirable to build Google Test by compiling a single file. // Sometimes it's desirable to build Google Test by compiling a single file.
// This file serves this purpose. // This file serves this purpose.
// Suppress clang analyzer warnings.
#ifndef __clang_analyzer__
// This line ensures that gtest.h can be compiled on its own, even // This line ensures that gtest.h can be compiled on its own, even
// when it's fused. // when it's fused.
#include "gtest/gtest.h" #include "gtest/gtest.h"
@ -109,7 +112,6 @@
#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ #ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ #define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
namespace testing { namespace testing {
// This helper class can be used to mock out Google Test failure reporting // This helper class can be used to mock out Google Test failure reporting
@ -10255,3 +10257,5 @@ const char* TypedTestCasePState::VerifyRegisteredTestNames(
} // namespace internal } // namespace internal
} // namespace testing } // namespace testing
#endif // __clang_analyzer__

View File

@ -230,6 +230,9 @@ class SanityTestBloomFilter : public SanityTest {
namespace { namespace {
bool RunSanityTests(const std::string& command, const std::string& path) { bool RunSanityTests(const std::string& command, const std::string& path) {
bool result = true;
// Suppress false positive clang static anaylzer warnings.
#ifndef __clang_analyzer__
std::vector<SanityTest*> sanity_tests = { std::vector<SanityTest*> sanity_tests = {
new SanityTestBasic(path), new SanityTestBasic(path),
new SanityTestSpecialComparator(path), new SanityTestSpecialComparator(path),
@ -248,7 +251,6 @@ bool RunSanityTests(const std::string& command, const std::string& path) {
} else { } else {
fprintf(stderr, "Verifying...\n"); fprintf(stderr, "Verifying...\n");
} }
bool result = true;
for (auto sanity_test : sanity_tests) { for (auto sanity_test : sanity_tests) {
Status s; Status s;
fprintf(stderr, "%s -- ", sanity_test->Name().c_str()); fprintf(stderr, "%s -- ", sanity_test->Name().c_str());
@ -266,6 +268,7 @@ bool RunSanityTests(const std::string& command, const std::string& path) {
delete sanity_test; delete sanity_test;
} }
#endif // __clang_analyzer__
return result; return result;
} }
} // namespace } // namespace

View File

@ -201,6 +201,7 @@ TEST_F(DynamicBloomTest, perf) {
} }
ASSERT_EQ(count, num_keys); ASSERT_EQ(count, num_keys);
elapsed = timer.ElapsedNanos(); elapsed = timer.ElapsedNanos();
assert(count > 0);
fprintf(stderr, "standard bloom, avg query latency %" PRIu64 "\n", fprintf(stderr, "standard bloom, avg query latency %" PRIu64 "\n",
elapsed / count); elapsed / count);
@ -227,6 +228,7 @@ TEST_F(DynamicBloomTest, perf) {
} }
elapsed = timer.ElapsedNanos(); elapsed = timer.ElapsedNanos();
assert(count > 0);
fprintf(stderr, fprintf(stderr,
"blocked bloom(enable locality), avg query latency %" PRIu64 "\n", "blocked bloom(enable locality), avg query latency %" PRIu64 "\n",
elapsed / count); elapsed / count);

View File

@ -756,6 +756,7 @@ Status RocksDBOptionsParser::VerifyBlockBasedTableFactory(
if (base_tf == nullptr) { if (base_tf == nullptr) {
return Status::OK(); return Status::OK();
} }
assert(file_tf != nullptr);
const auto& base_opt = base_tf->table_options(); const auto& base_opt = base_tf->table_options();
const auto& file_opt = file_tf->table_options(); const auto& file_opt = file_tf->table_options();

View File

@ -57,6 +57,8 @@ class IDChecker : public ThreadLocalPtr {
} // anonymous namespace } // anonymous namespace
// Suppress false positive clang analyzer warnings.
#ifndef __clang_analyzer__
TEST_F(ThreadLocalTest, UniqueIdTest) { TEST_F(ThreadLocalTest, UniqueIdTest) {
port::Mutex mu; port::Mutex mu;
port::CondVar cv(&mu); port::CondVar cv(&mu);
@ -103,6 +105,7 @@ TEST_F(ThreadLocalTest, UniqueIdTest) {
// After exit, id sequence in queue: // After exit, id sequence in queue:
// 3, 1, 2, 0 // 3, 1, 2, 0
} }
#endif // __clang_analyzer__
TEST_F(ThreadLocalTest, SequentialReadWriteTest) { TEST_F(ThreadLocalTest, SequentialReadWriteTest) {
// global id list carries over 3, 1, 2, 0 // global id list carries over 3, 1, 2, 0

View File

@ -226,6 +226,8 @@ class BaseDeltaIterator : public Iterator {
bool BaseValid() const { return base_iterator_->Valid(); } bool BaseValid() const { return base_iterator_->Valid(); }
bool DeltaValid() const { return delta_iterator_->Valid(); } bool DeltaValid() const { return delta_iterator_->Valid(); }
void UpdateCurrent() { void UpdateCurrent() {
// Suppress false positive clang analyzer warnings.
#ifndef __clang_analyzer__
while (true) { while (true) {
WriteEntry delta_entry; WriteEntry delta_entry;
if (DeltaValid()) { if (DeltaValid()) {
@ -275,6 +277,7 @@ class BaseDeltaIterator : public Iterator {
} }
AssertInvariants(); AssertInvariants();
#endif // __clang_analyzer__
} }
bool forward_; bool forward_;