diff --git a/scripts/docker/asan_check.sh b/scripts/docker/asan_check.sh index 1b4579e803..d2cddef6e5 100755 --- a/scripts/docker/asan_check.sh +++ b/scripts/docker/asan_check.sh @@ -1,9 +1,10 @@ #!/usr/bin/sh -set -ex - +shopt -s globstar +set -e BUILD_DIR=/tmp/build_asan SRC_DIR=/src LOG_DIR=/tmp/sanitize_log +SAMPLE_DIR=/tmp/samples ASAN_OPT="log_path=${LOG_DIR}" mkdir -p ${LOG_DIR} @@ -15,10 +16,12 @@ cmake -B ${BUILD_DIR} -S ${SRC_DIR} -GNinja \ ninja -C ${BUILD_DIR} sanitize_checks cd ${BUILD_DIR} -curl -LO https://github.com/lief-project/samples/raw/master/ELF/ELF64_x86-64_binary_all.bin -curl -LO https://github.com/lief-project/samples/raw/master/PE/PE64_x86-64_binary_mfc-application.exe -curl -LO https://github.com/lief-project/samples/raw/master/MachO/9edfb04c55289c6c682a25211a4b30b927a86fe50b014610d04d6055bd4ac23d_crypt_and_hash.macho -${BUILD_DIR}/tests/sanitizer/sanitize_checks ELF64_x86-64_binary_all.bin -${BUILD_DIR}/tests/sanitizer/sanitize_checks PE64_x86-64_binary_mfc-application.exe -${BUILD_DIR}/tests/sanitizer/sanitize_checks 9edfb04c55289c6c682a25211a4b30b927a86fe50b014610d04d6055bd4ac23d_crypt_and_hash.macho +mkdir -p ${SAMPLE_DIR} + +pushd ${SAMPLE_DIR} +curl -LO https://data.romainthomas.fr/lief_tests.zip +unzip lief_tests.zip +popd + +for x in ${SAMPLE_DIR}/**; do echo $x && ${BUILD_DIR}/tests/sanitizer/sanitize_checks $x; done diff --git a/src/ELF/Builder.tcc b/src/ELF/Builder.tcc index 9aff551e74..e879a37e4c 100644 --- a/src/ELF/Builder.tcc +++ b/src/ELF/Builder.tcc @@ -1208,11 +1208,18 @@ ok_error_t Builder::build_symbol_hash() { return make_error_code(lief_errors::not_found); } + uint32_t nbucket = sysv->nbucket(); uint32_t nchain = static_cast(layout_.get())->sysv_nchain(); - std::vector new_hash_table((nbucket + nchain + 2) * sizeof(uint32_t), 0); - auto *const new_hash_table_ptr = reinterpret_cast(new_hash_table.data()); + if (nbucket == 0) { + LIEF_ERR("sysv.nbucket is 0"); + return make_error_code(lief_errors::build_error); + } + + const size_t buckets_limits = nbucket + nchain + 2; + std::vector new_hash_table(buckets_limits * sizeof(uint32_t), 0); + auto* new_hash_table_ptr = reinterpret_cast(new_hash_table.data()); new_hash_table_ptr[0] = nbucket; new_hash_table_ptr[1] = nchain; @@ -1221,15 +1228,16 @@ ok_error_t Builder::build_symbol_hash() { uint32_t* chain = &new_hash_table_ptr[2 + nbucket]; uint32_t idx = 0; for (const std::unique_ptr& symbol : binary_->dynamic_symbols_) { - uint32_t hash = 0; + uint32_t hash = binary_->type_ == ELF_CLASS::ELFCLASS32 ? + hash32(symbol->name().c_str()) : + hash64(symbol->name().c_str()); - if (binary_->type_ == ELF_CLASS::ELFCLASS32) { - hash = hash32(symbol->name().c_str()); - } else { - hash = hash64(symbol->name().c_str()); + const size_t bucket_idx = hash % nbucket; + if (bucket_idx >= buckets_limits) { + LIEF_WARN("Bucket {} is out of range", bucket_idx); + continue; } - - if (bucket[hash % nbucket] == 0) { + if (bucket[bucket_idx] == 0) { bucket[hash % nbucket] = idx; } else { uint32_t value = bucket[hash % nbucket]; @@ -1247,7 +1255,7 @@ ok_error_t Builder::build_symbol_hash() { // to be improved...? if (should_swap()) { - for (size_t i = 0; i < nbucket + nchain + 2; i++) { + for (size_t i = 0; i < buckets_limits; i++) { Convert::swap_endian(&new_hash_table_ptr[i]); } } diff --git a/src/MachO/Builder.tcc b/src/MachO/Builder.tcc index 9ddbf51051..a3994893e5 100644 --- a/src/MachO/Builder.tcc +++ b/src/MachO/Builder.tcc @@ -78,7 +78,8 @@ ok_error_t Builder::build_segments() { const auto& content = segment.content(); if (content.size() != segment.file_size()) { - LIEF_ERR("content.size() != segment.file_size()"); + LIEF_ERR("{} content size and file_size are differents: 0x{:x} vs 0x{:x}", + segment.name(), content.size(), segment.file_size()); return make_error_code(lief_errors::build_error); } diff --git a/src/MachO/SegmentCommand.cpp b/src/MachO/SegmentCommand.cpp index 7a03916a8d..106a89a813 100644 --- a/src/MachO/SegmentCommand.cpp +++ b/src/MachO/SegmentCommand.cpp @@ -412,7 +412,14 @@ void SegmentCommand::content_resize(size_t size) { void SegmentCommand::content_insert(size_t where, size_t size) { update_data([] (std::vector& inner_data, size_t w, size_t s) { - inner_data.insert(std::begin(inner_data) + w, s, 0); + if (s == 0) { + return; + } + if (w < inner_data.size()) { + inner_data.insert(std::begin(inner_data) + w, s, 0); + } else { + inner_data.resize(inner_data.size() + w + s, 0); + } }, where, size); }