From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by sourceware.org (Postfix) with ESMTPS id 41DE63857C5F for ; Wed, 24 Mar 2021 17:06:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 41DE63857C5F Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tdevries@suse.de X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 24162AB8A; Wed, 24 Mar 2021 17:06:13 +0000 (UTC) Date: Wed, 24 Mar 2021 18:06:06 +0100 From: Tom de Vries To: dwz@sourceware.org, jakub@redhat.com, mark@klomp.org Subject: [committed] Fix memory leak in write_multifile Message-ID: <20210324170604.GA2653@delia> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.10.1 (2018-07-13) X-Spam-Status: No, score=-12.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: dwz@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Dwz mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 24 Mar 2021 17:06:16 -0000 Hi, When building dwz with -fsanitize=address, we run into some memory leaks: ... $ cp hello 1; ./dwz 1; cp 1 2; ./dwz -m 3 1 2 ./dwz: 1: DWARF compression not beneficial - old size 3372 new size 3372 ./dwz: 2: DWARF compression not beneficial - old size 3372 new size 3372 ================================================================= ==8024==ERROR: LeakSanitizer: detected memory leaks Direct leak of 432 byte(s) in 6 object(s) allocated from: #0 0x7f7ab92cc6d8 in __interceptor_calloc \ (/usr/lib64/libasan.so.4+0xdc6d8) #1 0x475dc1 in htab_try_create hashtab.c:164 #2 0x44c610 in build_abbrevs dwz.c:11230 #3 0x44ee00 in compute_abbrevs dwz.c:11510 #4 0x46f07c in dwz dwz.c:15396 #5 0x474e0d in dwz_files_1 dwz.c:16327 #6 0x475699 in dwz_files dwz.c:16417 #7 0x4759fc in main dwz.c:16458 #8 0x7f7ab8c41349 in __libc_start_main (/lib64/libc.so.6+0x24349) Indirect leak of 2928 byte(s) in 6 object(s) allocated from: #0 0x7f7ab92cc6d8 in __interceptor_calloc \ (/usr/lib64/libasan.so.4+0xdc6d8) #1 0x475de7 in htab_try_create hashtab.c:168 #2 0x44c610 in build_abbrevs dwz.c:11230 #3 0x44ee00 in compute_abbrevs dwz.c:11510 #4 0x46f07c in dwz dwz.c:15396 #5 0x474e0d in dwz_files_1 dwz.c:16327 #6 0x475699 in dwz_files dwz.c:16417 #7 0x4759fc in main dwz.c:16458 #8 0x7f7ab8c41349 in __libc_start_main (/lib64/libc.so.6+0x24349) SUMMARY: AddressSanitizer: 3360 byte(s) leaked in 12 allocation(s). ... A more concrete way to show some of the leaks is by using this patch on build_abbrevs: ... + assert (cu->cu_new_abbrev == NULL); cu->cu_new_abbrev = h; return 0; } ... which triggers here: ... #4 0x00000000004211b1 in build_abbrevs (cu=0x7ffff65f0e38, t=0x64e640, ndies=0x7fffffffd81c, vec=0x649280 ) at dwz.c:11239 #5 0x0000000000421db2 in compute_abbrevs (dso=0x0) at dwz.c:11511 #6 0x000000000042fa2c in write_multifile (dso=0x64c210) at dwz.c:15104 ... We could just do a htab_delete in build_abbrevs, which takes care of all the leaks detected by the assert. But write_multifile drops CUs from the cu list if cu->cu_die->die_no_multifile == 1, and if a dropped CU has cu->cu_new_abbrev != NULL then cu_new_abbrev is still leaked. Fix this by calling htab_delete in the loop that drops the CUs. Committed to trunk. Thanks, - Tom Fix memory leak in write_multifile 2021-03-24 Tom de Vries PR dwz/27643 * dwz.c (write_multifile): Clean up cu->cu_new_abbrev to fix memory leak. --- dwz.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/dwz.c b/dwz.c index c115b54..b212d6d 100644 --- a/dwz.c +++ b/dwz.c @@ -15092,10 +15092,15 @@ write_multifile (DSO *dso) dw_cu_ref *cup; for (cup = &first_cu; *cup && (*cup)->cu_kind != CU_TYPES; ) - if ((*cup)->cu_die->die_no_multifile == 0) - cup = &(*cup)->cu_next; - else - *cup = (*cup)->cu_next; + { + if ((*cup)->cu_new_abbrev) + htab_delete ((*cup)->cu_new_abbrev); + + if ((*cup)->cu_die->die_no_multifile == 0) + cup = &(*cup)->cu_next; + else + *cup = (*cup)->cu_next; + } *cup = NULL; multifile_mode = MULTIFILE_MODE_WR; if (tracing)