leveldb
leveldb copied to clipboard
Null Pointer Dereference Vulnerability in leveldb_open
Description
The leveldb_open
function in LevelDB is vulnerable to a null pointer dereference issue, where it directly converts a const char* name
to a std::string
without null checks. This can lead to a std::logic_error
being thrown if name
is nullptr
.
Steps to Reproduce
- Call
leveldb_open
withname
set tonullptr
. - Observe a crash due to unhandled
std::logic_error
.
Expected Behavior
The function should handle nullptr
inputs gracefully, either by returning an error or by rejecting the operation without crashing.
Suggested Fix
Implement a null check before using the name
variable:
if (name == nullptr) {
if (errptr != nullptr) {
*errptr = strdup("Database name is null");
}
return nullptr;
}
##My Fuzzer
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
leveldb_options_t* options = nullptr;
const char* path = nullptr;
char** error = nullptr;
leveldb_t* db = leveldb_open(options, path, error);
if (db != nullptr) {
leveldb_create_snapshot(db);
}
return 0;
}
root@2300d4f25744:/volume/PromptDriver# ./results/leveldb/fuzzer/Test_leveldb_Id56 ./results/leveldb/fuzzing/run1/out/Test_leveldb_Id56crash-da39a3ee5e6b4b0d3255bfef95601890afd80709
INFO: Seed: 1250284794
INFO: Loaded 1 modules (5466 inline 8-bit counters): 5466 [0x703f3f, 0x705499),
INFO: Loaded 1 PC tables (5466 PCs): 5466 [0x68d6d0,0x6a2c70),
./results/leveldb/fuzzer/Test_leveldb_Id56: Running 1 inputs 1 time(s) each.
Running: ./results/leveldb/fuzzing/run1/out/Test_leveldb_Id56crash-da39a3ee5e6b4b0d3255bfef95601890afd80709
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_M_construct null not valid
==325550== ERROR: libFuzzer: deadly signal
#0 0x5292b1 in __sanitizer_print_stack_trace (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x5292b1)
#1 0x474418 in fuzzer::PrintStackTrace() (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x474418)
#2 0x459563 in fuzzer::Fuzzer::CrashCallback() (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x459563)
#3 0x7fd3a5ac241f (/lib/x86_64-linux-gnu/libpthread.so.0+0x1441f)
#4 0x7fd3a58d200a in raise (/lib/x86_64-linux-gnu/libc.so.6+0x4300a)
#5 0x7fd3a58b1858 in abort (/lib/x86_64-linux-gnu/libc.so.6+0x22858)
#6 0x7fd3a5cbe8d0 (/lib/x86_64-linux-gnu/libstdc++.so.6+0x9e8d0)
#7 0x7fd3a5cca37b (/lib/x86_64-linux-gnu/libstdc++.so.6+0xaa37b)
#8 0x7fd3a5cca3e6 in std::terminate() (/lib/x86_64-linux-gnu/libstdc++.so.6+0xaa3e6)
#9 0x7fd3a5cca698 in __cxa_throw (/lib/x86_64-linux-gnu/libstdc++.so.6+0xaa698)
#10 0x7fd3a5cc11db in std::__throw_logic_error(char const*) (/lib/x86_64-linux-gnu/libstdc++.so.6+0xa11db)
#11 0x7fd3a5d65d9a in void std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char const*>(char const*, char const*, std::forward_iterator_tag) (/lib/x86_64-linux-gnu/libstdc++.so.6+0x145d9a)
#12 0x552aaf in leveldb_open /mnt/UTopia/exp/leveldb/src/db/c.cc:171:48
#13 0x55281e in LLVMFuzzerTestOneInput /mnt/PromptDriver/results/leveldb/driver/Test_leveldb_Id56.cc:52:19
#14 0x45ac21 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x45ac21)
#15 0x446392 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x446392)
#16 0x44be46 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x44be46)
#17 0x474b02 in main (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x474b02)
#18 0x7fd3a58b3082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
#19 0x420a3d in _start (/volume/PromptDriver/results/leveldb/fuzzer/Test_leveldb_Id56+0x420a3d)
NOTE: libFuzzer has rudimentary signal handlers.
Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal