diff --git a/.gitignore b/.gitignore index 6aee57ace..a485dce54 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,7 @@ shlib-exports-*.txt /test/sam /test/ref_cache/*.tmp.* /test/tabix/*.tmp.* +/test/test_alloc /test/test-bcf-sr /test/test-bcf-translate /test/test-bcf_set_variant_type diff --git a/Makefile b/Makefile index 6eab6ca6e..ddbfff899 100644 --- a/Makefile +++ b/Makefile @@ -81,6 +81,7 @@ BUILT_TEST_PROGRAMS = \ test/pileup_mod \ test/plugins-dlhts \ test/sam \ + test/test_alloc \ test/test_bgzf \ test/test_expr \ test/test_faidx \ @@ -494,49 +495,49 @@ hts-object-files: $(LIBHTS_OBJS) $(CC) -shared $(LDFLAGS) -o $@ $< hts.dll.a $(LIBS) -bgzf.o bgzf.pico: bgzf.c config.h $(htslib_hts_h) $(htslib_bgzf_h) $(htslib_hfile_h) $(htslib_thread_pool_h) $(htslib_hts_endian_h) cram/pooled_alloc.h $(hts_internal_h) $(bgzf_internal_h) $(htslib_khash_h) +bgzf.o bgzf.pico: bgzf.c config.h $(htslib_hts_h) $(htslib_bgzf_h) $(htslib_hfile_h) $(htslib_thread_pool_h) $(htslib_hts_alloc_h) $(htslib_hts_endian_h) cram/pooled_alloc.h $(hts_internal_h) $(bgzf_internal_h) $(htslib_khash_h) errmod.o errmod.pico: errmod.c config.h $(htslib_hts_h) $(htslib_ksort_h) $(htslib_hts_os_h) -kstring.o kstring.pico: kstring.c config.h $(htslib_kstring_h) -header.o header.pico: header.c config.h $(textutils_internal_h) $(header_h) $(htslib_bgzf_h) $(htslib_hfile_h) $(htslib_kseq_h) +kstring.o kstring.pico: kstring.c config.h $(htslib_kstring_h) $(htslib_hts_alloc_h) +header.o header.pico: header.c config.h $(textutils_internal_h) $(header_h) $(htslib_bgzf_h) $(htslib_hfile_h) $(htslib_hts_alloc_h) $(htslib_kseq_h) hfile.o hfile.pico: hfile.c config.h $(htslib_hfile_h) $(hfile_internal_h) $(htslib_kstring_h) $(hts_internal_h) $(htslib_khash_h) hfile_gcs.o hfile_gcs.pico: hfile_gcs.c config.h $(htslib_hts_h) $(htslib_kstring_h) $(hfile_internal_h) -hfile_libcurl.o hfile_libcurl.pico: hfile_libcurl.c config.h $(hfile_internal_h) $(htslib_hts_h) $(htslib_kstring_h) $(htslib_khash_h) -hfile_s3.o hfile_s3.pico: hfile_s3.c config.h $(hfile_internal_h) $(htslib_hts_h) $(htslib_kstring_h) $(hts_time_funcs_h) -hts.o hts.pico: hts.c config.h os/lzma_stub.h $(htslib_hts_h) $(htslib_bgzf_h) $(cram_h) $(htslib_hfile_h) $(htslib_hts_endian_h) version.h config_vars.h $(hts_internal_h) $(hfile_internal_h) $(sam_internal_h) $(htslib_hts_expr_h) $(htslib_hts_os_h) $(htslib_khash_h) $(htslib_kseq_h) $(htslib_ksort_h) $(htslib_tbx_h) $(htscodecs_htscodecs_h) -hts_expr.o hts_expr.pico: hts_expr.c config.h $(htslib_hts_expr_h) $(htslib_hts_log_h) $(textutils_internal_h) +hfile_libcurl.o hfile_libcurl.pico: hfile_libcurl.c config.h $(hfile_internal_h) $(htslib_hts_h) $(htslib_hts_alloc_h) $(htslib_kstring_h) $(htslib_khash_h) +hfile_s3.o hfile_s3.pico: hfile_s3.c config.h $(hfile_internal_h) $(htslib_hts_h) $(htslib_hts_alloc_h) $(htslib_kstring_h) $(hts_time_funcs_h) +hts.o hts.pico: hts.c config.h os/lzma_stub.h $(htslib_hts_h) $(htslib_bgzf_h) $(cram_h) $(htslib_hfile_h) $(htslib_hts_endian_h) version.h config_vars.h $(hts_internal_h) $(hfile_internal_h) $(sam_internal_h) $(htslib_hts_alloc_h) $(htslib_hts_expr_h) $(htslib_hts_os_h) $(htslib_khash_h) $(htslib_kseq_h) $(htslib_ksort_h) $(htslib_tbx_h) $(htscodecs_htscodecs_h) +hts_expr.o hts_expr.pico: hts_expr.c config.h $(htslib_hts_expr_h) $(htslib_hts_alloc_h) $(htslib_hts_log_h) $(textutils_internal_h) hts_os.o hts_os.pico: hts_os.c config.h $(htslib_hts_defs_h) os/rand.c -vcf.o vcf.pico: vcf.c config.h $(fuzz_settings_h) $(htslib_vcf_h) $(htslib_bgzf_h) $(htslib_tbx_h) $(htslib_hfile_h) $(hts_internal_h) $(htslib_khash_str2int_h) $(htslib_kstring_h) $(htslib_sam_h) $(htslib_khash_h) $(htslib_kseq_h) $(htslib_hts_endian_h) $(bgzf_internal_h) -sam.o sam.pico: sam.c config.h $(fuzz_settings_h) $(htslib_hts_defs_h) $(htslib_sam_h) $(htslib_bgzf_h) $(cram_h) $(hts_internal_h) $(sam_internal_h) $(htslib_hfile_h) $(htslib_hts_endian_h) $(htslib_hts_expr_h) $(header_h) $(htslib_khash_h) $(htslib_kseq_h) $(htslib_kstring_h) +vcf.o vcf.pico: vcf.c config.h $(fuzz_settings_h) $(htslib_vcf_h) $(htslib_bgzf_h) $(htslib_tbx_h) $(htslib_hfile_h) $(hts_internal_h) $(htslib_hts_alloc_h) $(htslib_hts_endian_h) $(htslib_khash_str2int_h) $(htslib_kstring_h) $(htslib_sam_h) $(htslib_khash_h) $(htslib_kseq_h) $(bgzf_internal_h) +sam.o sam.pico: sam.c config.h $(fuzz_settings_h) $(htslib_hts_defs_h) $(htslib_sam_h) $(htslib_bgzf_h) $(cram_h) $(hts_internal_h) $(sam_internal_h) $(htslib_hfile_h) $(htslib_hts_alloc_h) $(htslib_hts_endian_h) $(htslib_hts_expr_h) $(header_h) $(htslib_khash_h) $(htslib_kseq_h) $(htslib_kstring_h) sam_mods.o sam_mods.pico: sam_mods.c config.h $(htslib_sam_h) $(textutils_internal_h) simd.o simd.pico: simd.c config.h $(htslib_sam_h) $(sam_internal_h) -tbx.o tbx.pico: tbx.c config.h $(htslib_tbx_h) $(htslib_bgzf_h) $(htslib_hts_endian_h) $(hts_internal_h) $(htslib_khash_h) -faidx.o faidx.pico: faidx.c config.h $(htslib_bgzf_h) $(htslib_faidx_h) $(htslib_hfile_h) $(htslib_khash_h) $(htslib_kstring_h) $(hts_internal_h) -bcf_sr_sort.o bcf_sr_sort.pico: bcf_sr_sort.c config.h $(bcf_sr_sort_h) $(htslib_khash_str2int_h) $(htslib_kbitset_h) -synced_bcf_reader.o synced_bcf_reader.pico: synced_bcf_reader.c config.h $(htslib_synced_bcf_reader_h) $(htslib_kseq_h) $(htslib_khash_str2int_h) $(htslib_bgzf_h) $(htslib_thread_pool_h) $(bcf_sr_sort_h) +tbx.o tbx.pico: tbx.c config.h $(htslib_tbx_h) $(htslib_bgzf_h) $(htslib_hts_alloc_h) $(htslib_hts_endian_h) $(hts_internal_h) $(htslib_khash_h) +faidx.o faidx.pico: faidx.c config.h $(htslib_bgzf_h) $(htslib_faidx_h) $(htslib_hfile_h) $(htslib_hts_alloc_h) $(htslib_khash_h) $(htslib_kstring_h) $(hts_internal_h) +bcf_sr_sort.o bcf_sr_sort.pico: bcf_sr_sort.c config.h $(bcf_sr_sort_h) $(htslib_khash_str2int_h) $(htslib_kbitset_h) $(htslib_hts_alloc_h) +synced_bcf_reader.o synced_bcf_reader.pico: synced_bcf_reader.c config.h $(htslib_synced_bcf_reader_h) $(htslib_kseq_h) $(htslib_khash_str2int_h) $(htslib_bgzf_h) $(htslib_hts_alloc_h) $(htslib_thread_pool_h) $(bcf_sr_sort_h) vcf_sweep.o vcf_sweep.pico: vcf_sweep.c config.h $(htslib_vcf_sweep_h) $(htslib_bgzf_h) -vcfutils.o vcfutils.pico: vcfutils.c config.h $(htslib_vcfutils_h) $(htslib_kbitset_h) +vcfutils.o vcfutils.pico: vcfutils.c config.h $(htslib_vcfutils_h) $(htslib_hts_alloc_h) $(htslib_kbitset_h) kfunc.o kfunc.pico: kfunc.c config.h $(htslib_kfunc_h) -regidx.o regidx.pico: regidx.c config.h $(htslib_hts_h) $(htslib_kstring_h) $(htslib_kseq_h) $(htslib_khash_str2int_h) $(htslib_regidx_h) $(hts_internal_h) +regidx.o regidx.pico: regidx.c config.h $(htslib_hts_h) $(htslib_hts_alloc_h) $(htslib_kstring_h) $(htslib_kseq_h) $(htslib_khash_str2int_h) $(htslib_regidx_h) $(hts_internal_h) region.o region.pico: region.c config.h $(htslib_hts_h) $(htslib_khash_h) md5.o md5.pico: md5.c config.h $(htslib_hts_h) $(htslib_hts_endian_h) multipart.o multipart.pico: multipart.c config.h $(htslib_kstring_h) $(hts_internal_h) $(hfile_internal_h) plugin.o plugin.pico: plugin.c config.h $(hts_internal_h) $(htslib_kstring_h) -probaln.o probaln.pico: probaln.c config.h $(htslib_hts_h) -realn.o realn.pico: realn.c config.h $(htslib_hts_h) $(htslib_sam_h) +probaln.o probaln.pico: probaln.c config.h $(htslib_hts_h) $(htslib_hts_alloc_h) +realn.o realn.pico: realn.c config.h $(htslib_hts_h) $(htslib_hts_alloc_h) $(htslib_sam_h) textutils.o textutils.pico: textutils.c config.h $(htslib_hfile_h) $(htslib_kstring_h) $(htslib_sam_h) $(hts_internal_h) -cram/cram_codecs.o cram/cram_codecs.pico: cram/cram_codecs.c config.h $(fuzz_settings_h) $(htslib_hts_endian_h) $(htscodecs_varint_h) $(htscodecs_pack_h) $(htscodecs_rle_h) $(cram_h) -cram/cram_decode.o cram/cram_decode.pico: cram/cram_decode.c config.h $(cram_h) $(cram_os_h) $(htslib_hts_h) $(htslib_hfile_h) -cram/cram_encode.o cram/cram_encode.pico: cram/cram_encode.c config.h $(cram_h) $(cram_os_h) $(sam_internal_h) $(htslib_hts_h) $(htslib_hts_endian_h) $(textutils_internal_h) -cram/cram_external.o cram/cram_external.pico: cram/cram_external.c config.h $(htscodecs_rANS_static4x16_h) $(htslib_hfile_h) $(cram_h) -cram/cram_index.o cram/cram_index.pico: cram/cram_index.c config.h $(htslib_bgzf_h) $(htslib_hfile_h) $(hts_internal_h) $(cram_h) $(cram_os_h) -cram/cram_io.o cram/cram_io.pico: cram/cram_io.c config.h os/lzma_stub.h $(fuzz_settings_h) $(cram_h) $(cram_os_h) $(htslib_hts_h) $(hts_internal_h) $(cram_open_trace_file_h) $(htscodecs_rANS_static_h) $(htscodecs_rANS_static4x16_h) $(htscodecs_arith_dynamic_h) $(htscodecs_tokenise_name3_h) $(htscodecs_fqzcomp_qual_h) $(htscodecs_varint_h) $(htslib_hfile_h) $(htslib_bgzf_h) $(htslib_faidx_h) $(hts_internal_h) -cram/cram_stats.o cram/cram_stats.pico: cram/cram_stats.c config.h $(cram_h) $(cram_os_h) +cram/cram_codecs.o cram/cram_codecs.pico: cram/cram_codecs.c config.h $(fuzz_settings_h) $(htslib_hts_alloc_h) $(htslib_hts_endian_h) $(htscodecs_varint_h) $(htscodecs_pack_h) $(htscodecs_rle_h) $(cram_h) +cram/cram_decode.o cram/cram_decode.pico: cram/cram_decode.c config.h $(cram_h) $(cram_os_h) $(htslib_hts_h) $(htslib_hts_alloc_h) $(htslib_hfile_h) +cram/cram_encode.o cram/cram_encode.pico: cram/cram_encode.c config.h $(cram_h) $(cram_os_h) $(sam_internal_h) $(htslib_hts_h) $(htslib_hts_alloc_h) $(htslib_hts_endian_h) $(textutils_internal_h) +cram/cram_external.o cram/cram_external.pico: cram/cram_external.c config.h $(htscodecs_rANS_static4x16_h) $(htslib_hfile_h) $(htslib_hts_alloc_h) $(cram_h) +cram/cram_index.o cram/cram_index.pico: cram/cram_index.c config.h $(htslib_bgzf_h) $(htslib_hfile_h) $(htslib_hts_alloc_h) $(hts_internal_h) $(cram_h) $(cram_os_h) +cram/cram_io.o cram/cram_io.pico: cram/cram_io.c config.h os/lzma_stub.h $(fuzz_settings_h) $(cram_h) $(cram_os_h) $(htslib_hts_h) $(htslib_hts_alloc_h) $(hts_internal_h) $(cram_open_trace_file_h) $(htscodecs_rANS_static_h) $(htscodecs_rANS_static4x16_h) $(htscodecs_arith_dynamic_h) $(htscodecs_tokenise_name3_h) $(htscodecs_fqzcomp_qual_h) $(htscodecs_varint_h) $(htslib_hfile_h) $(htslib_bgzf_h) $(htslib_faidx_h) $(hts_internal_h) +cram/cram_stats.o cram/cram_stats.pico: cram/cram_stats.c config.h $(cram_h) $(cram_os_h) $(htslib_hts_alloc_h) cram/mFILE.o cram/mFILE.pico: cram/mFILE.c config.h $(htslib_hts_log_h) $(cram_os_h) cram/mFILE.h cram/open_trace_file.o cram/open_trace_file.pico: cram/open_trace_file.c config.h $(cram_os_h) $(cram_open_trace_file_h) $(cram_misc_h) $(htslib_hfile_h) $(htslib_hts_log_h) $(htslib_hts_h) -cram/pooled_alloc.o cram/pooled_alloc.pico: cram/pooled_alloc.c config.h cram/pooled_alloc.h $(cram_misc_h) -cram/string_alloc.o cram/string_alloc.pico: cram/string_alloc.c config.h cram/string_alloc.h -thread_pool.o thread_pool.pico: thread_pool.c config.h $(thread_pool_internal_h) $(htslib_hts_log_h) $(hts_internal_h) +cram/pooled_alloc.o cram/pooled_alloc.pico: cram/pooled_alloc.c config.h cram/pooled_alloc.h $(cram_misc_h) $(htslib_hts_alloc_h) +cram/string_alloc.o cram/string_alloc.pico: cram/string_alloc.c config.h cram/string_alloc.h $(htslib_hts_alloc_h) +thread_pool.o thread_pool.pico: thread_pool.c config.h $(thread_pool_internal_h) $(htslib_hts_alloc_h) $(htslib_hts_log_h) $(hts_internal_h) htscodecs/htscodecs/arith_dynamic.o htscodecs/htscodecs/arith_dynamic.pico: htscodecs/htscodecs/arith_dynamic.c config.h $(htscodecs_arith_dynamic_h) $(htscodecs_varint_h) $(htscodecs_pack_h) $(htscodecs_utils_h) $(htscodecs_c_simple_model_h) htscodecs/htscodecs/fqzcomp_qual.o htscodecs/htscodecs/fqzcomp_qual.pico: htscodecs/htscodecs/fqzcomp_qual.c config.h $(htscodecs_fqzcomp_qual_h) $(htscodecs_varint_h) $(htscodecs_utils_h) $(htscodecs_c_simple_model_h) @@ -573,10 +574,10 @@ tabix: tabix.o libhts.a ref_cache/ref-cache: $(REF_CACHE_OBJS) $(CC) $(LDFLAGS) $(REF_CACHE_EXTRA_LD_FLAGS) -o $@ $(REF_CACHE_OBJS) -lcurl -annot-tsv.o: annot-tsv.c config.h $(htslib_hts_h) $(htslib_hts_defs_h) $(htslib_khash_str2int_h) $(htslib_kstring_h) $(htslib_kseq_h) $(htslib_bgzf_h) $(htslib_regidx_h) $(textutils_internal_h) -bgzip.o: bgzip.c config.h $(htslib_bgzf_h) $(htslib_hts_h) $(htslib_hfile_h) +annot-tsv.o: annot-tsv.c config.h $(htslib_hts_h) $(htslib_hts_alloc_h) $(htslib_hts_defs_h) $(htslib_khash_str2int_h) $(htslib_kstring_h) $(htslib_kseq_h) $(htslib_bgzf_h) $(htslib_regidx_h) $(textutils_internal_h) +bgzip.o: bgzip.c config.h $(htslib_bgzf_h) $(htslib_hts_h) $(htslib_hts_alloc_h) $(htslib_hfile_h) htsfile.o: htsfile.c config.h $(htslib_hfile_h) $(htslib_hts_h) $(htslib_sam_h) $(htslib_vcf_h) -tabix.o: tabix.c config.h $(htslib_tbx_h) $(htslib_sam_h) $(htslib_vcf_h) $(htslib_kseq_h) $(htslib_bgzf_h) $(htslib_hts_h) $(htslib_regidx_h) $(htslib_hts_defs_h) $(htslib_hts_log_h) $(htslib_thread_pool_h) +tabix.o: tabix.c config.h $(htslib_tbx_h) $(htslib_sam_h) $(htslib_vcf_h) $(htslib_kseq_h) $(htslib_bgzf_h) $(htslib_hts_h) $(htslib_hts_alloc_h) $(htslib_regidx_h) $(htslib_hts_defs_h) $(htslib_hts_log_h) $(htslib_thread_pool_h) # ref_cache dependencies ref_cache_cmsg_wrap_h = ref_cache/cmsg_wrap.h @@ -597,12 +598,12 @@ ref_cache_upstream_h = ref_cache/upstream.h $(ref_cache_types_h) ref_cache/cmsg_wrap.o: ref_cache/cmsg_wrap.c config.h $(ref_cache_cmsg_wrap_h) ref_cache/http_parser.o: ref_cache/http_parser.c config.h $(ref_cache_http_parser_h) $(ref_cache_misc_h) $(ref_cache_options_h) $(ref_cache_request_handler_h) $(ref_cache_server_h) cram/pooled_alloc.h -ref_cache/listener.o: ref_cache/listener.c config.h $(ref_cache_listener_h) $(ref_cache_misc_h) $(ref_cache_options_h) $(ref_cache_poll_wrap_h) -ref_cache/log_files.o: ref_cache/log_files.c config.h $(ref_cache_log_files_h) $(ref_cache_options_h) -ref_cache/main.o: ref_cache/main.c config.h $(ref_cache_listener_h) $(ref_cache_log_files_h) $(ref_cache_misc_h) $(ref_cache_options_h) $(ref_cache_ping_h) $(ref_cache_poll_wrap_h) $(ref_cache_server_h) $(ref_cache_upstream_h) +ref_cache/listener.o: ref_cache/listener.c config.h $(ref_cache_listener_h) $(ref_cache_misc_h) $(ref_cache_options_h) $(ref_cache_poll_wrap_h) $(htslib_hts_alloc_h) +ref_cache/log_files.o: ref_cache/log_files.c config.h $(ref_cache_log_files_h) $(ref_cache_options_h) $(htslib_hts_alloc_h) +ref_cache/main.o: ref_cache/main.c config.h $(ref_cache_listener_h) $(ref_cache_log_files_h) $(ref_cache_misc_h) $(ref_cache_options_h) $(ref_cache_ping_h) $(ref_cache_poll_wrap_h) $(ref_cache_server_h) $(ref_cache_upstream_h) $(htslib_hts_alloc_h) ref_cache/ping.o: ref_cache/ping.c config.h $(ref_cache_ping_h) $(ref_cache_misc_h) $(ref_cache_options_h) ref_cache/poll_wrap_epoll.o: ref_cache/poll_wrap_epoll.c config.h $(ref_cache_poll_wrap_h) cram/pooled_alloc.h -ref_cache/poll_wrap_poll.o: ref_cache/poll_wrap_poll.c config.h $(ref_cache_poll_wrap_h) cram/pooled_alloc.h +ref_cache/poll_wrap_poll.o: ref_cache/poll_wrap_poll.c config.h $(ref_cache_poll_wrap_h) $(htslib_hts_alloc_h) cram/pooled_alloc.h ref_cache/ref_files.o: ref_cache/ref_files.c config.h $(ref_cache_ref_files_h) $(ref_cache_misc_h) $(ref_cache_options_h) $(ref_cache_upstream_h) ref_cache/request_handler.o: ref_cache/request_handler.c config.h $(ref_cache_request_handler_h) $(ref_cache_http_parser_h) $(ref_cache_misc_h) $(ref_cache_options_h) $(ref_cache_ref_files_h) $(ref_cache_transaction_h) $(ref_cache_upstream_h) ref_cache/sendfile_wrap.o: ref_cache/sendfile_wrap.c config.h $(ref_cache_sendfile_wrap_h) @@ -682,6 +683,7 @@ SRC = $(srcprefix) # MSYS2_ARG_CONV_EXCL="*" make check check test: all $(HTSCODECS_TEST_TARGETS) test/hts_endian + test/test_alloc test/test_expr test/test_kfunc test/test_khash @@ -748,6 +750,9 @@ test/plugins-dlhts: test/plugins-dlhts.o test/sam: test/sam.o libhts.a $(CC) $(LDFLAGS) -o $@ test/sam.o libhts.a $(LIBS) -lpthread +test/test_alloc: test/test_alloc.o + $(CC) $(LDFLAGS) -o $@ test/test_alloc.o + test/test_bgzf: test/test_bgzf.o libhts.a $(CC) $(LDFLAGS) -o $@ test/test_bgzf.o libhts.a $(LIBS) -lpthread @@ -872,10 +877,11 @@ test/pileup.o: test/pileup.c config.h $(htslib_sam_h) $(htslib_kstring_h) test/pileup_mod.o: test/pileup_mod.c config.h $(htslib_sam_h) test/plugins-dlhts.o: test/plugins-dlhts.c config.h test/sam.o: test/sam.c config.h $(htslib_hts_defs_h) $(htslib_sam_h) $(htslib_faidx_h) $(htslib_khash_h) $(htslib_hts_log_h) +test/test_alloc.o: test/test_alloc.c config.h $(htslib_hts_alloc_h) test/test_bgzf.o: test/test_bgzf.c config.h $(htslib_bgzf_h) $(htslib_hfile_h) $(htslib_hts_log_h) $(hfile_internal_h) test/test_expr.o: test/test_expr.c config.h $(htslib_hts_expr_h) test/test_kfunc.o: test/test_kfunc.c config.h $(htslib_kfunc_h) -test/test_khash.o: test/test_khash.c config.h $(htslib_khash_h) $(htslib_kroundup_h) +test/test_khash.o: test/test_khash.c config.h $(htslib_hts_alloc_h) $(htslib_khash_h) $(htslib_kroundup_h) test/test_kstring.o: test/test_kstring.c config.h $(htslib_kstring_h) kstring.c test/test_mod.o: test/test_mod.c config.h $(htslib_sam_h) test/test_nibbles.o: test/test_nibbles.c config.h $(htslib_sam_h) $(sam_internal_h) @@ -887,9 +893,9 @@ test/test_time_funcs.o: test/test_time_funcs.c config.h $(hts_time_funcs_h) test/test_view.o: test/test_view.c config.h $(cram_h) $(htslib_sam_h) $(htslib_vcf_h) $(htslib_hts_log_h) test/test_faidx.o: test/test_faidx.c config.h $(htslib_faidx_h) test/test_index.o: test/test_index.c config.h $(htslib_sam_h) $(htslib_vcf_h) -test/test-vcf-api.o: test/test-vcf-api.c config.h $(htslib_hts_h) $(htslib_vcf_h) $(htslib_vcfutils_h) $(htslib_kbitset_h) $(htslib_kstring_h) $(htslib_kseq_h) +test/test-vcf-api.o: test/test-vcf-api.c config.h $(htslib_hts_h) $(htslib_hts_alloc_h) $(htslib_vcf_h) $(htslib_vcfutils_h) $(htslib_kbitset_h) $(htslib_kstring_h) $(htslib_kseq_h) test/test-vcf-sweep.o: test/test-vcf-sweep.c config.h $(htslib_vcf_sweep_h) -test/test-bcf-sr.o: test/test-bcf-sr.c config.h $(htslib_hts_defs_h) $(htslib_synced_bcf_reader_h) $(htslib_hts_h) $(htslib_vcf_h) +test/test-bcf-sr.o: test/test-bcf-sr.c config.h $(htslib_hts_alloc_h) $(htslib_hts_defs_h) $(htslib_synced_bcf_reader_h) $(htslib_hts_h) $(htslib_vcf_h) test/test-bcf-translate.o: test/test-bcf-translate.c config.h $(htslib_vcf_h) test/test_introspection.o: test/test_introspection.c config.h $(htslib_hts_h) $(htslib_hfile_h) test/test-bcf_set_variant_type.o: test/test-bcf_set_variant_type.c config.h $(htslib_hts_h) vcf.c diff --git a/annot-tsv.c b/annot-tsv.c index 3c601c73a..7c657b777 100644 --- a/annot-tsv.c +++ b/annot-tsv.c @@ -38,6 +38,7 @@ #include #include #include "htslib/hts.h" +#include "htslib/hts_alloc.h" #include "htslib/hts_defs.h" #include "htslib/khash_str2int.h" #include "htslib/kstring.h" @@ -151,7 +152,7 @@ static inline void nbp_add(nbp_t *nbp, hts_pos_t beg, hts_pos_t end) if ( nbp->n >= nbp->m ) { nbp->m += 2; - nbp->regs = realloc(nbp->regs, nbp->m*sizeof(*nbp->regs)); + nbp->regs = hts_realloc_p(nbp->regs, sizeof(*nbp->regs), nbp->m); if ( !nbp->regs ) error("Out of memory, failed to allocate %zu bytes\n",nbp->m*sizeof(*nbp->regs)); } nbp->regs[nbp->n - 2] = NBP_SET_BEG(beg); @@ -203,7 +204,7 @@ cols_t *cols_split(const char *line, cols_t *cols, char delim) if ( cols->n > cols->m ) { cols->m += 10; - cols->off = realloc(cols->off, sizeof(*cols->off)*cols->m); + cols->off = hts_realloc_p(cols->off, sizeof(*cols->off), cols->m); if ( !cols->off ) error("Out of memory, failed to allocate %zu bytes\n",sizeof(*cols->off)*cols->m); } cols->off[ cols->n - 1 ] = ss; @@ -253,7 +254,7 @@ void cols_append(cols_t *cols, char *str) if ( cols->n > cols->m ) { cols->m++; - cols->off = realloc(cols->off,sizeof(*cols->off)*cols->m); + cols->off = hts_realloc_p(cols->off, sizeof(*cols->off), cols->m); if ( !cols->off ) error("Out of memory, failed to allocate %zu bytes\n",sizeof(*cols->off)*cols->m); } cols->off[cols->n-1] = str; @@ -479,7 +480,7 @@ static int read_next_line(dat_t *dat) void sanity_check_columns(char *fname, hdr_t *hdr, cols_t *cols, int **col2idx, int force) { - *col2idx = (int*)malloc(sizeof(int)*cols->n); + *col2idx = hts_malloc_p(sizeof(int), cols->n); if ( !*col2idx ) error("Out of memory, failed to allocate %zu bytes\n",sizeof(int)*cols->n); int i, idx; for (i=0; in; i++) diff --git a/bcf_sr_sort.c b/bcf_sr_sort.c index 73be004c9..9f5e6f3a1 100644 --- a/bcf_sr_sort.c +++ b/bcf_sr_sort.c @@ -31,6 +31,7 @@ #include "bcf_sr_sort.h" #include "htslib/khash_str2int.h" #include "htslib/kbitset.h" +#include "htslib/hts_alloc.h" // Variant types and pair-wise compatibility of their combinations, see bcf_sr_init_scores() #define SR_REF 1 @@ -311,7 +312,9 @@ static char *grp_create_key(sr_sort_t *srt) if ( i>0 ) srt->charp[i][-1] = 0; } qsort(srt->charp, srt->noff, sizeof(*srt->charp), cmpstringp); - char *ret = (char*) malloc(srt->str.l + 1), *ptr = ret; + char *ret = hts_malloc_ps(sizeof(*ret), srt->str.l, 1), *ptr = ret; + if (!ret) + return NULL; for (i=0; inoff; i++) { int len = strlen(srt->charp[i]); @@ -461,7 +464,7 @@ static int bcf_sr_sort_set(bcf_srs_t *readers, sr_sort_t *srt, const char *chr, int mvcf = var->mvcf; var->nvcf++; hts_expand0(int*, var->nvcf, var->mvcf, var->vcf); - if ( mvcf != var->mvcf ) var->rec = (bcf1_t **) realloc(var->rec,sizeof(bcf1_t*)*var->mvcf); + if ( mvcf != var->mvcf ) var->rec = hts_realloc_p(var->rec, sizeof(bcf1_t*), var->mvcf); var->vcf[var->nvcf-1] = ireader; var->rec[var->nvcf-1] = line; @@ -600,7 +603,8 @@ int bcf_sr_sort_next(bcf_srs_t *readers, sr_sort_t *srt, const char *chr, hts_po srt->sr = readers; if ( srt->nsr < readers->nreaders ) { - srt->vcf_buf = (vcf_buf_t*) realloc(srt->vcf_buf,readers->nreaders*sizeof(vcf_buf_t)); + srt->vcf_buf = hts_realloc_p(srt->vcf_buf, sizeof(vcf_buf_t), + readers->nreaders); memset(srt->vcf_buf + srt->nsr, 0, sizeof(vcf_buf_t)*(readers->nreaders - srt->nsr)); if ( srt->msr < srt->nsr ) srt->msr = srt->nsr; } diff --git a/bgzf.c b/bgzf.c index 307c534d1..b28c29d7c 100644 --- a/bgzf.c +++ b/bgzf.c @@ -45,6 +45,7 @@ #include "htslib/bgzf.h" #include "htslib/hfile.h" #include "htslib/thread_pool.h" +#include "htslib/hts_alloc.h" #include "htslib/hts_endian.h" #include "cram/pooled_alloc.h" #include "hts_internal.h" @@ -204,7 +205,7 @@ int bgzf_idx_push(BGZF *fp, hts_idx_t *hidx, int tid, hts_pos_t beg, hts_pos_t e if (ic->nentries >= ic->mentries) { int new_sz = ic->mentries ? ic->mentries*2 : 1024; - if (!(e = realloc(ic->e, new_sz * sizeof(*ic->e)))) { + if (!(e = hts_realloc_p(ic->e, sizeof(*ic->e), new_sz))) { pthread_mutex_unlock(&mt->idx_m); return -1; } @@ -391,7 +392,7 @@ static BGZF *bgzf_read_init(hFILE *hfpr, const char *filename) if (fp == NULL) return NULL; fp->is_write = 0; - fp->uncompressed_block = malloc(2 * BGZF_MAX_BLOCK_SIZE); + fp->uncompressed_block = hts_malloc_p(2, BGZF_MAX_BLOCK_SIZE); if (fp->uncompressed_block == NULL) { free(fp); return NULL; } fp->compressed_block = (char *)fp->uncompressed_block + BGZF_MAX_BLOCK_SIZE; fp->is_compressed = (n==18 && magic[0]==0x1f && magic[1]==0x8b); @@ -455,7 +456,7 @@ static BGZF *bgzf_write_init(const char *mode) } fp->is_compressed = 1; - fp->uncompressed_block = malloc(2 * BGZF_MAX_BLOCK_SIZE); + fp->uncompressed_block = hts_malloc_p(2, BGZF_MAX_BLOCK_SIZE); if (fp->uncompressed_block == NULL) goto mem_fail; fp->compressed_block = (char *)fp->uncompressed_block + BGZF_MAX_BLOCK_SIZE; @@ -1019,7 +1020,7 @@ int bgzf_read_block(BGZF *fp) if (!j || j->errcode == BGZF_ERR_MT) { if (!fp->mt->free_block) { - fp->uncompressed_block = malloc(2 * BGZF_MAX_BLOCK_SIZE); + fp->uncompressed_block = hts_malloc_p(2, BGZF_MAX_BLOCK_SIZE); if (fp->uncompressed_block == NULL) return -1; fp->compressed_block = (char *)fp->uncompressed_block + BGZF_MAX_BLOCK_SIZE; } // else it's already allocated with malloc, maybe even in-use. @@ -1417,7 +1418,8 @@ static void *bgzf_mt_writer(void *vp) { { fp->idx->moffs = fp->idx->noffs; kroundup32(fp->idx->moffs); - fp->idx->offs = (bgzidx1_t*) realloc(fp->idx->offs, fp->idx->moffs*sizeof(bgzidx1_t)); + fp->idx->offs = hts_realloc_p(fp->idx->offs, sizeof(bgzidx1_t), + fp->idx->moffs); if ( !fp->idx->offs ) goto err; } fp->idx->offs[ fp->idx->noffs-1 ].uaddr = fp->idx->offs[ fp->idx->noffs-2 ].uaddr + j->uncomp_len; @@ -2358,7 +2360,8 @@ int bgzf_index_add_block(BGZF *fp) { fp->idx->moffs = fp->idx->noffs; kroundup32(fp->idx->moffs); - fp->idx->offs = (bgzidx1_t*) realloc(fp->idx->offs, fp->idx->moffs*sizeof(bgzidx1_t)); + fp->idx->offs = hts_realloc_p(fp->idx->offs, sizeof(bgzidx1_t), + fp->idx->moffs); if ( !fp->idx->offs ) return -1; } fp->idx->offs[ fp->idx->noffs-1 ].uaddr = fp->idx->ublock_addr; diff --git a/bgzip.c b/bgzip.c index 459ea6c97..eda601e97 100644 --- a/bgzip.c +++ b/bgzip.c @@ -38,6 +38,7 @@ #include #include "htslib/bgzf.h" #include "htslib/hts.h" +#include "htslib/hts_alloc.h" #include "htslib/hfile.h" #ifdef _WIN32 @@ -352,7 +353,8 @@ int main(int argc, char **argv) fp = bgzf_open("-", out_mode); else { - char *name = malloc(strlen(argv[optind]) + 5); + char *name = hts_malloc_ps(sizeof(*name), + strlen(argv[optind]), 5); strcpy(name, argv[optind]); strcat(name, ".gz"); fp = bgzf_open(name, is_forced? out_mode : out_mode_exclusive); diff --git a/cram/cram_codecs.c b/cram/cram_codecs.c index f4ef18556..63690537d 100644 --- a/cram/cram_codecs.c +++ b/cram/cram_codecs.c @@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../fuzz_settings.h" #endif +#include "../htslib/hts_alloc.h" #include "../htslib/hts_endian.h" #if defined(HAVE_EXTERNAL_LIBHTSCODECS) @@ -268,12 +269,14 @@ static int store_bits_MSB(cram_block *block, uint64_t val, int nbits) { if (block->byte+8 >= block->alloc) { if (block->byte) { block->alloc *= 2; - block->data = realloc(block->data, block->alloc + 8); + block->data = hts_realloc_ps(block->data, sizeof(*block->data), + block->alloc, 8); if (!block->data) return -1; } else { block->alloc = 1024; - block->data = realloc(block->data, block->alloc + 8); + block->data = hts_realloc_ps(block->data, sizeof(*block->data), + block->alloc, 8); if (!block->data) return -1; block->data[0] = 0; // initialise first byte of buffer @@ -1975,7 +1978,7 @@ int cram_xdelta_encode_int(cram_slice *slice, cram_codec *c, int cram_xdelta_encode_char(cram_slice *slice, cram_codec *c, char *in, int in_size) { - char *dat = malloc(in_size*5); + char *dat = hts_malloc_p(5, in_size); if (!dat) return -1; char *cp = dat, *cp_end = dat + in_size*5; @@ -2269,7 +2272,7 @@ int cram_xrle_encode_flush(cram_codec *c) { c->u.e_xrle.to_flush_size = BLOCK_SIZE(c->out); } - out_len = malloc(c->u.e_xrle.to_flush_size+8); + out_len = hts_malloc_ps(sizeof(*out_len), c->u.e_xrle.to_flush_size, 8); if (!out_len) return -1; @@ -3122,7 +3125,7 @@ int cram_huffman_encode_store(cram_codec *c, cram_block *b, char *prefix, * * Therefore 6*ncodes + 5 + 5 + 1 + 5 is max memory */ - char *tmp = malloc(6*c->u.e_huffman.nvals+16); + char *tmp = hts_malloc_pse(6, c->u.e_huffman.nvals, 0, 16); char *tp = tmp, *tpend = tmp+6*c->u.e_huffman.nvals+16; if (!tmp) @@ -3196,10 +3199,10 @@ cram_codec *cram_huffman_encode_init(cram_stats *st, continue; if (nvals >= vals_alloc) { vals_alloc = vals_alloc ? vals_alloc*2 : 1024; - new_vals = realloc(vals, vals_alloc * sizeof(int)); + new_vals = hts_realloc_p(vals, sizeof(*vals), vals_alloc); if (!new_vals) goto nomem; vals = new_vals; - new_freqs = realloc(freqs, vals_alloc * sizeof(int)); + new_freqs = hts_realloc_p(freqs, sizeof(*freqs), vals_alloc); if (!new_freqs) goto nomem; freqs = new_freqs; } @@ -3218,10 +3221,10 @@ cram_codec *cram_huffman_encode_init(cram_stats *st, continue; if (nvals >= vals_alloc) { vals_alloc = vals_alloc ? vals_alloc*2 : 1024; - new_vals = realloc(vals, vals_alloc * sizeof(int)); + new_vals = hts_realloc_p(vals, sizeof(*vals), vals_alloc); if (!new_vals) goto nomem; vals = new_vals; - new_freqs = realloc(freqs, vals_alloc * sizeof(int)); + new_freqs = hts_realloc_p(freqs, sizeof(*freqs), vals_alloc); if (!new_freqs) goto nomem; freqs = new_freqs; } @@ -3236,10 +3239,10 @@ cram_codec *cram_huffman_encode_init(cram_stats *st, assert(nvals > 0); - new_freqs = realloc(freqs, 2*nvals*sizeof(*freqs)); + new_freqs = hts_realloc_p(freqs, 2 * sizeof(*freqs), nvals); if (!new_freqs) goto nomem; freqs = new_freqs; - lens = calloc(2*nvals, sizeof(*lens)); + lens = calloc(nvals, 2 * sizeof(*lens)); if (!lens) goto nomem; /* Inefficient, use pointers to form chain so we can insert and maintain @@ -3280,7 +3283,7 @@ cram_codec *cram_huffman_encode_init(cram_stats *st, /* Sort, need in a struct */ - if (!(codes = malloc(nvals * sizeof(*codes)))) + if (!(codes = hts_malloc_p(sizeof(*codes), nvals))) goto nomem; for (i = 0; i < nvals; i++) { codes[i].symbol = vals[i]; diff --git a/cram/cram_decode.c b/cram/cram_decode.c index cdc67ce55..cad58dfdf 100644 --- a/cram/cram_decode.c +++ b/cram/cram_decode.c @@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "cram.h" #include "os.h" #include "../htslib/hts.h" +#include "../htslib/hts_alloc.h" #include "../htslib/hfile.h" //Whether CIGAR has just M or uses = and X to indicate match and mismatch @@ -178,7 +179,7 @@ cram_block_compression_hdr *cram_decode_compression_header(cram_fd *fd, free(hdr); return NULL; } - if (!(hdr->landmark = malloc(hdr->num_landmarks * sizeof(int32_t)))) { + if (!(hdr->landmark = hts_malloc_p(sizeof(int32_t), hdr->num_landmarks))) { free(hdr); return NULL; } @@ -629,7 +630,7 @@ int cram_dependent_data_series(cram_fd *fd, return 0; } - block_used = calloc(s->hdr->num_blocks+1, sizeof(int)); + block_used = hts_calloc_ps(sizeof(*block_used), s->hdr->num_blocks, 1); if (!block_used) return -1; @@ -1007,7 +1008,7 @@ cram_block_slice_hdr *cram_decode_slice_header(cram_fd *fd, cram_block *b) { free(hdr); return NULL; } - hdr->block_content_ids = malloc(hdr->num_content_ids * sizeof(int32_t)); + hdr->block_content_ids = hts_malloc_p(sizeof(int32_t), hdr->num_content_ids); if (!hdr->block_content_ids) { free(hdr); return NULL; @@ -1162,7 +1163,7 @@ static int cram_decode_seq(cram_fd *fd, cram_container *c, cram_slice *s, if (ncigar+2 >= cigar_alloc) { cigar_alloc = cigar_alloc ? cigar_alloc*2 : 1024; - if (!(cigar = realloc(s->cigar, cigar_alloc * sizeof(*cigar)))) + if (!(cigar = hts_realloc_p(s->cigar, sizeof(*cigar), cigar_alloc))) return -1; s->cigar = cigar; } @@ -1775,7 +1776,7 @@ static int cram_decode_seq(cram_fd *fd, cram_container *c, cram_slice *s, if (ncigar+1 >= cigar_alloc) { cigar_alloc = cigar_alloc ? cigar_alloc*2 : 1024; - if (!(cigar = realloc(s->cigar, cigar_alloc * sizeof(*cigar)))) + if (!(cigar = hts_realloc_p(s->cigar, sizeof(*cigar), cigar_alloc))) return -1; s->cigar = cigar; } @@ -1805,7 +1806,7 @@ static int cram_decode_seq(cram_fd *fd, cram_container *c, cram_slice *s, if (cig_len) { if (ncigar >= cigar_alloc) { cigar_alloc = cigar_alloc ? cigar_alloc*2 : 1024; - if (!(cigar = realloc(s->cigar, cigar_alloc * sizeof(*cigar)))) + if (!(cigar = hts_realloc_p(s->cigar, sizeof(*cigar), cigar_alloc))) return -1; s->cigar = cigar; } @@ -2400,7 +2401,7 @@ int cram_decode_slice(cram_fd *fd, cram_container *c, cram_slice *s, if (s->crecs) free(s->crecs); - if (!(s->crecs = malloc(s->hdr->num_records * sizeof(*s->crecs)))) + if (!(s->crecs = hts_malloc_p(sizeof(*s->crecs), s->hdr->num_records))) return -1; ref_id = s->hdr->ref_seq_id; diff --git a/cram/cram_encode.c b/cram/cram_encode.c index 00d2e48e0..12768cd28 100644 --- a/cram/cram_encode.c +++ b/cram/cram_encode.c @@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "os.h" #include "../sam_internal.h" // for nibble2base #include "../htslib/hts.h" +#include "../htslib/hts_alloc.h" #include "../htslib/hts_endian.h" #include "../textutils_internal.h" @@ -517,7 +518,7 @@ cram_block *cram_encode_slice_header(cram_fd *fd, cram_slice *s) { if (!b) return NULL; - cp = buf = malloc(22+16+5*(8+s->hdr->num_blocks)); + cp = buf = hts_malloc_pse(8, s->hdr->num_blocks, 5, 22+16); if (NULL == buf) { cram_free_block(b); return NULL; @@ -1119,8 +1120,10 @@ static int cram_encode_slice(cram_fd *fd, cram_container *c, c->num_records += s->hdr->num_records; int ntags = c->tags_used ? c->tags_used->n_occupied : 0; - s->block = calloc(DS_END + ntags*2, sizeof(s->block[0])); - s->hdr->block_content_ids = malloc(DS_END * sizeof(int32_t)); + s->block = hts_calloc_ps(sizeof(s->block[0]), DS_END, + hts_prod_sat2(ntags, 2)); + s->hdr->block_content_ids = hts_malloc_p(sizeof(*s->hdr->block_content_ids), + DS_END); if (!s->block || !s->hdr->block_content_ids) return -1; @@ -1213,8 +1216,9 @@ static int cram_encode_slice(cram_fd *fd, cram_container *c, { int i, j; - s->hdr->block_content_ids = realloc(s->hdr->block_content_ids, - s->hdr->num_blocks * sizeof(int32_t)); + s->hdr->block_content_ids = hts_realloc_p(s->hdr->block_content_ids, + sizeof(*s->hdr->block_content_ids), + s->hdr->num_blocks); if (!s->hdr->block_content_ids) return -1; @@ -1529,8 +1533,8 @@ static inline int extend_ref(char **ref, uint32_t (**hist)[5], hts_pos_t pos, return -1; *ref = tmp; - uint32_t (*tmp5)[5] = realloc(**hist, - (new_end - ref_start)*sizeof(**hist)); + uint32_t (*tmp5)[5] = hts_realloc_p(**hist, sizeof(**hist), + new_end - ref_start); if (!tmp5) return -1; *hist = tmp5; @@ -2103,7 +2107,7 @@ int cram_encode_container(cram_fd *fd, cram_container *c) { // slice can start aggregating them from the start again. if (c->tags_used->n_occupied) { int ntags = c->tags_used->n_occupied; - s->aux_block = calloc(ntags*2, sizeof(*s->aux_block)); + s->aux_block = calloc(hts_prod_sat2(ntags, 2), sizeof(*s->aux_block)); if (!s->aux_block) return -1; @@ -2474,7 +2478,7 @@ int cram_encode_container(cram_fd *fd, cram_container *c) { /* Compute landmarks */ /* Fill out slice landmarks */ c->num_landmarks = c->curr_slice; - c->landmark = malloc(c->num_landmarks * sizeof(*c->landmark)); + c->landmark = hts_malloc_p(sizeof(*c->landmark), c->num_landmarks); if (!c->landmark) return -1; @@ -2575,7 +2579,7 @@ static int cram_add_feature(cram_container *c, cram_slice *s, cram_record *r, cram_feature *f) { if (s->nfeatures >= s->afeatures) { s->afeatures = s->afeatures ? s->afeatures*2 : 1024; - s->features = realloc(s->features, s->afeatures*sizeof(*s->features)); + s->features = hts_realloc_p(s->features, sizeof(*s->features), s->afeatures); if (!s->features) return -1; } @@ -2806,7 +2810,7 @@ static sam_hrec_rg_t *cram_encode_aux(cram_fd *fd, bam_seq_t *b, // 2: Don't auto-decode NM (may be invalid) if (cf_tag && CRAM_MAJOR_VERS(fd->version) < 4) { // Temporary copy of aux so we can ammend it. - aux = malloc(aux_size+4); + aux = hts_malloc_ps(sizeof(*aux), aux_size, 4); if (!aux) return NULL; @@ -3484,7 +3488,7 @@ static int process_one_read(cram_fd *fd, cram_container *c, cr->ncigar = bam_cigar_len(b); while (cr->cigar + cr->ncigar >= s->cigar_alloc) { s->cigar_alloc = s->cigar_alloc ? s->cigar_alloc*2 : 1024; - s->cigar = realloc(s->cigar, s->cigar_alloc * sizeof(*s->cigar)); + s->cigar = hts_realloc_p(s->cigar, sizeof(*s->cigar), s->cigar_alloc); if (!s->cigar) return -1; } diff --git a/cram/cram_external.c b/cram/cram_external.c index 4943750dd..e1117fc2c 100644 --- a/cram/cram_external.c +++ b/cram/cram_external.c @@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #include "../htslib/hfile.h" +#include "../htslib/hts_alloc.h" #include "cram.h" /* @@ -378,8 +379,8 @@ cram_cid2ds_t *cram_update_cid2ds_map(cram_block_compression_hdr *hdr, if (c2d->ds_idx >= c2d->ds_size) { c2d->ds_size += 100; c2d->ds_size *= 2; - ds_list *ds_new = realloc(c2d->ds, - c2d->ds_size * sizeof(*ds_new)); + ds_list *ds_new = hts_realloc_p(c2d->ds, sizeof(*ds_new), + c2d->ds_size); if (!ds_new) goto err; c2d->ds = ds_new; @@ -450,7 +451,7 @@ int *cram_cid2ds_query(cram_cid2ds_t *c2d, int content_id, int *n) { return NULL; if (!c2d->ds_a) { - c2d->ds_a = malloc(c2d->ds_idx * sizeof(int)); + c2d->ds_a = hts_malloc_p(sizeof(*c2d->ds_a), c2d->ds_idx); if (!c2d->ds_a) return NULL; } diff --git a/cram/cram_index.c b/cram/cram_index.c index b08ca5bfd..5660dfe92 100644 --- a/cram/cram_index.c +++ b/cram/cram_index.c @@ -64,6 +64,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../htslib/bgzf.h" #include "../htslib/hfile.h" +#include "../htslib/hts_alloc.h" #include "../hts_internal.h" #include "cram.h" #include "os.h" @@ -287,8 +288,8 @@ int cram_index_load(cram_fd *fd, const char *fn, const char *fn_idx) { cram_index *new_idx; int new_sz = e.refid+2; size_t index_end = fd->index_sz * sizeof(*fd->index); - new_idx = realloc(fd->index, - new_sz * sizeof(*fd->index)); + new_idx = hts_realloc_p(fd->index, sizeof(*fd->index), + new_sz); if (!new_idx) goto fail; @@ -315,7 +316,7 @@ int cram_index_load(cram_fd *fd, const char *fn, const char *fn_idx) { if (idx->nslice+1 >= idx->nalloc) { cram_index *new_e; idx->nalloc = idx->nalloc ? idx->nalloc*2 : 16; - new_e = realloc(idx->e, idx->nalloc * sizeof(*idx->e)); + new_e = hts_realloc_p(idx->e, sizeof(*idx->e), idx->nalloc); if (!new_e) goto fail; @@ -329,7 +330,7 @@ int cram_index_load(cram_fd *fd, const char *fn, const char *fn_idx) { if (++idx_stack_ptr >= idx_stack_alloc) { cram_index **new_stack; idx_stack_alloc *= 2; - new_stack = realloc(idx_stack, idx_stack_alloc*sizeof(*idx_stack)); + new_stack = hts_realloc_p(idx_stack, sizeof(*idx_stack), idx_stack_alloc); if (!new_stack) goto fail; idx_stack = new_stack; diff --git a/cram/cram_io.c b/cram/cram_io.c index 28a035a63..d275e8a66 100644 --- a/cram/cram_io.c +++ b/cram/cram_io.c @@ -76,6 +76,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "cram.h" #include "os.h" #include "../htslib/hts.h" +#include "../htslib/hts_alloc.h" #include "../hts_internal.h" #include "open_trace_file.h" @@ -2661,7 +2662,7 @@ static refs_t *refs_load_fai(refs_t *r_orig, const char *fn, int is_err) { int x; id_alloc = id_alloc ?id_alloc*2 : 16; - new_refs = realloc(r->ref_id, id_alloc * sizeof(*r->ref_id)); + new_refs = hts_realloc_p(r->ref_id, sizeof(*r->ref_id), id_alloc); if (!new_refs) goto err; r->ref_id = new_refs; @@ -2788,7 +2789,8 @@ static int refs_from_header(cram_fd *fd) { //fprintf(stderr, "refs_from_header for %p mode %c\n", fd, fd->mode); /* Existing refs are fine, as long as they're compatible with the hdr. */ - ref_entry **new_ref_id = realloc(r->ref_id, (r->nref + h->hrecs->nref) * sizeof(*r->ref_id)); + ref_entry **new_ref_id = hts_realloc_ps(r->ref_id, sizeof(*r->ref_id), + r->nref, h->hrecs->nref); if (!new_ref_id) return -1; r->ref_id = new_ref_id; @@ -3884,7 +3886,7 @@ cram_container *cram_read_container(cram_fd *fd) { return NULL; } #endif - if (c->num_landmarks && !(c->landmark = malloc(c->num_landmarks * sizeof(int32_t)))) { + if (c->num_landmarks && !(c->landmark = hts_malloc_p(sizeof(*c->landmark), c->num_landmarks))) { fd->err = errno; cram_free_container(c); return NULL; @@ -4514,9 +4516,9 @@ cram_slice *cram_new_slice(enum cram_content_type type, int nrecs) { s->block = NULL; s->block_by_id = NULL; s->last_apos = 0; - if (!(s->crecs = malloc(nrecs * sizeof(cram_record)))) goto err; + if (!(s->crecs = hts_malloc_p(sizeof(*s->crecs), nrecs))) goto err; s->cigar_alloc = 1024; - if (!(s->cigar = malloc(s->cigar_alloc * sizeof(*s->cigar)))) goto err; + if (!(s->cigar = hts_malloc_p(sizeof(*s->cigar), s->cigar_alloc))) goto err; s->ncigar = 0; if (!(s->seqs_blk = cram_new_block(EXTERNAL, 0))) goto err; @@ -4620,7 +4622,7 @@ cram_slice *cram_read_slice(cram_fd *fd) { /* Initialise encoding/decoding tables */ s->cigar_alloc = 1024; - if (!(s->cigar = malloc(s->cigar_alloc * sizeof(*s->cigar)))) goto err; + if (!(s->cigar = hts_malloc_p(sizeof(*s->cigar), s->cigar_alloc))) goto err; s->ncigar = 0; if (!(s->seqs_blk = cram_new_block(EXTERNAL, 0))) goto err; diff --git a/cram/cram_stats.c b/cram/cram_stats.c index d06b8ffb9..fe5d70201 100644 --- a/cram/cram_stats.c +++ b/cram/cram_stats.c @@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "cram.h" #include "os.h" +#include "../htslib/hts_alloc.h" cram_stats *cram_stats_create(void) { return calloc(1, sizeof(cram_stats)); @@ -146,8 +147,8 @@ enum cram_encoding cram_stats_encoding(cram_fd *fd, cram_stats *st) { continue; if (nvals >= vals_alloc) { vals_alloc = vals_alloc ? vals_alloc*2 : 1024; - int *vals_tmp = realloc(vals, vals_alloc * sizeof(int)); - int *freqs_tmp = realloc(freqs, vals_alloc * sizeof(int)); + int *vals_tmp = hts_realloc_p(vals, sizeof(*vals), vals_alloc); + int *freqs_tmp = hts_realloc_p(freqs, sizeof(*freqs), vals_alloc); if (!vals_tmp || !freqs_tmp) { free(vals_tmp ? vals_tmp : vals); free(freqs_tmp ? freqs_tmp : freqs); @@ -173,8 +174,8 @@ enum cram_encoding cram_stats_encoding(cram_fd *fd, cram_stats *st) { if (nvals >= vals_alloc) { vals_alloc = vals_alloc ? vals_alloc*2 : 1024; - int *vals_tmp = realloc(vals, vals_alloc * sizeof(int)); - int *freqs_tmp = realloc(freqs, vals_alloc * sizeof(int)); + int *vals_tmp = hts_realloc_p(vals, sizeof(*vals), vals_alloc); + int *freqs_tmp = hts_realloc_p(freqs, sizeof(*freqs), vals_alloc); if (!vals_tmp || !freqs_tmp) { free(vals_tmp ? vals_tmp : vals); free(freqs_tmp ? freqs_tmp : freqs); diff --git a/cram/pooled_alloc.c b/cram/pooled_alloc.c index 4601a7f35..21cf5cda2 100644 --- a/cram/pooled_alloc.c +++ b/cram/pooled_alloc.c @@ -37,6 +37,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "pooled_alloc.h" #include "misc.h" +#include "../htslib/hts_alloc.h" //#define DISABLE_POOLED_ALLOC //#define TEST_MAIN @@ -97,12 +98,12 @@ static pool_t *new_pool(pool_alloc_t *p) { size_t n = p->psize / p->dsize; pool_t *pool; - pool = realloc(p->pools, (p->npools + 1) * sizeof(*p->pools)); + pool = hts_realloc_ps(p->pools, sizeof(*p->pools), p->npools, 1); if (NULL == pool) return NULL; p->pools = pool; pool = &p->pools[p->npools]; - pool->pool = malloc(n * p->dsize); + pool->pool = hts_malloc_p(p->dsize, n); if (NULL == pool->pool) return NULL; pool->used = 0; diff --git a/cram/string_alloc.c b/cram/string_alloc.c index c339b1020..087d67907 100644 --- a/cram/string_alloc.c +++ b/cram/string_alloc.c @@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "string_alloc.h" +#include "../htslib/hts_alloc.h" #define MIN_STR_SIZE 1024 @@ -77,7 +78,7 @@ static string_t *new_string_pool(string_alloc_t *a_str) { if (a_str->nstrings == a_str->max_strings) { size_t new_max = (a_str->max_strings | (a_str->max_strings >> 2)) + 1; - str = realloc(a_str->strings, new_max * sizeof(*a_str->strings)); + str = hts_realloc_p(a_str->strings, sizeof(*a_str->strings), new_max); if (NULL == str) return NULL; diff --git a/faidx.c b/faidx.c index c7fc022a8..039da994a 100644 --- a/faidx.c +++ b/faidx.c @@ -39,6 +39,7 @@ DEALINGS IN THE SOFTWARE. */ #include "htslib/bgzf.h" #include "htslib/faidx.h" #include "htslib/hfile.h" +#include "htslib/hts_alloc.h" #include "htslib/khash.h" #include "htslib/kstring.h" #include "hts_internal.h" @@ -111,7 +112,7 @@ static inline int fai_insert_index(faidx_t *idx, const char *name, uint64_t len, if (idx->n == idx->m) { char **tmp; idx->m = idx->m? idx->m<<1 : 16; - if (!(tmp = (char**)realloc(idx->name, sizeof(char*) * idx->m))) { + if (!(tmp = hts_realloc_p(idx->name, sizeof(char*), idx->m))) { hts_log_error("Out of memory"); return -1; } @@ -743,7 +744,7 @@ static char *fai_retrieve(const faidx_t *fai, const faidx1_t *val, } // Over-allocate so there is extra space for one end-of-line sequence - buffer = (char*)malloc((size_t) end - beg + val->line_len - val->line_blen + 1); + buffer = malloc(hts_add_sat3(end - beg, val->line_len - val->line_blen, 1)); if (!buffer) { *len = -1; return NULL; diff --git a/header.c b/header.c index 738f81814..627f64b98 100644 --- a/header.c +++ b/header.c @@ -38,6 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "header.h" #include "htslib/bgzf.h" #include "htslib/hfile.h" +#include "htslib/hts_alloc.h" #include "htslib/kseq.h" // Hash table for removing multiple lines from the header @@ -248,7 +249,7 @@ static int sam_hrecs_update_hashes(sam_hrecs_t *hrecs, if (nref == hrecs->ref_sz) { size_t new_sz = hrecs->ref_sz >= 4 ? hrecs->ref_sz + (hrecs->ref_sz / 4) : 32; - sam_hrec_sq_t *new_ref = realloc(hrecs->ref, sizeof(*hrecs->ref) * new_sz); + sam_hrec_sq_t *new_ref = hts_realloc_p(hrecs->ref, sizeof(*hrecs->ref), new_sz); if (!new_ref) return -1; hrecs->ref = new_ref; @@ -300,7 +301,7 @@ static int sam_hrecs_update_hashes(sam_hrecs_t *hrecs, if (nrg == hrecs->rg_sz) { size_t new_sz = hrecs->rg_sz >= 4 ? hrecs->rg_sz + hrecs->rg_sz / 4 : 4; - sam_hrec_rg_t *new_rg = realloc(hrecs->rg, sizeof(*hrecs->rg) * new_sz); + sam_hrec_rg_t *new_rg = hts_realloc_p(hrecs->rg, sizeof(*hrecs->rg), new_sz); if (!new_rg) return -1; hrecs->rg = new_rg; @@ -327,7 +328,7 @@ static int sam_hrecs_update_hashes(sam_hrecs_t *hrecs, if (npg == hrecs->pg_sz) { size_t new_sz = hrecs->pg_sz >= 4 ? hrecs->pg_sz + hrecs->pg_sz / 4 : 4; - new_pg = realloc(hrecs->pg, sizeof(*hrecs->pg) * new_sz); + new_pg = hts_realloc_p(hrecs->pg, sizeof(*hrecs->pg), new_sz); if (!new_pg) return -1; hrecs->pg = new_pg; @@ -396,7 +397,7 @@ static int sam_hrecs_update_hashes(sam_hrecs_t *hrecs, int *new_pg_end; int new_alloc = hrecs->npg_end_alloc ? hrecs->npg_end_alloc*2 : 4; - new_pg_end = realloc(hrecs->pg_end, new_alloc * sizeof(int)); + new_pg_end = hts_realloc_p(hrecs->pg_end, sizeof(int), new_alloc); if (!new_pg_end) return -1; hrecs->npg_end_alloc = new_alloc; @@ -611,7 +612,7 @@ static int sam_hrecs_vadd(sam_hrecs_t *hrecs, const char *type, va_list ap, ...) if (strncmp(type, "CO", 2)) { h_tag->len = 3 + strlen(val); - str = string_alloc(hrecs->str_pool, h_tag->len+1); + str = string_alloc(hrecs->str_pool, hts_add_sat2(h_tag->len, 1)); if (!str || snprintf(str, h_tag->len+1, "%2.2s:%s", key, val) < 0) return -1; h_tag->str = str; @@ -646,7 +647,7 @@ static int sam_hrecs_vadd(sam_hrecs_t *hrecs, const char *type, va_list ap, ...) if (strncmp(type, "CO", 2)) { h_tag->len = 3 + strlen(val); - str = string_alloc(hrecs->str_pool, h_tag->len+1); + str = string_alloc(hrecs->str_pool, hts_add_sat2(h_tag->len, 1)); if (!str || snprintf(str, h_tag->len+1, "%2.2s:%s", key, val) < 0) return -1; h_tag->str = str; @@ -1045,8 +1046,8 @@ static int sam_hrecs_parse_lines(sam_hrecs_t *hrecs, const char *hdr, size_t len return -1; if (hrecs->ref_sz < sq_count) { - sam_hrec_sq_t *new_ref = realloc(hrecs->ref, - sizeof(*hrecs->ref) * sq_count); + sam_hrec_sq_t *new_ref = hts_realloc_p(hrecs->ref, + sizeof(*hrecs->ref), sq_count); if (!new_ref) return -1; hrecs->ref = new_ref; @@ -1080,13 +1081,13 @@ int sam_hdr_update_target_arrays(sam_hdr_t *bh, const sam_hrecs_t *hrecs, // Grow arrays if necessary if (bh->n_targets < hrecs->nref) { - char **new_names = realloc(bh->target_name, - hrecs->nref * sizeof(*new_names)); + char **new_names = hts_realloc_p(bh->target_name, sizeof(*new_names), + hrecs->nref); if (!new_names) return -1; bh->target_name = new_names; - uint32_t *new_lens = realloc(bh->target_len, - hrecs->nref * sizeof(*new_lens)); + uint32_t *new_lens = hts_realloc_p(bh->target_len, sizeof(*new_lens), + hrecs->nref); if (!new_lens) return -1; bh->target_len = new_lens; @@ -1194,8 +1195,8 @@ static int sam_hrecs_refs_from_targets_array(sam_hrecs_t *hrecs, } if (hrecs->ref_sz < bh->n_targets) { - sam_hrec_sq_t *new_ref = realloc(hrecs->ref, - bh->n_targets * sizeof(*new_ref)); + sam_hrec_sq_t *new_ref = hts_realloc_p(hrecs->ref, sizeof(*new_ref), + bh->n_targets); if (!new_ref) return -1; @@ -1486,8 +1487,8 @@ int sam_hdr_build_from_sam_file(sam_hdr_t *hdr, htsFile* fp) { goto error; if (hrecs->ref_sz < sq_count) { - sam_hrec_sq_t *new_ref = realloc(hrecs->ref, - sizeof(*hrecs->ref) * sq_count); + sam_hrec_sq_t *new_ref = hts_realloc_p(hrecs->ref, + sizeof(*hrecs->ref), sq_count); if (!new_ref) goto error; hrecs->ref = new_ref; @@ -2482,7 +2483,7 @@ static int sam_hdr_link_pg(sam_hdr_t *bh) { return 0; hrecs->npg_end_alloc = hrecs->npg; - new_pg_end = realloc(hrecs->pg_end, hrecs->npg * sizeof(*new_pg_end)); + new_pg_end = hts_realloc_p(hrecs->pg_end, sizeof(*new_pg_end), hrecs->npg); if (!new_pg_end) return -1; hrecs->pg_end = new_pg_end; @@ -2578,7 +2579,8 @@ const char *sam_hdr_pg_id(sam_hdr_t *bh, const char *name) { name_len = strlen(name); if (name_len > 1000) name_len = 1000; if (hrecs->ID_buf_sz < name_len + name_extra) { - char *new_ID_buf = realloc(hrecs->ID_buf, name_len + name_extra); + char *new_ID_buf = realloc(hrecs->ID_buf, + hts_add_sat2(name_len, name_extra)); if (new_ID_buf == NULL) return NULL; hrecs->ID_buf = new_ID_buf; @@ -2662,7 +2664,7 @@ int sam_hdr_add_pg(sam_hdr_t *bh, const char *name, ...) { if (!specified_pp && hrecs->npg_end) { /* Copy ends array to avoid us looping while modifying it */ - int *end = malloc(hrecs->npg_end * sizeof(int)); + int *end = hts_malloc_p(sizeof(int), hrecs->npg_end); int i, nends = hrecs->npg_end; if (!end) @@ -2962,7 +2964,7 @@ int sam_hrecs_vupdate(sam_hrecs_t *hrecs, sam_hrec_type_t *type, va_list ap) { } tag->len = 3 + strlen(v); - str = string_alloc(hrecs->str_pool, tag->len+1); + str = string_alloc(hrecs->str_pool, hts_add_sat2(tag->len, 1)); if (!str) return -1; diff --git a/hfile_libcurl.c b/hfile_libcurl.c index d3872c42a..a82ee1863 100644 --- a/hfile_libcurl.c +++ b/hfile_libcurl.c @@ -42,6 +42,7 @@ DEALINGS IN THE SOFTWARE. */ #include "version.h" #endif #include "htslib/hts.h" // for hts_version() and hts_verbose +#include "htslib/hts_alloc.h" #include "htslib/kstring.h" #include "htslib/khash.h" @@ -353,8 +354,8 @@ static void libcurl_exit(void) static int append_header(hdrlist *hdrs, const char *data, int dup) { if (hdrs->num == hdrs->size) { unsigned int new_sz = hdrs->size ? hdrs->size * 2 : 4, i; - struct curl_slist *new_list = realloc(hdrs->list, - new_sz * sizeof(*new_list)); + struct curl_slist *new_list = hts_realloc_p(hdrs->list, + sizeof(*new_list), new_sz); if (!new_list) return -1; hdrs->size = new_sz; hdrs->list = new_list; diff --git a/hfile_s3.c b/hfile_s3.c index 30de86e27..71701d831 100644 --- a/hfile_s3.c +++ b/hfile_s3.c @@ -40,6 +40,7 @@ DEALINGS IN THE SOFTWARE. */ #include "version.h" #endif #include "htslib/hts.h" // for hts_version() and hts_verbose +#include "htslib/hts_alloc.h" #include "htslib/kstring.h" #include "hts_time_funcs.h" @@ -398,8 +399,8 @@ static char *escape_query(const char *qs) { char *escaped; length = strlen(qs); - alloced = length * 3 + 1; - if ((escaped = malloc(alloced)) == NULL) { + alloced = hts_add_sat2(hts_prod_sat2(length, 3), 1); + if ((escaped = hts_malloc(alloced)) == NULL) { return NULL; } @@ -426,9 +427,9 @@ static char *escape_path(const char *path) { char *escaped; length = strlen(path); - alloced = length * 3 + 1; + alloced = hts_add_sat2(hts_prod_sat2(length, 3), 1); - if ((escaped = malloc(alloced)) == NULL) { + if ((escaped = hts_malloc(alloced)) == NULL) { return NULL; } @@ -1018,7 +1019,7 @@ static int order_query_string(kstring_t *qs) { return -1; } - if ((queries = malloc(num_queries * sizeof(char*))) == NULL) + if ((queries = hts_malloc_p(sizeof(char*), num_queries)) == NULL) goto err; for (i = 0; i < num_queries; i++) { diff --git a/hts.c b/hts.c index 7af22fce7..bb16cdff4 100644 --- a/hts.c +++ b/hts.c @@ -59,6 +59,7 @@ DEALINGS IN THE SOFTWARE. */ #include "hts_internal.h" #include "hfile_internal.h" #include "sam_internal.h" +#include "htslib/hts_alloc.h" #include "htslib/hts_expr.h" #include "htslib/hts_os.h" // drand48 @@ -2111,7 +2112,7 @@ char **hts_readlist(const char *string, int is_file, int *_n) } } // Try to shrink s to the minimum size needed - s_new = (char**)realloc(s, n * sizeof(char*)); + s_new = hts_realloc_p(s, sizeof(char*), n); if (!s_new) goto err; @@ -2166,7 +2167,7 @@ char **hts_readlines(const char *fn, int *_n) } } else return 0; // Try to shrink s to the minimum size needed - s_new = (char**)realloc(s, n * sizeof(char*)); + s_new = hts_realloc_p(s, sizeof(char*), n); if (!s_new) goto err; @@ -2334,7 +2335,8 @@ static inline int insert_to_b(bidx_t *b, int bin, uint64_t beg, uint64_t end) } } else if (l->n == l->m) { uint32_t new_m = l->m ? l->m << 1 : 1; - hts_pair64_t *new_list = realloc(l->list, new_m * sizeof(hts_pair64_t)); + hts_pair64_t *new_list = hts_realloc_p(l->list, + sizeof(hts_pair64_t), new_m); if (!new_list) return -1; l->list = new_list; l->m = new_m; @@ -2354,7 +2356,7 @@ static inline int insert_to_l(lidx_t *l, int64_t _beg, int64_t _end, uint64_t of size_t new_m = l->m * 2 > end + 1 ? l->m * 2 : end + 1; uint64_t *new_offset; - new_offset = (uint64_t*)realloc(l->offset, new_m * sizeof(uint64_t)); + new_offset = hts_realloc_p(l->offset, sizeof(uint64_t), new_m); if (!new_offset) return -1; // fill unused memory with (uint64_t)-1 @@ -2483,7 +2485,7 @@ static int compress_binning(hts_idx_t *idx, int i) hts_pair64_t *new_list; kroundup32(new_m); if (new_m > INT32_MAX) return -1; // Limited by index format - new_list = realloc(q->list, new_m * sizeof(*new_list)); + new_list = hts_realloc_p(q->list, sizeof(*new_list), new_m); if (!new_list) return -1; q->m = new_m; q->list = new_list; @@ -2566,11 +2568,11 @@ int hts_idx_push(hts_idx_t *idx, int tid, hts_pos_t beg, hts_pos_t end, uint64_t bidx_t **new_bidx; lidx_t *new_lidx; - new_bidx = (bidx_t**)realloc(idx->bidx, new_m * sizeof(bidx_t*)); + new_bidx = hts_realloc_p(idx->bidx, sizeof(bidx_t*), new_m); if (!new_bidx) return -1; idx->bidx = new_bidx; - new_lidx = (lidx_t*) realloc(idx->lidx, new_m * sizeof(lidx_t)); + new_lidx = hts_realloc_p(idx->lidx, sizeof(lidx_t), new_m); if (!new_lidx) return -1; idx->lidx = new_lidx; @@ -2653,7 +2655,7 @@ int hts_idx_tbi_name(hts_idx_t *idx, int tid, const char *name) { return idx->tbi_n; uint32_t len = strlen(name)+1; - uint8_t *tmp = (uint8_t *)realloc(idx->meta, idx->l_meta + len); + uint8_t *tmp = hts_realloc_ps(idx->meta, sizeof(*tmp), idx->l_meta, len); if (!tmp) return -1; @@ -2954,7 +2956,7 @@ static int idx_read_core(hts_idx_t *idx, BGZF *fp, int fmt) if (p->n < 0) return -3; if ((size_t) p->n > SIZE_MAX / sizeof(hts_pair64_t)) return -2; p->m = p->n; - p->list = (hts_pair64_t*)malloc(p->m * sizeof(hts_pair64_t)); + p->list = hts_malloc_p(sizeof(hts_pair64_t), p->m); if (p->list == NULL) return -2; if (bgzf_read(fp, p->list, ((size_t) p->n)<<4) != ((size_t) p->n)<<4) return -1; if (is_be) swap_bins(p); @@ -2968,7 +2970,7 @@ static int idx_read_core(hts_idx_t *idx, BGZF *fp, int fmt) if (l->n < 0) return -3; if ((size_t) l->n > SIZE_MAX / sizeof(uint64_t)) return -2; l->m = l->n; - l->offset = (uint64_t*)malloc(l->n * sizeof(uint64_t)); + l->offset = hts_malloc_p(sizeof(uint64_t), l->n); if (l->offset == NULL) return -2; if (bgzf_read(fp, l->offset, l->n << 3) != l->n << 3) return -1; if (is_be) for (j = 0; j < l->n; ++j) ed_swap_8p(&l->offset[j]); @@ -3004,7 +3006,7 @@ static hts_idx_t *idx_read(const char *fn) if (is_be) for (i = 0; i < 3; ++i) ed_swap_4p(&x[i]); if (x[2]) { if (SIZE_MAX - x[2] < 1) goto fail; // Prevent possible overflow - if ((meta = (uint8_t*)malloc((size_t) x[2] + 1)) == NULL) goto fail; + if ((meta = hts_malloc_ps(sizeof(*meta), x[2], 1)) == NULL) goto fail; if (bgzf_read(fp, meta, x[2]) != x[2]) goto fail; // Prevent possible strlen past the end in tbx_index_load2 meta[x[2]] = '\0'; @@ -3029,7 +3031,7 @@ static hts_idx_t *idx_read(const char *fn) n = le_to_u32(&x[7*4]); // location of l_nm if (n > UINT32_MAX - 29) goto fail; // Prevent possible overflow idx->l_meta = 28 + n; - if ((idx->meta = (uint8_t*)malloc(idx->l_meta + 1)) == NULL) goto fail; + if ((idx->meta = hts_malloc_ps(sizeof(*idx->meta), idx->l_meta, 1)) == NULL) goto fail; // copy format, col_seq, col_beg, col_end, meta, skip, l_nm // N.B. left in little-endian byte order. memcpy(idx->meta, &x[1*4], 28); @@ -3069,7 +3071,7 @@ int hts_idx_set_meta(hts_idx_t *idx, uint32_t l_meta, uint8_t *meta, errno = ENOMEM; return -1; } - new_meta = malloc(l + 1); + new_meta = hts_malloc_ps(sizeof(*new_meta), l, 1); if (!new_meta) return -1; memcpy(new_meta, meta, l); // Prevent possible strlen past the end in tbx_index_load2 @@ -3206,7 +3208,7 @@ static inline int reg2bins(int64_t beg, int64_t end, hts_itr_t *itr, int min_shi errno = ENOMEM; return -1; } - int *new_a = realloc(itr->bins.a, new_m * sizeof(*new_a)); + int *new_a = hts_realloc_p(itr->bins.a, sizeof(*new_a), new_m); if (!new_a) return -1; itr->bins.a = new_a; itr->bins.m = new_m; @@ -3227,7 +3229,7 @@ static inline int add_to_interval(hts_itr_t *iter, bins_t *bin, if (!bin->n) return 0; - off = realloc(iter->off, (iter->n_off + bin->n) * sizeof(*off)); + off = hts_realloc_ps(iter->off, sizeof(*off), iter->n_off, bin->n); if (!off) return -2; @@ -3770,7 +3772,7 @@ int hts_itr_multi_cram(const hts_idx_t *idx, hts_itr_t *iter) tid = curr_reg->tid; if (tid >= 0) { - tmp = realloc(off, (n_off + curr_reg->count) * sizeof(*off)); + tmp = hts_realloc_ps(off, sizeof(*off), n_off, curr_reg->count); if (!tmp) goto err; off = tmp; diff --git a/hts_expr.c b/hts_expr.c index dfd15b151..87a5e7bd1 100644 --- a/hts_expr.c +++ b/hts_expr.c @@ -38,6 +38,7 @@ DEALINGS IN THE SOFTWARE. */ #include #include "htslib/hts_expr.h" +#include "htslib/hts_alloc.h" #include "htslib/hts_log.h" #include "textutils_internal.h" @@ -851,12 +852,12 @@ hts_filter_t *hts_filter_init(const char *str) { if (!f) return NULL; // Oversize to permit faster comparisons with memcmp over strcmp - size_t len = strlen(str)+100; - if (!(f->str = malloc(len))) { + size_t len = strlen(str); + if (!(f->str = hts_malloc_ps(sizeof(*f->str), len, 100))) { free(f); return NULL; } - strcpy(f->str, str); + memcpy(f->str, str, len + 1); return f; } diff --git a/htslib/hts_alloc.h b/htslib/hts_alloc.h new file mode 100644 index 000000000..41d7eefb8 --- /dev/null +++ b/htslib/hts_alloc.h @@ -0,0 +1,360 @@ +/* hts_alloc.h -- Allocation functions. + + Copyright (C) 2026 Genome Research Ltd. + + Author: Rob Davies + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. */ + +#ifndef HTSLIB_HTS_ALLOC_H +#define HTSLIB_HTS_ALLOC_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Compute saturating addition of two size_t inputs + * + * @return sum of @p a and @p b, or SIZE_MAX if the sum would overflow + */ + +static inline size_t hts_add_sat2(size_t a, size_t b) { + size_t r = a + b; + return r >= a ? r : SIZE_MAX; +} + +/** + * Compute saturating addition of three size_t inputs + * + * @return sum of @p a, @p b and @p c, or SIZE_MAX if the sum would overflow + */ + +static inline size_t hts_add_sat3(size_t a, size_t b, size_t c) { + return hts_add_sat2(hts_add_sat2(a, b), c); +} + +/** + * Compute saturating product of two size_t inputs + * + * @return product of @p a, and @p b, or SIZE_MAX if the sum would overflow + */ + +static inline size_t hts_prod_sat2(size_t a, size_t b) { + const size_t safe_limit = ((size_t) 1) << (sizeof(size_t) * 8 / 2); + if (a < safe_limit && b < safe_limit) + return a * b; + if (a == 0) + return 0; + if ((SIZE_MAX / a) < b) + return SIZE_MAX; + return a * b; +} + +#define HTS_SIZE_LIMIT (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX) + +/** + * Allocate memory with checks for overflow + * + * @param size Number of bytes to allocate + * + * @return Pointer to the allocated memory, or NULL on error + * + * The total allocated will be @p size bytes. NULL will be returned + * if the product is too big for a size_t or ptrdiff_t, or if the memory + * could not be allocated. + * + * @note Using this function helps avoid -Walloc-size-larger-than warnings + * from gcc, which doesn't like attempts to malloc more than PTRDIFF_MAX. + * + */ + +static inline void * hts_malloc(size_t size) { + if (size >= HTS_SIZE_LIMIT) { + errno = ENOMEM; + return NULL; + } + return malloc(size); +} + +/** + * Allocate memory with checks for overflow, product of sizes + * + * @param a First term of product + * @param b Secord term of product + * + * @return Pointer to the allocated memory, or NULL on error + * + * The total allocated will be @p a * @p b bytes. NULL will be returned + * if the product is too big for a size_t or ptrdiff_t, or if the memory + * could not be allocated. + * + * This function is a safer replacement for the idiom + * @code{c} + * ptr = malloc(number * sizeof(*ptr)); + * @endcode + * as it will detect cases where the product could overflow. + */ + +static inline void * hts_malloc_p(size_t a, size_t b) { + size_t prod = hts_prod_sat2(a, b); + return hts_malloc(prod); +} + +/** + * Allocate memory with checks for overflow, product of sum of sizes + * + * @param sz Size of item + * @param a First term of sum + * @param b Secord term of sum + * + * @return Pointer to the allocated memory, or NULL on error + * + * The total allocated will be @p sz * (@p a + @p b) bytes. NULL will be + * returned if the product is too big for a size_t or ptrdiff_t, or if the + * memory could not be allocated. + * + * This function is a safer replacement for the idiom + * @code{c} + * ptr = malloc((a + b) * sizeof(*ptr)); + * @endcode + * as it will detect cases where the sum and/or product could overflow. + */ + +static inline void * hts_malloc_ps(size_t sz, size_t a, size_t b) { + size_t sum = hts_add_sat2(a, b); + size_t prod = hts_prod_sat2(sz, sum); + return hts_malloc(prod); +} + +/** + * Allocate memory with checks for overflow, product of sum of sizes plus extra bytes + * + * @param sz Element size + * @param a First term of sum + * @param b Second term of sum + * @param extra Extra space to allocate, in bytes + * + * @return Pointer to the allocated memory, or NULL on error + * + * The total allocated will be (@p a + @p b) * @p sz + @p extra bytes. + * NULL will be returned if the total is too big for a size_t or + * ptrdiff_t, or if the memory could not be allocated. + * + * This function is a safer replacement for the idiom + * @code{c} + * ptr = malloc((a + b) * sizeof(*ptr) + extra); + * @endcode + * as it will detect cases where the sums and/or product could overflow. + */ + +static inline void * hts_malloc_pse(size_t sz, size_t a, size_t b, size_t extra) { + size_t sum = hts_add_sat2(a, b); + size_t prod = hts_prod_sat2(sz, sum); + size_t bytes = hts_add_sat2(prod, extra); + return hts_malloc(bytes); +} + +/** + * Allocate and clear memory with checks for overflow + * + * @param sz Size in bytes of each element + * @param num Number of elements + * + * @return Pointer to the allocated memory, or NULL on error + * + * The total allocated will be @p size bytes. NULL will be returned + * if the product is too big for a size_t or ptrdiff_t, or if the memory + * could not be allocated. + * + * @note Using this function helps avoid -Walloc-size-larger-than warnings + * from gcc, which doesn't like attempts to malloc more than PTRDIFF_MAX. + * + * @note In this function the size parameter is listed first to match + * the other hts_alloc interfaces, which is the opposite way round to calloc(). + * In practice this makes no difference as the values get multiplied together. + */ + +static inline void * hts_calloc(size_t sz, size_t num) { + if (num >= HTS_SIZE_LIMIT || sz >= HTS_SIZE_LIMIT) { + errno = ENOMEM; + return NULL; + } + return calloc(num, sz); +} + +/** + * Allocate and clear memory with checks for overflow, product of sum of sizes + * + * @param sz Element size + * @param a First term of sum + * @param b Second term of sum + * + * @return Pointer to the allocated memory, or NULL on error + * + * The total allocated will be (@p a + @p b) * @p sz + @p extra bytes. + * NULL will be returned if the total is too big for a size_t or + * ptrdiff_t, or if the memory could not be allocated. + * + * This function is a safer replacement for the idiom + * @code{c} + * ptr = calloc(a + b, sizeof(*ptr)); + * @endcode + * as it will detect cases where the sum could overflow. + */ + +static inline void * hts_calloc_ps(size_t sz, size_t a, size_t b) { + size_t sum = hts_add_sat2(a, b); + return hts_calloc(sz, sum); +} + +/** + * Allocate and clear memory with checks for overflow + * + * @param sz Element size + * @param a First term of sum + * @param b Second term of sum + * @param extra Extra space to allocate, in bytes + * + * @return Pointer to the allocated memory, or NULL on error + * + * The total allocated will be (@p a + @p b) * @p sz + @p extra bytes. + * NULL will be returned if the total is too big for a size_t or + * ptrdiff_t, or if the memory could not be allocated. + * + * This function is a safer replacement for the idiom + * @code{c} + * ptr = calloc((a + b) * sizeof(*ptr) + extra, 1); + * @endcode + * as it will detect cases where the sums and/or product could overflow. + */ + +static inline void * hts_calloc_pse(size_t sz, size_t a, size_t b, size_t extra) { + size_t sum = hts_add_sat2(a, b); + size_t prod = hts_prod_sat2(sz, sum); + size_t bytes = hts_add_sat2(prod, extra); + return hts_calloc(1, bytes); +} + +/** + * Rellocate memory with checks for overflow + * + * @return Pointer to the allocated memory, or NULL on error + */ + +static inline void * hts_realloc(void *orig, size_t size) { + if (size >= HTS_SIZE_LIMIT) { + errno = ENOMEM; + return NULL; + } + return realloc(orig, size); +} + +/** + * Rellocate memory with checks for overflow + * + * @param sz Size of item + * @param a First term of sum + * @param b Secord term of sum + * + * @return Pointer to the allocated memory, or NULL on error + * + * The total allocated will be @p sz * (@p a + @p b) bytes. NULL will be + * returned if the product is too big for a size_t or ptrdiff_t, or if the + * memory could not be allocated. + * + * This function is a safer replacement for the idiom + * @code{c} + * ptr = realloc(orig, (a + b) * sizeof(*ptr)); + * @endcode + * as it will detect cases where the sum and/or product could overflow. + */ + +static inline void * hts_realloc_p(void *orig, size_t a, size_t b) { + size_t prod = hts_prod_sat2(a, b); + return hts_realloc(orig, prod); +} + +/** + * Rellocate memory with checks for overflow + * + * @param sz Element size + * @param a First term of sum + * @param b Second term of sum + * + * @return Pointer to the allocated memory, or NULL on error + * + * The total allocated will be (@p a + @p b) * @p sz bytes. + * NULL will be returned if the total is too big for a size_t or + * ptrdiff_t, or if the memory could not be allocated. + * + * This function is a safer replacement for the idiom + * @code{c} + * ptr = realloc(orig, (a + b) * sizeof(*ptr)); + * @endcode + * as it will detect cases where the sum and/or product could overflow. + */ + +static inline void * hts_realloc_ps(void *orig, size_t sz, size_t a, size_t b) { + size_t sum = hts_add_sat2(a, b); + size_t prod = hts_prod_sat2(sz, sum); + return hts_realloc(orig, prod); +} + +/** + * Rellocate memory with checks for overflow + * + * @param sz Element size + * @param a First term of sum + * @param b Second term of sum + * @param extra Extra space to allocate, in bytes + * + * @return Pointer to the allocated memory, or NULL on error + * + * The total allocated will be (@p a + @p b) * @p sz + @p extra bytes. + * NULL will be returned if the total is too big for a size_t or + * ptrdiff_t, or if the memory could not be allocated. + * + * This function is a safer replacement for the idiom + * @code{c} + * ptr = realloc(orig, (a + b) * sizeof(*ptr) + extra); + * @endcode + * as it will detect cases where the sums and/or product could overflow. + */ + +static inline void * hts_realloc_pse(void *orig, size_t sz, size_t a, size_t b, + size_t extra) { + size_t sum = hts_add_sat2(a, b); + size_t prod = hts_prod_sat2(sz, sum); + size_t bytes = hts_add_sat2(prod, extra); + return hts_realloc(orig, bytes); +} + +#undef HTS_SIZE_LIMIT + +#ifdef __cplusplus +} +#endif + +#endif /* HTSLIB_HTS_ALLOC_H */ diff --git a/htslib/kbitset.h b/htslib/kbitset.h index 0a52958cf..2e0a44e36 100644 --- a/htslib/kbitset.h +++ b/htslib/kbitset.h @@ -55,6 +55,7 @@ #include #include #include +#include "hts_alloc.h" #define KBS_ELTBITS (CHAR_BIT * sizeof (unsigned long)) #define KBS_ELT(i) ((i) / KBS_ELTBITS) @@ -79,7 +80,7 @@ static inline kbitset_t *kbs_init2(size_t ni, int fill) { size_t n = (ni + KBS_ELTBITS-1) / KBS_ELTBITS; kbitset_t *bs = - (kbitset_t *) malloc(sizeof(kbitset_t) + n * sizeof(unsigned long)); + (kbitset_t *) hts_malloc_pse(sizeof(unsigned long), n, 0, sizeof(kbitset_t)); if (bs == NULL) return NULL; bs->n = bs->n_max = n; memset(bs->b, fill? ~0 : 0, n * sizeof (unsigned long)); @@ -104,7 +105,7 @@ static inline int kbs_resize2(kbitset_t **bsp, size_t ni_new, int fill) size_t n_new = (ni_new + KBS_ELTBITS-1) / KBS_ELTBITS; if (bs == NULL || n_new > bs->n_max) { bs = (kbitset_t *) - realloc(*bsp, sizeof(kbitset_t) + n_new * sizeof(unsigned long)); + hts_realloc_pse(*bsp, sizeof(unsigned long), n_new, 0, sizeof(kbitset_t)); if (bs == NULL) return -1; bs->n_max = n_new; diff --git a/htslib/ksort.h b/htslib/ksort.h index 7857d4c77..3a314cbc2 100644 --- a/htslib/ksort.h +++ b/htslib/ksort.h @@ -64,6 +64,7 @@ #include #include +#include "hts_alloc.h" #include "hts_defs.h" #ifndef klib_unused @@ -103,7 +104,7 @@ typedef struct { int curr, shift; \ \ a2[0] = array; \ - a2[1] = temp? temp : (type_t*)malloc(sizeof(type_t) * n); \ + a2[1] = temp? temp : (type_t*)hts_malloc_p(sizeof(type_t), n); \ for (curr = 0, shift = 0; (1ul< #include #include "htslib/kstring.h" +#include "htslib/hts_alloc.h" int kputd(double d, kstring_t *s) { int len = 0; @@ -233,7 +234,7 @@ int ksplit_core(char *s, int delimiter, int *_max, int **_offsets) if (n == max) { \ int *tmp; \ max = max? max<<1 : 2; \ - if ((tmp = (int*)realloc(offsets, sizeof(int) * max))) { \ + if ((tmp = hts_realloc_p(offsets, sizeof(int), max))) { \ offsets = tmp; \ } else { \ free(offsets); \ @@ -407,7 +408,7 @@ static int *ksBM_prep(const ubyte_t *pat, int m) int i, *suff, *prep, *bmGs, *bmBc; if (m < 1) return NULL; - prep = (int*)calloc((size_t) m + 256, sizeof(int)); + prep = hts_calloc_ps(sizeof(int), m, 256); if (!prep) return NULL; bmGs = prep; bmBc = prep + m; { // preBmBc() diff --git a/probaln.c b/probaln.c index b42f85685..764a44b88 100644 --- a/probaln.c +++ b/probaln.c @@ -35,6 +35,7 @@ #include #include #include "htslib/hts.h" +#include "htslib/hts_alloc.h" /***************************************** * Probabilistic banded glocal alignment * @@ -113,11 +114,11 @@ int probaln_glocal(const uint8_t *ref, int l_ref, const uint8_t *query, } // s[] is the scaling factor to avoid underflow - s = malloc((l_query+2) * sizeof(double)); + s = hts_malloc_ps(sizeof(*s), l_query, 2); if (!s) goto fail; // initialize qual - qual = malloc(l_query * sizeof(float)); + qual = hts_malloc_p(sizeof(float), l_query); if (!qual) goto fail; if (g_qual2prob[0] == 0) for (i = 0; i < 256; ++i) diff --git a/realn.c b/realn.c index d7e8255f8..d1b76e2f5 100644 --- a/realn.c +++ b/realn.c @@ -34,6 +34,7 @@ DEALINGS IN THE SOFTWARE. */ #include #include #include "htslib/hts.h" +#include "htslib/hts_alloc.h" #include "htslib/sam.h" int sam_cap_mapq(bam1_t *b, const char *ref, hts_pos_t ref_len, int thres) @@ -219,7 +220,7 @@ int sam_prob_realn(bam1_t *b, const char *ref, hts_pos_t ref_len, int flag) { } assert(bq == NULL); // bq was used above, but should now be NULL - bq = malloc(align_lqseq * 3 + lref); + bq = malloc(hts_add_sat2(hts_prod_sat2(align_lqseq, 3), lref)); if (!bq) goto fail; q = bq + align_lqseq; tseq = q + align_lqseq; @@ -233,7 +234,7 @@ int sam_prob_realn(bam1_t *b, const char *ref, hts_pos_t ref_len, int flag) { tref[i-xb] = seq_nt16_int[seq_nt16_table[(unsigned char)ref[i]]]; } - state = malloc(c->l_qseq * sizeof(int)); + state = hts_malloc_p(sizeof(int), c->l_qseq); if (!state) goto fail; if (probaln_glocal(tref, xe-xb, tseq, c->l_qseq, qual, &conf, state, q) == INT_MIN) { diff --git a/ref_cache/listener.c b/ref_cache/listener.c index 5062bcd9a..6c087abab 100644 --- a/ref_cache/listener.c +++ b/ref_cache/listener.c @@ -42,6 +42,7 @@ DEALINGS IN THE SOFTWARE. */ #include "misc.h" #include "options.h" #include "poll_wrap.h" +#include "../htslib/hts_alloc.h" struct Listeners { size_t nsocks; @@ -129,7 +130,7 @@ Listeners * get_listen_sockets(int port) { return NULL; } - lsocks->sockets = malloc(count * sizeof(*lsocks->sockets)); + lsocks->sockets = hts_malloc_p(sizeof(*lsocks->sockets), count); if (lsocks->sockets == NULL) { perror("Allocating socket list"); freeaddrinfo(addr_list); @@ -209,7 +210,7 @@ Listeners * adopt_listen_sockets(int min_sock_fd, int num_fds) { if (lsocks == NULL) return NULL; - lsocks->sockets = malloc((size_t) num_fds * sizeof(*lsocks->sockets)); + lsocks->sockets = hts_malloc_p(sizeof(*lsocks->sockets), (size_t) num_fds); if (lsocks->sockets == NULL) { perror("Allocating socket list"); free(lsocks); diff --git a/ref_cache/log_files.c b/ref_cache/log_files.c index 160bbfb67..259b7a745 100644 --- a/ref_cache/log_files.c +++ b/ref_cache/log_files.c @@ -43,6 +43,7 @@ DEALINGS IN THE SOFTWARE. */ #include "log_files.h" #include "options.h" +#include "../htslib/hts_alloc.h" #define LOG_NAME_LEN 80 typedef struct { @@ -200,7 +201,7 @@ Logfiles * open_logs(const Options *opts) { && (strcmp(suff, "log") == 0 || strcmp(suff, "log.gz") == 0)) { if (logfiles->nlogs == logfiles->sz) { size_t new_sz = logfiles->sz * 2; - Logfile *new_logs = realloc(logfiles->logs, new_sz * sizeof(Logfile)); + Logfile *new_logs = hts_realloc_p(logfiles->logs, sizeof(Logfile), new_sz); if (new_logs == NULL) { perror(NULL); goto fail; diff --git a/ref_cache/main.c b/ref_cache/main.c index 11a393f4e..27564ff98 100644 --- a/ref_cache/main.c +++ b/ref_cache/main.c @@ -61,6 +61,7 @@ DEALINGS IN THE SOFTWARE. */ #include "poll_wrap.h" #include "server.h" #include "upstream.h" +#include "../htslib/hts_alloc.h" // May not have been defined, depending on compiler options #ifndef NI_MAXHOST @@ -107,10 +108,10 @@ static void change_name(char *name) { static int init_children(Options *opts) { int k; - upstream = malloc((opts->max_kids + 1U) * sizeof(int)); + upstream = hts_malloc_ps(sizeof(*upstream), opts->max_kids, 1); if (upstream == NULL) return -1; - kids = malloc((opts->max_kids + 1U) * sizeof(Child_proc)); + kids = hts_malloc_ps(sizeof(*kids), opts->max_kids, 1); if (kids == NULL) return -1; for (k = 0; k <= opts->max_kids; k++) { @@ -751,8 +752,9 @@ static int add_match_addr(Options *opts, const char *addr_list) { if (opts->match_addrs_size == opts->num_match_addrs) { size_t new_size = (opts->match_addrs_size > 0 ? opts->match_addrs_size * 2 : 16); - MatchAddr *new_addrs = realloc(opts->match_addrs, - new_size * sizeof(*new_addrs)); + MatchAddr *new_addrs = hts_realloc_p(opts->match_addrs, + sizeof(*new_addrs), + new_size); if (!new_addrs) { perror("Allocating address match list"); freeaddrinfo(addrs); diff --git a/ref_cache/poll_wrap_poll.c b/ref_cache/poll_wrap_poll.c index ca28b34d7..5631b339c 100644 --- a/ref_cache/poll_wrap_poll.c +++ b/ref_cache/poll_wrap_poll.c @@ -34,6 +34,7 @@ DEALINGS IN THE SOFTWARE. */ #include #include #include "poll_wrap.h" +#include "../htslib/hts_alloc.h" #include "../cram/pooled_alloc.h" #if defined(REF_CACHE_NO_POOLED_ALLOC) @@ -74,11 +75,11 @@ Poll_wrap *pw_init(int debug) { if (pw->pool == NULL) goto fail; pw->polled_sz = INIT_POLLED_SZ; - pw->polled = malloc(pw->polled_sz * sizeof(struct pollfd)); + pw->polled = hts_malloc_p(sizeof(struct pollfd), pw->polled_sz); if (pw->polled == NULL) goto fail; pw->idx_sz = INIT_IDX_SZ; - pw->fd_index = malloc(pw->idx_sz * sizeof(unsigned int)); + pw->fd_index = hts_malloc_p(sizeof(unsigned int), pw->idx_sz); if (pw->fd_index == NULL) goto fail; pw->item_index = calloc(pw->idx_sz, sizeof(Pw_item *)); @@ -113,13 +114,13 @@ Pw_item * pw_register(Poll_wrap *pw, int fd, Pw_fd_type fd_type, if (pw->idx_sz <= (unsigned int) fd) { unsigned int new_sz = (unsigned int) fd + 1; - unsigned int *new_index = realloc(pw->fd_index, - new_sz * sizeof(unsigned int)); + unsigned int *new_index = hts_realloc_p(pw->fd_index, + sizeof(*pw->fd_index), new_sz); Pw_item **new_items; if (new_index == NULL) return NULL; pw->fd_index = new_index; - new_items = realloc(pw->item_index, new_sz * sizeof(Pw_item *)); + new_items = hts_realloc_p(pw->item_index, sizeof(*pw->item_index), new_sz); if (new_items == NULL) return NULL; memset(new_items + pw->idx_sz,0,(new_sz - pw->idx_sz) * sizeof(Pw_item *)); @@ -128,8 +129,8 @@ Pw_item * pw_register(Poll_wrap *pw, int fd, Pw_fd_type fd_type, } if (pw->npolled == pw->polled_sz) { unsigned int new_sz = pw->polled_sz * 2; - struct pollfd *new_polled = realloc(pw->polled, - new_sz * sizeof(*new_polled)); + struct pollfd *new_polled = hts_realloc_p(pw->polled, + sizeof(*pw->polled), new_sz); if (new_polled == NULL) return NULL; pw->polled = new_polled; diff --git a/regidx.c b/regidx.c index 602edebf3..20640f0cc 100644 --- a/regidx.c +++ b/regidx.c @@ -27,6 +27,7 @@ #include #include #include "htslib/hts.h" +#include "htslib/hts_alloc.h" #include "htslib/kstring.h" #include "htslib/kseq.h" #include "htslib/khash_str2int.h" @@ -184,7 +185,7 @@ int regidx_push(regidx_t *idx, char *chr_beg, char *chr_end, hts_pos_t beg, hts_ list->reg[list->nreg].end = end; if ( idx->payload_size ) { if ( mreg != list->mreg ) { - uint8_t *new_dat = realloc(list->dat, idx->payload_size*list->mreg); + uint8_t *new_dat = hts_realloc_p(list->dat, idx->payload_size, list->mreg); if (!new_dat) return -1; list->dat = new_dat; } @@ -339,12 +340,12 @@ static int reglist_build_index_(regidx_t *regidx, reglist_t *list) if ( !regidx->payload_size ) { qsort(list->reg,list->nreg,sizeof(reg_t),cmp_reg_ptrs); } else { - reg_t **ptr = malloc(sizeof(*ptr)*list->nreg); + reg_t **ptr = hts_malloc_p(sizeof(*ptr), list->nreg); if (!ptr) return -1; for (i=0; inreg; i++) ptr[i] = list->reg + i; qsort(ptr,list->nreg,sizeof(*ptr),cmp_reg_ptrs2); - uint8_t *tmp_dat = malloc(regidx->payload_size*list->nreg); + uint8_t *tmp_dat = hts_malloc_p(regidx->payload_size, list->nreg); if (!tmp_dat) { free(ptr); return -1; } for (i=0; inreg; i++) { size_t iori = ptr[i] - list->reg; @@ -355,7 +356,7 @@ static int reglist_build_index_(regidx_t *regidx, reglist_t *list) free(list->dat); list->dat = tmp_dat; - reg_t *tmp_reg = (reg_t*) malloc(sizeof(reg_t)*list->nreg); + reg_t *tmp_reg = (reg_t*) hts_malloc_p(sizeof(reg_t), list->nreg); if (!tmp_reg) { free(ptr); return -1; } for (i=0; inreg; i++) { size_t iori = ptr[i] - list->reg; diff --git a/sam.c b/sam.c index 56deec42e..dc1841910 100644 --- a/sam.c +++ b/sam.c @@ -53,6 +53,7 @@ DEALINGS IN THE SOFTWARE. */ #include "hts_internal.h" #include "sam_internal.h" #include "htslib/hfile.h" +#include "htslib/hts_alloc.h" #include "htslib/hts_endian.h" #include "htslib/hts_expr.h" #include "header.h" @@ -212,7 +213,7 @@ sam_hdr_t *sam_hdr_dup(const sam_hdr_t *h0) goto fail; } else { h->l_text = h0->text ? h0->l_text : 0; - h->text = malloc(h->l_text + 1); + h->text = hts_malloc_ps(sizeof(*h->text), h->l_text, 1); if (!h->text) goto fail; if (h0->text) memcpy(h->text, h0->text, h->l_text); @@ -592,7 +593,7 @@ int bam_set1(bam1_t *bam, // re-allocate the data buffer as needed. size_t data_len = l_qname + qname_nuls + n_cigar * 4 + (l_seq + 1) / 2 + l_seq; - if (realloc_bam_data(bam, data_len + l_aux) < 0) { + if (realloc_bam_data(bam, hts_add_sat2(data_len, l_aux)) < 0) { return -1; } @@ -2909,7 +2910,7 @@ ssize_t sam_parse_cigar(const char *in, char **end, uint32_t **a_cigar, size_t * n_cigar = read_ncigar(in); if (!n_cigar) return 0; if (n_cigar > *a_mem) { - uint32_t *a_tmp = realloc(*a_cigar, n_cigar*sizeof(**a_cigar)); + uint32_t *a_tmp = hts_realloc_p(*a_cigar, sizeof(**a_cigar), n_cigar); if (a_tmp) { *a_cigar = a_tmp; *a_mem = n_cigar; @@ -3257,7 +3258,7 @@ static void *sam_parse_worker(void *arg) { if (i >= gb->abams) { int old_abams = gb->abams; gb->abams *= 2; - b = (bam1_t *)realloc(gb->bams, gb->abams*sizeof(bam1_t)); + b = hts_realloc_p(gb->bams, sizeof(bam1_t), gb->abams); if (!b) { gb->abams /= 2; sam_state_err(fd, ENOMEM); @@ -3364,7 +3365,7 @@ static void *sam_dispatcher_read(void *vp) { if (!l) goto err; l->alloc = SAM_NBYTES; - l->data = malloc(l->alloc+8); // +8 for optimisation in sam_parse1 + l->data = hts_malloc_ps(sizeof(*l->data), l->alloc, 8); // +8 for optimisation in sam_parse1 if (!l->data) { free(l); l = NULL; @@ -3375,7 +3376,8 @@ static void *sam_dispatcher_read(void *vp) { l->next = NULL; if (l->alloc < line_frag+SAM_NBYTES/2) { - char *rp = realloc(l->data, line_frag+SAM_NBYTES/2 +8); + char *rp = hts_realloc_ps(l->data, sizeof(*rp), + line_frag, SAM_NBYTES/2 + 8); if (!rp) goto err; l->alloc = line_frag+SAM_NBYTES/2; @@ -3408,7 +3410,7 @@ static void *sam_dispatcher_read(void *vp) { // entire buffer is part of a single line if (cp == l->data) { line_frag = l->data_size; - char *rp = realloc(l->data, l->alloc * 2 + 8); + char *rp = realloc(l->data, hts_add_sat2(hts_prod_sat2(l->alloc, 2), 8)); if (!rp) goto err; l->alloc *= 2; @@ -5393,7 +5395,7 @@ static inline void mp_free(mempool_t *mp, lbnode_t *p) --mp->cnt; p->next = 0; // clear lbnode_t::next here if (mp->n == mp->max) { mp->max = mp->max? mp->max<<1 : 256; - mp->buf = (lbnode_t**)realloc(mp->buf, sizeof(lbnode_t*) * mp->max); + mp->buf = hts_realloc_p(mp->buf, sizeof(lbnode_t*), mp->max); } mp->buf[mp->n++] = p; } @@ -6031,7 +6033,7 @@ const bam_pileup1_t *bam_plp64_next(bam_plp_t iter, int *_tid, hts_pos_t *_pos, if (p->b.core.tid == iter->tid && p->beg <= iter->pos) { // here: p->end > pos; then add to pileup if (n_plp == iter->max_plp) { // then double the capacity iter->max_plp = iter->max_plp? iter->max_plp<<1 : 256; - iter->plp = (bam_pileup1_t*)realloc(iter->plp, sizeof(bam_pileup1_t) * iter->max_plp); + iter->plp = hts_realloc_p(iter->plp, sizeof(bam_pileup1_t), iter->max_plp); } iter->plp[n_plp].b = &p->b; iter->plp[n_plp].cd = p->cd; diff --git a/synced_bcf_reader.c b/synced_bcf_reader.c index 7769132fa..d7780d6e1 100644 --- a/synced_bcf_reader.c +++ b/synced_bcf_reader.c @@ -39,6 +39,7 @@ DEALINGS IN THE SOFTWARE. */ #include "htslib/kseq.h" #include "htslib/khash_str2int.h" #include "htslib/bgzf.h" +#include "htslib/hts_alloc.h" #include "htslib/thread_pool.h" #include "bcf_sr_sort.h" @@ -156,7 +157,7 @@ static int *init_filters(bcf_hdr_t *hdr, const char *filters, int *nfilters) { if ( *tmp==',' || !*tmp ) { - int *otmp = (int*) realloc(out, (nout+1)*sizeof(int)); + int *otmp = hts_realloc_ps(out, sizeof(*otmp), nout, 1); if (!otmp) goto err; out = otmp; @@ -279,9 +280,11 @@ int bcf_sr_add_hreader(bcf_srs_t *files, htsFile *file_ptr, int autoclose, const return 0; } - files->has_line = (int*) realloc(files->has_line, sizeof(int)*(files->nreaders+1)); + files->has_line = hts_realloc_ps(files->has_line, sizeof(*files->has_line), + files->nreaders, 1); files->has_line[files->nreaders] = 0; - files->readers = (bcf_sr_t*) realloc(files->readers, sizeof(bcf_sr_t)*(files->nreaders+1)); + files->readers = hts_realloc_ps(files->readers, sizeof(*files->readers), + files->nreaders, 1); bcf_sr_t *reader = &files->readers[files->nreaders++]; memset(reader,0,sizeof(bcf_sr_t)); @@ -435,7 +438,7 @@ int bcf_sr_add_hreader(bcf_srs_t *files, htsFile *file_ptr, int autoclose, const if ((auxdata = BCF_SR_AUX(files))) { //store closure status for htsfile - int *tmp = realloc(auxdata->closefile, sizeof(int) * files->nreaders); + int *tmp = hts_realloc_p(auxdata->closefile, sizeof(int), files->nreaders); if (!tmp) { hts_log_error("Failed to allocate memory"); return 0; @@ -666,7 +669,7 @@ static int _reader_fill_buffer(bcf_srs_t *files, bcf_sr_t *reader) { // Increase buffer size reader->mbuffer += 8; - reader->buffer = (bcf1_t**) realloc(reader->buffer, sizeof(bcf1_t*)*reader->mbuffer); + reader->buffer = hts_realloc_p(reader->buffer, sizeof(bcf1_t*), reader->mbuffer); for (i=8; i>0; i--) // initialize { reader->buffer[reader->mbuffer-i] = bcf_init1(); @@ -980,7 +983,8 @@ int bcf_sr_set_samples(bcf_srs_t *files, const char *fname, int is_file) continue; } - files->samples = (char**) realloc(files->samples, (files->n_smpl+1)*sizeof(const char*)); + files->samples = hts_realloc_ps(files->samples, sizeof(const char*), + files->n_smpl, 1); files->samples[files->n_smpl++] = strdup(smpl[i]); } @@ -1000,7 +1004,7 @@ int bcf_sr_set_samples(bcf_srs_t *files, const char *fname, int is_file) for (i=0; inreaders; i++) { bcf_sr_t *reader = &files->readers[i]; - reader->samples = (int*) malloc(sizeof(int)*files->n_smpl); + reader->samples = hts_malloc_p(sizeof(int), files->n_smpl); reader->n_smpl = files->n_smpl; for (j=0; jn_smpl; j++) reader->samples[j] = bcf_hdr_id2int(reader->header, BCF_DT_SAMPLE, files->samples[j]); @@ -1040,8 +1044,8 @@ static int _regions_add(bcf_sr_regions_t *reg, const char *chr, hts_pos_t start, { // the chromosome block does not exist iseq = reg->nseqs++; - reg->seq_names = (char**) realloc(reg->seq_names,sizeof(char*)*reg->nseqs); - reg->regs = (region_t*) realloc(reg->regs,sizeof(region_t)*reg->nseqs); + reg->seq_names = hts_realloc_p(reg->seq_names,sizeof(char*),reg->nseqs); + reg->regs = hts_realloc_p(reg->regs,sizeof(region_t),reg->nseqs); memset(®->regs[reg->nseqs-1],0,sizeof(region_t)); reg->seq_names[iseq] = strdup(chr); reg->regs[iseq].creg = -1; diff --git a/tabix.c b/tabix.c index bd7d100f6..39eacc8f0 100644 --- a/tabix.c +++ b/tabix.c @@ -41,6 +41,7 @@ DEALINGS IN THE SOFTWARE. */ #include "htslib/kseq.h" #include "htslib/bgzf.h" #include "htslib/hts.h" +#include "htslib/hts_alloc.h" #include "htslib/regidx.h" #include "htslib/hts_defs.h" #include "htslib/hts_log.h" @@ -154,7 +155,7 @@ static char **parse_regions(char *regions_fname, char **argv, int argc, int *nre } (*nregs) += regidx_nregs(idx); - regs = (char**) malloc(sizeof(char*)*(*nregs)); + regs = hts_malloc_p(sizeof(char*), *nregs); if (!regs) error_errno(NULL); int nseq; @@ -184,7 +185,7 @@ static char **parse_regions(char *regions_fname, char **argv, int argc, int *nre { if ( argc ) { - regs = (char**) malloc(sizeof(char*)*argc); + regs = hts_malloc_p(sizeof(char*), argc); if (!regs) error_errno(NULL); } else diff --git a/tbx.c b/tbx.c index 61721dc3a..d9d636b43 100644 --- a/tbx.c +++ b/tbx.c @@ -33,6 +33,7 @@ DEALINGS IN THE SOFTWARE. */ #include #include "htslib/tbx.h" #include "htslib/bgzf.h" +#include "htslib/hts_alloc.h" #include "htslib/hts_endian.h" #include "hts_internal.h" @@ -382,7 +383,7 @@ static int tbx_set_meta(tbx_t *tbx) khash_t(s2i) *d = (khash_t(s2i)*)tbx->dict; memcpy(x, &tbx->conf, 24); - name = (char**)malloc(sizeof(char*) * kh_size(d)); + name = hts_malloc_p(sizeof(char*), kh_size(d)); if (!name) return -1; for (k = kh_begin(d), l = 0; k != kh_end(d); ++k) { if (!kh_exist(d, k)) continue; @@ -390,7 +391,7 @@ static int tbx_set_meta(tbx_t *tbx) l += strlen(kh_key(d, k)) + 1; // +1 to include '\0' } l_nm = x[6] = l; - meta = (uint8_t*)malloc(l_nm + 28); + meta = hts_malloc_ps(sizeof(*meta), l_nm, 28); if (!meta) { free(name); return -1; } if (ed_is_big()) for (i = 0; i < 7; ++i) diff --git a/test/test-bcf-sr.c b/test/test-bcf-sr.c index 1cd198fa0..853d6d824 100644 --- a/test/test-bcf-sr.c +++ b/test/test-bcf-sr.c @@ -36,6 +36,7 @@ #include #include +#include "../htslib/hts_alloc.h" #include "../htslib/hts_defs.h" #include "../htslib/synced_bcf_reader.h" #include "../htslib/hts.h" @@ -224,7 +225,7 @@ int main(int argc, char *argv[]) error("Failed to set targets\n"); } - if (usefptr && !(htsfp = malloc(sizeof(htsFile*) * nvcf))) { + if (usefptr && !(htsfp = hts_malloc_p(sizeof(htsFile*), nvcf))) { error("Failed to allocate memory\n"); } diff --git a/test/test-vcf-api.c b/test/test-vcf-api.c index 2de39c72e..8656f792a 100644 --- a/test/test-vcf-api.c +++ b/test/test-vcf-api.c @@ -29,6 +29,7 @@ DEALINGS IN THE SOFTWARE. */ #include #include "../htslib/hts.h" +#include "../htslib/hts_alloc.h" #include "../htslib/vcf.h" #include "../htslib/vcfutils.h" #include "../htslib/kbitset.h" @@ -201,7 +202,7 @@ void write_bcf(char *fname) check0(bcf_update_info_flag(hdr, rec, "DB", NULL, 1)); check0(bcf_update_info_flag(hdr, rec, "H2", NULL, 1)); // .. FORMAT - int32_t *tmpia = (int*)malloc(bcf_hdr_nsamples(hdr)*2*sizeof(int)); + int32_t *tmpia = (int*)hts_malloc_p(2 * sizeof(*tmpia), bcf_hdr_nsamples(hdr)); tmpia[0] = bcf_gt_phased(0); tmpia[1] = bcf_gt_phased(0); tmpia[2] = bcf_gt_phased(1); diff --git a/test/test_alloc.c b/test/test_alloc.c new file mode 100644 index 000000000..b7c23f39d --- /dev/null +++ b/test/test_alloc.c @@ -0,0 +1,327 @@ +/* test_alloc.c -- hts_alloc unit tests + + Copyright (C) 2026 Genome Research Ltd. + + Author: Rob Davies + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. */ + +#include +#include +#include +#include +#include +#include +#include "../htslib/hts_alloc.h" + +typedef struct { + size_t a; + size_t b; + size_t expected; +} test_case_t; + +static int try_add_sat2(size_t a, size_t b, size_t expected, int verbose) { + size_t r_ab = hts_add_sat2(a, b); + size_t r_ba = hts_add_sat2(b, a); + int fails = 0; + if (r_ab != expected) { + fails++; + fprintf(stderr, + "Failed: hts_add_sat2(%zu, %zu) got %zu expected %zu\n", + a, b, r_ab, expected); + } else if (verbose) { + fprintf(stderr, "hts_add_sat2(%zu, %zu) = %zu\n", a, b, r_ab); + } + if (r_ba != expected) { + fails++; + fprintf(stderr, + "Failed: hts_add_sat2(%zu, %zu) got %zu expected %zu\n", + b, a, r_ba, expected); + } else if (verbose) { + fprintf(stderr, "hts_add_sat2(%zu, %zu) = %zu\n", b, a, r_ba); + } + return fails; +} + +static int test_add_sat2(int verbose) { + const test_case_t tests[] = { + { 0, 0, 0 }, + { 0, 1, 1 }, + { 1, 1, 2 }, + { 0, SIZE_MAX - 1, SIZE_MAX - 1 }, + { 1, SIZE_MAX - 1, SIZE_MAX }, + { 2, SIZE_MAX - 1, SIZE_MAX }, + { 0, SIZE_MAX, SIZE_MAX }, + { 0, SIZE_MAX, SIZE_MAX }, + { SIZE_MAX, SIZE_MAX, SIZE_MAX }, + }; + size_t n; + int fails = 0; + + for (n = 0; n < sizeof(tests)/sizeof(tests[0]); n++) { + fails += try_add_sat2(tests[n].a, tests[n].b, tests[n].expected, verbose); + } + return fails; +} + +static int try_prod_sat2(size_t a, size_t b, size_t expected, int verbose) { + size_t r_ab = hts_prod_sat2(a, b); + size_t r_ba = hts_prod_sat2(b, a); + int fails = 0; + if (r_ab != expected) { + fails++; + fprintf(stderr, + "Failed: hts_prod_sat2(%zu, %zu) got %zu expected %zu\n", + a, b, r_ab, expected); + } else if (verbose) { + fprintf(stderr, "hts_prod_sat2(%zu, %zu) = %zu\n", a, b, r_ab); + } + if (r_ba != expected) { + fails++; + fprintf(stderr, + "Failed: hts_prod_sat2(%zu, %zu) got %zu expected %zu\n", + b, a, r_ba, expected); + } else if (verbose) { + fprintf(stderr, "hts_prod_sat2(%zu, %zu) = %zu\n", b, a, r_ba); + } + return fails; +} + +static int test_prod_sat2(int verbose) { + const test_case_t tests[] = { + { 0, 0, 0 }, + { 0, 1, 0 }, + { 1, 1, 1 }, + { 2, 3, 6 }, + { 0, SIZE_MAX, 0 }, + { 1, SIZE_MAX - 1, SIZE_MAX - 1 }, + { 2, SIZE_MAX - 1, SIZE_MAX }, + { 0, SIZE_MAX, 0 }, + { 1, SIZE_MAX, SIZE_MAX }, + { 2, SIZE_MAX, SIZE_MAX }, + { SIZE_MAX, SIZE_MAX, SIZE_MAX }, + }; + size_t n, size_bits = sizeof(size_t) * 8; + int fails = 0; + + for (n = 0; n < sizeof(tests)/sizeof(tests[0]); n++) { + fails += try_prod_sat2(tests[n].a, tests[n].b, tests[n].expected, + verbose); + } + + for (n = 0; n < size_bits; n++) { + size_t a = ((size_t) 1) << n; + size_t b = ((size_t) 1) << (size_bits - 1 - n); + // Should not overflow + fails += try_prod_sat2(a, b, ((size_t) 1) << (size_bits - 1), verbose); + if (n > 0) { + // Should overflow + fails += try_prod_sat2(a, b * 2, SIZE_MAX, verbose); + } + } + + return fails; +} + +static void ptr2hex(char *out, size_t sz, void *ptr) { + if (ptr) { + snprintf(out, sz, "0x%p", ptr); + } else { + snprintf(out, sz, "NULL"); + } +} + +static int alloc_result(const char *prefix, size_t a, size_t b, + const char *suffix, void *ptr, size_t should_work, + int verbose) { + char pbuf[32]; + int failed = 0; + if ((ptr != NULL) ^ should_work) { + failed = 1; + ptr2hex(pbuf, sizeof(pbuf), ptr); + fprintf(stderr, "Failed: %s%zu, %zu%s got %s expected %s\n", + prefix, a, b, suffix, pbuf, should_work ? "pointer" : "NULL"); + } else if (verbose) { + ptr2hex(pbuf, sizeof(pbuf), ptr); + fprintf(stderr, "%s%zu, %zu%s = %s\n", prefix, a, b, suffix, pbuf); + } + return failed; +} + +static int test_malloc(unsigned long max_mb, int verbose) { + const size_t size_limit = PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX; + const size_t max_bytes = hts_prod_sat2(1024*1024, max_mb); + test_case_t tests[] = { + { 1, 1, 1 }, + { max_bytes, 1, 1 }, + { 1, max_bytes, 1 }, + { max_bytes / 2, 2, 1 }, + { 2, max_bytes / 2, 1 }, + { size_limit, 1, 0 }, + { 1, size_limit, 0 }, + { 2, SIZE_MAX / 2 + 100, 0 }, + { SIZE_MAX / 2 + 100, 2, 0 }, + }; + size_t n; + int fails = 0, i; + for (n = 0; n < sizeof(tests)/sizeof(tests[0]); n++) { + void *ptr = hts_malloc_p(tests[n].a, tests[n].b); + fails += alloc_result("hts_malloc_p(", tests[n].a, tests[n].b, ")", + ptr, tests[n].expected, verbose); + free(ptr); + + if (tests[n].b > 100) { + char suffix[32]; + ptr = hts_malloc_ps(tests[n].a, tests[n].b - 100, 100); + fails += alloc_result("hts_malloc_ps(", + tests[n].a, tests[n].b - 100, ", 100)", + ptr, tests[n].expected, verbose); + free(ptr); + + ptr = hts_calloc_ps(tests[n].a, tests[n].b - 100, 100); + fails += alloc_result("hts_calloc_ps(", + tests[n].a, tests[n].b - 100, ", 100)", + ptr, tests[n].expected, verbose); + free(ptr); + + snprintf(suffix, sizeof(suffix), ", %zu)", tests[n].a * 100); + ptr = hts_malloc_pse(tests[n].a, tests[n].b - 100, 0, + tests[n].a * 100); + fails += alloc_result("hts_malloc_pse(", + tests[n].a, tests[n].b - 100, suffix, + ptr, tests[n].expected, verbose); + free(ptr); + + ptr = hts_calloc_pse(tests[n].a, tests[n].b - 100, 0, + tests[n].a * 100); + fails += alloc_result("hts_calloc_pse(", + tests[n].a, tests[n].b - 100, suffix, + ptr, tests[n].expected, verbose); + free(ptr); + } + + if (tests[n].expected) { + ptr = hts_malloc_ps(tests[n].a, tests[n].b, size_limit); + fails += alloc_result("hts_malloc_ps(", + tests[n].a, tests[n].b, ", size_limit)", + ptr, 0, verbose); + free(ptr); + + ptr = hts_malloc_pse(tests[n].a, tests[n].b, 0, size_limit); + fails += alloc_result("hts_malloc_pse(", + tests[n].a, tests[n].b, ", 0, size_limit)", + ptr, 0, verbose); + free(ptr); + } + + for (i = 0; i < 2; i++) { + // i == 0 start with a NULL pointer + // i == 1 start with an allocted pointer + void *tmp = i ? malloc(1) : NULL; + const char *prefix = i ? "hts_realloc_p(ptr, " : "hts_realloc_p(NULL, "; + ptr = hts_realloc_p(tmp, tests[n].a, tests[n].b); + fails += alloc_result(prefix, tests[n].a, tests[n].b, ")", + ptr, tests[n].expected, verbose); + free(ptr ? ptr : tmp); + + if (tests[n].b > 100) { + char suffix[32]; + tmp = i ? malloc(1) : NULL; + prefix = i ? "hts_realloc_ps(ptr, " : "hts_realloc_ps(NULL, "; + ptr = hts_realloc_ps(tmp, tests[n].a, tests[n].b - 100, 100); + fails += alloc_result(prefix, + tests[n].a, tests[n].b - 100, ", 100)", + ptr, tests[n].expected, verbose); + free(ptr ? ptr : tmp); + + tmp = i ? malloc(1) : NULL; + prefix = i ? "hts_realloc_pse(ptr, " : "hts_realloc_pse(NULL, "; + snprintf(suffix, sizeof(suffix), ", %zu)", tests[n].a * 100); + ptr = hts_realloc_pse(tmp, tests[n].a, tests[n].b - 100, 0, + tests[n].a * 100); + fails += alloc_result(prefix, + tests[n].a, tests[n].b - 100, suffix, + ptr, tests[n].expected, verbose); + free(ptr ? ptr : tmp); + } + + if (tests[n].expected) { + tmp = i ? malloc(1) : NULL; + prefix = i ? "hts_realloc_ps(ptr, " : "hts_realloc_ps(NULL, "; + ptr = hts_realloc_ps(tmp, tests[n].a, tests[n].b, size_limit); + fails += alloc_result("hts_realloc_ps(NULL, ", + tests[n].a, tests[n].b, ", size_limit)", + ptr, 0, verbose); + free(ptr ? ptr : tmp); + + tmp = i ? malloc(1) : NULL; + prefix = i ? "hts_realloc_pse(ptr, " : "hts_realloc_pse(NULL, "; + ptr = hts_realloc_pse(tmp, tests[n].a, tests[n].b, 0, size_limit); + fails += alloc_result("hts_realloc_pse(NULL, ", + tests[n].a, tests[n].b, ", 0, size_limit)", + ptr, 0, verbose); + free(ptr ? ptr : tmp); + } + } + } + return fails; +} + +void show_help(FILE *fp) { + fprintf(fp, "Usage: test_alloc [-m ] [-v]\n"); +} + +int main(int argc, char **argv) { + int fails = 0; + int verbose = 0; + unsigned long max_mb = 10, max_max_mb = sizeof(size_t) > 4 ? 50000 : 2100; + int opt; + + while ((opt = getopt(argc, argv, "m:v")) > 0) { + switch (opt) { + case 'm': + max_mb = strtoul(optarg, NULL, 0); + if (max_mb < 1 || max_mb > max_max_mb) { + fprintf(stderr, "test_alloc: -m should be between 1 and %lu\n", + max_max_mb); + show_help(stderr); + return EXIT_FAILURE; + } + break; + case 'v': + verbose = 1; + break; + case 'h': + show_help(stdout); + return EXIT_SUCCESS; + default: + fprintf(stderr, "test_alloc: Unknown option '%c'\n", opt); + show_help(stderr); + return EXIT_FAILURE; + } + } + + fails += test_add_sat2(verbose); + fails += test_prod_sat2(verbose); + fails += test_malloc(max_mb, verbose); + if (fails > 0) { + fprintf(stderr, "test_alloc: %d tests failed\n", fails); + } + return fails == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/test/test_khash.c b/test/test_khash.c index 76ff1879c..792cd34ab 100644 --- a/test/test_khash.c +++ b/test/test_khash.c @@ -40,6 +40,7 @@ DEALINGS IN THE SOFTWARE. */ #include #include +#include "../htslib/hts_alloc.h" #include "../htslib/khash.h" #include "../htslib/kroundup.h" @@ -68,7 +69,7 @@ char * make_keys(size_t num, size_t kl) { char *keys; if (num > MAX_ENTRIES) return NULL; - keys = malloc(kl * num); + keys = hts_malloc_p(kl, num); if (!keys) { perror(NULL); return NULL; @@ -285,7 +286,7 @@ static size_t read_keys(const char *keys_file, char **keys_out, if (key < end) nkeys++; } - key_locations = malloc(nkeys * sizeof(*key_locations)); + key_locations = hts_malloc_p(sizeof(*key_locations), nkeys); if (!key_locations) goto fail; diff --git a/thread_pool.c b/thread_pool.c index 2370aa82e..4d70047f2 100644 --- a/thread_pool.c +++ b/thread_pool.c @@ -40,6 +40,7 @@ DEALINGS IN THE SOFTWARE. */ #include #include "thread_pool_internal.h" +#include "htslib/hts_alloc.h" #include "htslib/hts_log.h" // Minimum stack size for threads. Required for some rANS codecs @@ -738,12 +739,12 @@ hts_tpool *hts_tpool_init(int n) { p->t_stack = NULL; p->n_count = 0; p->n_running = 0; - p->t = malloc(n * sizeof(p->t[0])); + p->t = hts_malloc_p(sizeof(p->t[0]), n); if (!p->t) { free(p); return NULL; } - p->t_stack = malloc(n * sizeof(*p->t_stack)); + p->t_stack = hts_malloc_p(sizeof(*p->t_stack), n); if (!p->t_stack) { free(p->t); free(p); diff --git a/vcf.c b/vcf.c index 544fe8c01..3b8970962 100644 --- a/vcf.c +++ b/vcf.c @@ -46,6 +46,7 @@ DEALINGS IN THE SOFTWARE. */ #include "htslib/tbx.h" #include "htslib/hfile.h" #include "hts_internal.h" +#include "htslib/hts_alloc.h" #include "htslib/hts_endian.h" #include "htslib/khash_str2int.h" #include "htslib/kstring.h" @@ -248,7 +249,7 @@ static int bcf_hdr_add_sample_len(bcf_hdr_t *h, const char *s, size_t len) // Ensure space is available in h->samples size_t n = kh_size(d); - char **new_samples = realloc(h->samples, sizeof(char*) * (n + 1)); + char **new_samples = hts_realloc_ps(h->samples, sizeof(*h->samples), n, 1); if (!new_samples) { free(sdup); return -1; @@ -324,7 +325,7 @@ int bcf_hdr_sync(bcf_hdr_t *h) { bcf_idpair_t *new_idpair; // this should be true only for i=2, BCF_DT_SAMPLE - new_idpair = (bcf_idpair_t*) realloc(h->id[i], kh_size(d)*sizeof(bcf_idpair_t)); + new_idpair = hts_realloc_p(h->id[i], sizeof(bcf_idpair_t), kh_size(d)); if (!new_idpair) return -1; h->n[i] = kh_size(d); h->id[i] = new_idpair; @@ -381,9 +382,9 @@ bcf_hrec_t *bcf_hrec_dup(bcf_hrec_t *hrec) if (!out->value) goto fail; } out->nkeys = hrec->nkeys; - out->keys = (char**) malloc(sizeof(char*)*hrec->nkeys); + out->keys = hts_malloc_p(sizeof(char*), hrec->nkeys); if (!out->keys) goto fail; - out->vals = (char**) malloc(sizeof(char*)*hrec->nkeys); + out->vals = hts_malloc_p(sizeof(char*), hrec->nkeys); if (!out->vals) goto fail; int i, j = 0; for (i=0; inkeys; i++) @@ -442,14 +443,14 @@ int bcf_hrec_add_key(bcf_hrec_t *hrec, const char *str, size_t len) char **tmp; size_t n = hrec->nkeys + 1; assert(len > 0 && len < SIZE_MAX); - tmp = realloc(hrec->keys, sizeof(char*)*n); + tmp = hts_realloc_p(hrec->keys, sizeof(char*), n); if (!tmp) return -1; hrec->keys = tmp; - tmp = realloc(hrec->vals, sizeof(char*)*n); + tmp = hts_realloc_p(hrec->vals, sizeof(char*), n); if (!tmp) return -1; hrec->vals = tmp; - hrec->keys[hrec->nkeys] = (char*) malloc((len+1)*sizeof(char)); + hrec->keys[hrec->nkeys] = hts_malloc_ps(sizeof(char), len, 1); if (!hrec->keys[hrec->nkeys]) return -1; memcpy(hrec->keys[hrec->nkeys],str,len); hrec->keys[hrec->nkeys][len] = 0; @@ -471,7 +472,7 @@ int bcf_hrec_set_val(bcf_hrec_t *hrec, int i, const char *str, size_t len, int i errno = ENOMEM; return -1; } - hrec->vals[i] = (char*) malloc((len+3)*sizeof(char)); + hrec->vals[i] = hts_malloc_ps(sizeof(char), len, 3); if (!hrec->vals[i]) return -1; hrec->vals[i][0] = '"'; memcpy(&hrec->vals[i][1],str,len); @@ -484,7 +485,7 @@ int bcf_hrec_set_val(bcf_hrec_t *hrec, int i, const char *str, size_t len, int i errno = ENOMEM; return -1; } - hrec->vals[i] = (char*) malloc((len+1)*sizeof(char)); + hrec->vals[i] = hts_malloc_ps(sizeof(char), len, 1); if (!hrec->vals[i]) return -1; memcpy(hrec->vals[i],str,len); hrec->vals[i][len] = 0; @@ -495,11 +496,11 @@ int bcf_hrec_set_val(bcf_hrec_t *hrec, int i, const char *str, size_t len, int i int hrec_add_idx(bcf_hrec_t *hrec, int idx) { int n = hrec->nkeys + 1; - char **tmp = (char**) realloc(hrec->keys, sizeof(char*)*n); + char **tmp = hts_realloc_p(hrec->keys, sizeof(char*), n); if (!tmp) return -1; hrec->keys = tmp; - tmp = (char**) realloc(hrec->vals, sizeof(char*)*n); + tmp = hts_realloc_p(hrec->vals, sizeof(char*), n); if (!tmp) return -1; hrec->vals = tmp; @@ -666,7 +667,7 @@ bcf_hrec_t *bcf_hdr_parse_line(const bcf_hdr_t *h, const char *line, int *len) hrec = (bcf_hrec_t*) calloc(1,sizeof(bcf_hrec_t)); if (!hrec) { *len = -1; return NULL; } - hrec->key = (char*) malloc(sizeof(char)*(n+1)); + hrec->key = hts_malloc_ps(sizeof(char), n, 1); if (!hrec->key) goto fail; memcpy(hrec->key,p,n); hrec->key[n] = 0; @@ -676,7 +677,7 @@ bcf_hrec_t *bcf_hdr_parse_line(const bcf_hdr_t *h, const char *line, int *len) if ( *p!='<' ) // generic field, e.g. ##samtoolsVersion=0.1.18-r579 { while ( *q && *q!='\n' ) q++; - hrec->value = (char*) malloc((q-p+1)*sizeof(char)); + hrec->value = hts_malloc_p(sizeof(char), (q-p+1)); if (!hrec->value) goto fail; memcpy(hrec->value, p, q-p); hrec->value[q-p] = 0; @@ -1180,7 +1181,7 @@ int bcf_hdr_add_hrec(bcf_hdr_t *hdr, bcf_hrec_t *hrec) // New record, needs to be added int n = hdr->nhrec + 1; - bcf_hrec_t **new_hrec = realloc(hdr->hrec, n*sizeof(bcf_hrec_t*)); + bcf_hrec_t **new_hrec = hts_realloc_p(hdr->hrec, sizeof(bcf_hrec_t*), n); if (!new_hrec) { free(str.s); bcf_hdr_unregister_hrec(hdr, hrec); @@ -3772,7 +3773,7 @@ static int vcf_parse_filter(kstring_t *str, const bcf_hdr_t *h, bcf1_t *v, char for (r = p; *r; ++r) if (*r == ';') ++n_flt; if (n_flt > max_n_flt) { - a_flt = malloc(n_flt * sizeof(*a_flt)); + a_flt = hts_malloc_p(sizeof(*a_flt), n_flt); if (!a_flt) { hts_log_error("Could not allocate memory at %s:%"PRIhts_pos, bcf_seqname_safe(h,v), v->pos+1); v->errcode |= BCF_ERR_LIMITS; // No appropriate code? @@ -3878,7 +3879,7 @@ static int vcf_parse_info(kstring_t *str, const bcf_hdr_t *h, bcf1_t *v, char *p if (*t == ',') ++n_val; // Check both int and float size in one step for simplicity if (n_val > max_n_val) { - int32_t *a_tmp = (int32_t *)realloc(a_val, n_val * sizeof(*a_val)); + int32_t *a_tmp = hts_realloc_p(a_val, sizeof(*a_val), n_val); if (!a_tmp) { hts_log_error("Could not allocate memory at %s:%"PRIhts_pos, bcf_seqname_safe(h,v), v->pos+1); v->errcode |= BCF_ERR_LIMITS; // No appropriate code? @@ -4486,7 +4487,7 @@ int vcf_format(const bcf_hdr_t *h, const bcf1_t *v, kstring_t *s) // No real gain to be had in handling unpacked data here, // but it doesn't cost us much in complexity either and // it gives us flexibility. - fmt = malloc(v->n_fmt * sizeof(*fmt)); + fmt = hts_malloc_p(sizeof(*fmt), v->n_fmt); if (!fmt) return -1; } @@ -5032,7 +5033,7 @@ int bcf_translate(const bcf_hdr_t *dst_hdr, bcf_hdr_t *src_hdr, bcf1_t *line) int dict; for (dict=0; dict<2; dict++) // BCF_DT_ID and BCF_DT_CTG { - src_hdr->transl[dict] = (int*) malloc(src_hdr->n[dict]*sizeof(int)); + src_hdr->transl[dict] = hts_malloc_p(sizeof(int), src_hdr->n[dict]); for (i=0; in[dict]; i++) { if ( !src_hdr->id[dict][i].key ) // gap left after removed BCF header lines @@ -5276,7 +5277,7 @@ int bcf_hdr_set_samples(bcf_hdr_t *hdr, const char *samples, int is_file) else { // Make new list and dictionary with desired samples - char **samples = (char**) malloc(sizeof(char*)*bcf_hdr_nsamples(hdr)); + char **samples = hts_malloc_p(sizeof(char*), bcf_hdr_nsamples(hdr)); vdict_t *new_dict, *d; int k, res; if (!samples) return -1; @@ -5447,7 +5448,8 @@ static int bcf_set_variant_types(bcf1_t *b) bcf_dec_t *d = &b->d; if ( d->n_var < b->n_allele ) { - bcf_variant_t *new_var = realloc(d->var, sizeof(bcf_variant_t)*b->n_allele); + bcf_variant_t *new_var = hts_realloc_p(d->var, sizeof(bcf_variant_t), + b->n_allele); if (!new_var) return -1; d->var = new_var; @@ -5692,7 +5694,7 @@ int bcf_update_format_string(const bcf_hdr_t *hdr, bcf1_t *line, const char *key int len = strlen(values[i]); if ( len > max_len ) max_len = len; } - char *out = (char*) malloc(max_len*n); + char *out = hts_malloc_p(max_len, n); if ( !out ) return -2; for (i=0; ilen ) { *ndst = info->len; - *dst = realloc(*dst, *ndst * size1); + *dst = hts_realloc_p(*dst, *ndst, size1); } #define BRANCH(type_t, convert, is_missing, is_vector_end, set_missing, set_regular, out_type_t) do { \ @@ -6166,7 +6168,7 @@ int bcf_get_format_string(const bcf_hdr_t *hdr, bcf1_t *line, const char *tag, c int nsmpl = bcf_hdr_nsamples(hdr); if ( !*dst ) { - *dst = (char**) malloc(sizeof(char*)*nsmpl); + *dst = hts_malloc_p(sizeof(char*), nsmpl); if ( !*dst ) return -4; // could not alloc (*dst)[0] = NULL; } @@ -6226,7 +6228,7 @@ int bcf_get_format_values(const bcf_hdr_t *hdr, bcf1_t *line, const char *tag, v if ( *ndst < fmt->n*nsmpl ) { *ndst = fmt->n*nsmpl; - *dst = realloc(*dst, *ndst*size1); + *dst = hts_realloc_p(*dst, *ndst, size1); if ( !*dst ) return -4; // could not alloc } diff --git a/vcfutils.c b/vcfutils.c index 3e6abb6c8..94350c903 100644 --- a/vcfutils.c +++ b/vcfutils.c @@ -27,6 +27,7 @@ DEALINGS IN THE SOFTWARE. */ #include #include "htslib/vcfutils.h" +#include "htslib/hts_alloc.h" #include "htslib/kbitset.h" int bcf_calc_ac(const bcf_hdr_t *header, bcf1_t *line, int *ac, int which) @@ -667,7 +668,7 @@ int bcf_remove_allele_set(const bcf_hdr_t *header, bcf1_t *line, const struct kb const char *cardinalities[] = { "fixed", ".", "A", "G", "R", "P", "LA", "LG", "LR", "M" }; - int *map = malloc(line->n_allele * sizeof(int)); + int *map = hts_malloc_p(sizeof(int), line->n_allele); int *laa = NULL, *laa_map = NULL, *lr_orig = NULL; uint8_t *dat = NULL; int num_laa, laa_size = 0, laa_map_stride = 0; @@ -1002,10 +1003,11 @@ int bcf_remove_allele_set(const bcf_hdr_t *header, bcf1_t *line, const struct kb int num_laa_vals = num_laa / line->n_sample; laa_map_stride = num_laa_vals + 1; int max_k = 0; - laa_map = malloc(sizeof(*laa_map) * laa_map_stride * line->n_sample); + laa_map = hts_malloc_p(sizeof(*laa_map), + hts_prod_sat2(laa_map_stride, line->n_sample)); if (!laa_map) goto err; - lr_orig = malloc(sizeof(*lr_orig) * line->n_sample); + lr_orig = hts_malloc_p(sizeof(*lr_orig), line->n_sample); if (!lr_orig) goto err; int laa_changed = 0;