From patchwork Sun Aug 16 06:59:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Jean-No=C3=ABl_Avila_via_GitGitGadget?= X-Patchwork-Id: 11715977 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4E09414F6 for ; Sun, 16 Aug 2020 06:59:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3656B206F4 for ; Sun, 16 Aug 2020 06:59:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="lC+ZQAxv" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729376AbgHPG7P (ORCPT ); Sun, 16 Aug 2020 02:59:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45008 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728364AbgHPG7P (ORCPT ); Sun, 16 Aug 2020 02:59:15 -0400 Received: from mail-wr1-x444.google.com (mail-wr1-x444.google.com [IPv6:2a00:1450:4864:20::444]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4554AC061786 for ; Sat, 15 Aug 2020 23:59:15 -0700 (PDT) Received: by mail-wr1-x444.google.com with SMTP id 88so11860975wrh.3 for ; Sat, 15 Aug 2020 23:59:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=JArmeROMmkV4jbhZczOcNlFtBp4VTj32CPteB0gmQQ0=; b=lC+ZQAxvLJKpzqxGljA2fZSK0jlblSIQV+O7zSaUORtneB4x5P8xSq/uK5riXlqBGe zp5K8KCp1kxoF6UMMCwcYbdVXTNSPx1hi822omi6v3GQ9tezJSNQYlcfLvTuZrEFnMMr U0xzYHtP1bk9OGdLZ8YACaMB53knKhBXbDXhYN9W6xqMjqzt0zKP73BxqgcX4aFDrP0n dhV5L0ZrbZx8Z9ZjoxD58+swmip3HsNy19QhI/1PNXGZlexjT4AZ8vy/kADwVHsdxWYK eIMZE/chO2aVHhr41bDdjbyevSIMtUAS5dY5AZnbaT5/dUSynn+gIf4BaCxLBS09bbdG 6Jdg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=JArmeROMmkV4jbhZczOcNlFtBp4VTj32CPteB0gmQQ0=; b=XvzbqmjWi0ONhDHI4ZEoRkO9Zemn/cSuQQaVMTUyPa7vi6x8NfOoA8OhhVGukm0cHN eh4u6n0ZW5NIdUVPBqoeBxsOCnYe+gQh9RH66UhQ/vNCFjHX1SULudmQn6z4INBJ6eNm 6YQ2KYOd9S39LRIMfY1pyP/jnSgWZcgqcxesSlbzBTc83FjxYUzJIUiIsT7Ej7MHTdzJ TOjHm853/4bxtg3lg75dFXlgAoN6CKw6/4/Ti2lJl4SG81iUMoRcNafmc0vm1rxr8Pua XQv0WtPbSwernWsX/S5xCdWokQ1PGvtuRHHuKlE9WD7sYpA/Lcb69yUIDstQQ3qIi6K2 TCbg== X-Gm-Message-State: AOAM532ucm7Qqa5e3Liw1OmVl+kfmjKqM9SVqR8rNQ1jnU+onn5LK0PE 0nCDCpw2fJluvJ8XQ2TDvsBTuhegAdU= X-Google-Smtp-Source: ABdhPJzfTbO0a4+CkM37VbVKDWOZFtbn15YBdmms6p03p87pYK5EABiwjSxkdVO0tGLrc+kxFFCJCw== X-Received: by 2002:a5d:4604:: with SMTP id t4mr9497250wrq.417.1597561153817; Sat, 15 Aug 2020 23:59:13 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id i4sm25490399wrw.26.2020.08.15.23.59.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 15 Aug 2020 23:59:13 -0700 (PDT) Message-Id: <932741d7598ca2934dbca40f715ba2d3819fcc51.1597561152.git.gitgitgadget@gmail.com> In-Reply-To: References: From: "Elijah Newren via GitGitGadget" Date: Sun, 16 Aug 2020 06:59:09 +0000 Subject: [PATCH 1/3] dir: fix leak of parent_hashmap and recursive_hashmap Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Elijah Newren , Elijah Newren Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren Commit 96cc8ab531 ("sparse-checkout: use hashmaps for cone patterns", 2019-11-21) added a parent_hashmap and recursive_hashmap to each struct pattern_list and initialized these in add_patterns_from_buffer() but did not make sure to add necessary code to clear_pattern_list() to free these new structures. Call hashmap_free_() on each to plug this memory leak. Signed-off-by: Elijah Newren --- dir.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dir.c b/dir.c index fe64be30ed..08df469bf7 100644 --- a/dir.c +++ b/dir.c @@ -916,6 +916,10 @@ void clear_pattern_list(struct pattern_list *pl) free(pl->patterns[i]); free(pl->patterns); free(pl->filebuf); + hashmap_free_(&pl->parent_hashmap, + offsetof(struct pattern_entry, ent)); + hashmap_free_(&pl->recursive_hashmap, + offsetof(struct pattern_entry, ent)); memset(pl, 0, sizeof(*pl)); } From patchwork Sun Aug 16 06:59:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Jean-No=C3=ABl_Avila_via_GitGitGadget?= X-Patchwork-Id: 11715979 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 93C1B722 for ; Sun, 16 Aug 2020 06:59:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7324B2065C for ; Sun, 16 Aug 2020 06:59:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="R5MBHfVH" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729481AbgHPG7S (ORCPT ); Sun, 16 Aug 2020 02:59:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45014 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728364AbgHPG7Q (ORCPT ); Sun, 16 Aug 2020 02:59:16 -0400 Received: from mail-wr1-x443.google.com (mail-wr1-x443.google.com [IPv6:2a00:1450:4864:20::443]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F2E18C061786 for ; Sat, 15 Aug 2020 23:59:15 -0700 (PDT) Received: by mail-wr1-x443.google.com with SMTP id r15so1925964wrp.13 for ; Sat, 15 Aug 2020 23:59:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=IxJdTKCZwVzThoMxWIXx9IZir8S1e+YUZRU8upg7dvs=; b=R5MBHfVH8r/W8H9IsQRVbYqyV5JAHeenvzBEKf/UcvP+OQIi2lWCQEnRteI3zwoThf 77UWa41aGWvnpgPKNJ7ffkIPUVq1IBWNRG3uaClses1Aa4gSvmsxbpCQPgQE7MOHG0O+ 2xFVuTrN7N+wSIw2No8l8sDlb1aOFNuNEpQp+jHj2LV2xOv0cRvfI+eXmUIYas8Klgkh TvYqs/c48k3LEfu6pgKqQGk4TbJu2g2W4tGjgECYRlRuYjgCqMwW9n3vUAC4sd60HqSt bAnrUVRB6fqu1PzWmMWltz3KiXk4s3dVqUZoDNtSJdcVVZXqBXqmQITit9gzU7OS/onY ydYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=IxJdTKCZwVzThoMxWIXx9IZir8S1e+YUZRU8upg7dvs=; b=WRicutfRx5MQHR7b3rnBV3bkSPFT/qQCxodIzDlsEdkluebZUQRZ7SQyBQ4q2UrPci nii0upSN8FfMQB0YBfOxIEakpy9O60tr2ejKIv9jRUCl+t81VG+2oyhV++NhpGBKbBQ5 Lc3fLAVCxOMFgp5nx25W8vX1Rq1X5ho85VNsV6k8+UhK0ZzAbGhGbHmQ20StE2Byyd5u Bg5+IgQLLuIVpWBq9iweDBTJ7Y9fxYyWSCL3Sf0yHwrC/V0wVBq+jVyJ+bb7zK26VprE ANNavIdyKjV1+VMDxjNr83zmvdWAFrFAMS5/sdku+W7q+z2Fckcu1dqkUC7Zy3KGTx9O VDQA== X-Gm-Message-State: AOAM530ysE2HZsbLSNX7cz23jUp5Io1onkyoAJL+Mii5CDbv8f4Iky5N kYiecKZ1H7P0iDaV9JXkGtf/h9BDVWY= X-Google-Smtp-Source: ABdhPJynbVtU0R9605q6V3RD7AqlrxdaWfF8+Y26RMCElSPG7IX2Cmg+EwddYPFFWXoYTvH7RbO+TQ== X-Received: by 2002:a5d:5710:: with SMTP id a16mr10208267wrv.217.1597561154574; Sat, 15 Aug 2020 23:59:14 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id m1sm23979542wmc.28.2020.08.15.23.59.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 15 Aug 2020 23:59:14 -0700 (PDT) Message-Id: <068e097e22fa42b79e70b0346cc7460f1a3cbcff.1597561152.git.gitgitgadget@gmail.com> In-Reply-To: References: From: "Elijah Newren via GitGitGadget" Date: Sun, 16 Aug 2020 06:59:10 +0000 Subject: [PATCH 2/3] dir: make clear_directory() free all relevant memory Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Elijah Newren , Elijah Newren Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren The calling convention for the dir API is supposed to end with a call to clear_directory() to free up no longer needed memory. However, clear_directory() didn't free dir->entries or dir->ignored. I believe this was oversight, but a number of callers noticed memory leaks and started free'ing these, but often somewhat haphazardly (sometimes freeing the entries in the arrays, and sometimes only free'ing the arrays themselves). This suggests the callers weren't trying to make sure any possible memory used might be free'd, but just the memory they noticed their usecase definitely had allocated. This also caused the extra memory deallocations to be duplicated in many places. Fix this mess by moving all the duplicated free'ing logic into clear_directory(). Signed-off-by: Elijah Newren --- builtin/clean.c | 6 +----- builtin/stash.c | 3 --- dir.c | 12 ++++++++---- dir.h | 2 +- wt-status.c | 4 ---- 5 files changed, 10 insertions(+), 17 deletions(-) diff --git a/builtin/clean.c b/builtin/clean.c index 5a9c29a558..4ffe00dd7f 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -1021,11 +1021,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix) string_list_append(&del_list, rel); } - for (i = 0; i < dir.nr; i++) - free(dir.entries[i]); - - for (i = 0; i < dir.ignored_nr; i++) - free(dir.ignored[i]); + clear_directory(&dir); if (interactive && del_list.nr > 0) interactive_main_loop(); diff --git a/builtin/stash.c b/builtin/stash.c index 10d87630cd..da48533d49 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -875,11 +875,8 @@ static int get_untracked_files(const struct pathspec *ps, int include_untracked, strbuf_addstr(untracked_files, ent->name); /* NUL-terminate: will be fed to update-index -z */ strbuf_addch(untracked_files, '\0'); - free(ent); } - free(dir.entries); - free(dir.ignored); clear_directory(&dir); return found; } diff --git a/dir.c b/dir.c index 08df469bf7..b136c037d9 100644 --- a/dir.c +++ b/dir.c @@ -3012,10 +3012,7 @@ int remove_path(const char *name) return 0; } -/* - * Frees memory within dir which was allocated for exclude lists and - * the exclude_stack. Does not free dir itself. - */ +/* Frees memory within dir which was allocated. Does not free dir itself. */ void clear_directory(struct dir_struct *dir) { int i, j; @@ -3034,6 +3031,13 @@ void clear_directory(struct dir_struct *dir) free(group->pl); } + for (i = 0; i < dir->ignored_nr; i++) + free(dir->ignored[i]); + for (i = 0; i < dir->nr; i++) + free(dir->entries[i]); + free(dir->ignored); + free(dir->entries); + stk = dir->exclude_stack; while (stk) { struct exclude_stack *prev = stk->prev; diff --git a/dir.h b/dir.h index 5855c065a6..7d76d0644f 100644 --- a/dir.h +++ b/dir.h @@ -36,7 +36,7 @@ * * - Use `dir.entries[]`. * - * - Call `clear_directory()` when none of the contained elements are no longer in use. + * - Call `clear_directory()` when the contained elements are no longer in use. * */ diff --git a/wt-status.c b/wt-status.c index d75399085d..c00ea3e06a 100644 --- a/wt-status.c +++ b/wt-status.c @@ -724,18 +724,14 @@ static void wt_status_collect_untracked(struct wt_status *s) struct dir_entry *ent = dir.entries[i]; if (index_name_is_other(istate, ent->name, ent->len)) string_list_insert(&s->untracked, ent->name); - free(ent); } for (i = 0; i < dir.ignored_nr; i++) { struct dir_entry *ent = dir.ignored[i]; if (index_name_is_other(istate, ent->name, ent->len)) string_list_insert(&s->ignored, ent->name); - free(ent); } - free(dir.entries); - free(dir.ignored); clear_directory(&dir); if (advice_status_u_option) From patchwork Sun Aug 16 06:59:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Jean-No=C3=ABl_Avila_via_GitGitGadget?= X-Patchwork-Id: 11715981 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B05E414F6 for ; Sun, 16 Aug 2020 06:59:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 94156206F4 for ; Sun, 16 Aug 2020 06:59:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="s/3wU40j" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729772AbgHPG7T (ORCPT ); Sun, 16 Aug 2020 02:59:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45016 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729402AbgHPG7R (ORCPT ); Sun, 16 Aug 2020 02:59:17 -0400 Received: from mail-wm1-x344.google.com (mail-wm1-x344.google.com [IPv6:2a00:1450:4864:20::344]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D7CE6C061385 for ; Sat, 15 Aug 2020 23:59:16 -0700 (PDT) Received: by mail-wm1-x344.google.com with SMTP id c19so11119018wmd.1 for ; Sat, 15 Aug 2020 23:59:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=ZrJ7pai114Fzc5IoVpWnRKyIRPCcvWzEB4ynT5Y+AG4=; b=s/3wU40jCkro7Adyl3vW6iZP8kRvjOjtpVM/oN3dVd/CT6VBALTUvbtMnp3ALHhB+B ZFXO3w5abv9Ujc0aL8jVoTc/aPpu6mKQFKaxnx+uZXYhHru181Y7lJev7+WkE0uF4ccj zyb5O/Iv0UqGjVvvbI/1muMdneZ0zA5WhNDK8tdhZmQOZeyCY9J8V9vGHDvniiZUAFE6 ZTjjgBuotH8k0D0EPyPyePrPs5+ZpUtFPvOT1VebeYAQ8quMmfUpIRywLg9S3yCRHqZm ahwRplpLVdTnNJXr+igfv/KVUC7gENhY1APJCwEGDwiDQAQWsKYMp6ayQQcUw7AHzRwK Zvpw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=ZrJ7pai114Fzc5IoVpWnRKyIRPCcvWzEB4ynT5Y+AG4=; b=JPTxvNt8KBLC/ec9VUhY3lFdF5+M9x4ZCmHR+xcOhHAz8mqz4luekbv1Jfqo49yizz uJNwUNo09ByCHyE+X5ftMqmt4kK46u4CbEK/IrL/H6g0Ui0yAqixj477VcdOonoQ6GcN JXgVHdsLph508+udSotn8SH295EXWBELTz4mQ7Om4eyUbNy6mxS/sXBDGe43zvhcuBqI stfHajsPnNMT/TYlYzF7VZZKnd9NRd7tQiewcujXCrqVZ8iW5TQmzWDfbWE2Xa/w1Hl2 VfGtPFAjQmkLCqLb84fN1MbXPP9X/alwTZ7g5fHHJwOijVApr1YAf4pxlwuT07zDZA6Q 8RcQ== X-Gm-Message-State: AOAM530BWaKqtDy4CJB0CwAIuNzgp+G2RwcDShwZaceWRVntH1uKNExG KYT0D9DMI070P8H2GPqys3fMVp+TNRY= X-Google-Smtp-Source: ABdhPJzJcsiAl1Y52q7sqP5d/ljkzBHW+V2QTQY3TW7BYlRCYUhGRLNo+YXO72QLIpKYc5nkO2FWCg== X-Received: by 2002:a7b:c011:: with SMTP id c17mr9478983wmb.63.1597561155310; Sat, 15 Aug 2020 23:59:15 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id f6sm32134525wme.32.2020.08.15.23.59.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 15 Aug 2020 23:59:14 -0700 (PDT) Message-Id: In-Reply-To: References: From: "Elijah Newren via GitGitGadget" Date: Sun, 16 Aug 2020 06:59:11 +0000 Subject: [PATCH 3/3] dir: fix problematic API to avoid memory leaks Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Elijah Newren , Elijah Newren Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren Two commits ago, we noticed that parent_hashmap and recursive_hashmap were being leaked and fixed it by making clear_pattern_list() free those hashmaps. One commit ago, we noticed that clear_directory() was only taking responsibility for a subset of fields within dir_struct, despite the fact that entries[] and ignored[] we allocated internally to dir.c, resulting in many callers either leaking or haphazardly trying to free these arrays and their contents. Digging further, I found that despite the pretty clear documentation near the top of dir.h that folks were supposed to call clear_directory() when the user no longer needed the dir_struct, there were four callers that didn't bother doing that at all. However, two of them clearly thought about leaks since they had an UNLEAK(dir) directive, which to me suggests that the method to free the data was too unclear. I suspect the non-obviousness of the API and its holes led folks to avoid it, which then snowballed into further problems with the entries[], ignored[], parent_hashmap, and recursive_hashmap problems. Rename clear_directory() to dir_free() to be more in line with other data structures in git, and introduce a dir_init() to handle the suggested memsetting of dir_struct to all zeroes. I hope that a name like "dir_free()" is more clear, and that the presence of dir_init() will provide a hint to those looking at the code that there may be a corresponding dir_free() that they need to call. Signed-off-by: Elijah Newren --- builtin/add.c | 4 ++-- builtin/check-ignore.c | 4 ++-- builtin/clean.c | 8 ++++---- builtin/grep.c | 3 ++- builtin/ls-files.c | 4 ++-- builtin/stash.c | 4 ++-- dir.c | 7 ++++++- dir.h | 19 ++++++++++--------- merge.c | 3 ++- wt-status.c | 4 ++-- 10 files changed, 34 insertions(+), 26 deletions(-) diff --git a/builtin/add.c b/builtin/add.c index ab39a60a0d..46c9a0f552 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -534,11 +534,11 @@ int cmd_add(int argc, const char **argv, const char *prefix) die_in_unpopulated_submodule(&the_index, prefix); die_path_inside_submodule(&the_index, &pathspec); + dir_init(&dir); if (add_new_files) { int baselen; /* Set up the default git porcelain excludes */ - memset(&dir, 0, sizeof(dir)); if (!ignored_too) { dir.flags |= DIR_COLLECT_IGNORED; setup_standard_excludes(&dir); @@ -611,7 +611,7 @@ int cmd_add(int argc, const char **argv, const char *prefix) COMMIT_LOCK | SKIP_IF_UNCHANGED)) die(_("Unable to write new index file")); + dir_free(&dir); UNLEAK(pathspec); - UNLEAK(dir); return exit_status; } diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c index ea5d0ae3a6..29b464a1fa 100644 --- a/builtin/check-ignore.c +++ b/builtin/check-ignore.c @@ -180,7 +180,7 @@ int cmd_check_ignore(int argc, const char **argv, const char *prefix) if (!no_index && read_cache() < 0) die(_("index file corrupt")); - memset(&dir, 0, sizeof(dir)); + dir_init(&dir); setup_standard_excludes(&dir); if (stdin_paths) { @@ -190,7 +190,7 @@ int cmd_check_ignore(int argc, const char **argv, const char *prefix) maybe_flush_or_die(stdout, "ignore to stdout"); } - clear_directory(&dir); + dir_free(&dir); return !num_ignored; } diff --git a/builtin/clean.c b/builtin/clean.c index 4ffe00dd7f..a4cf58af74 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -667,7 +667,7 @@ static int filter_by_patterns_cmd(void) if (!confirm.len) break; - memset(&dir, 0, sizeof(dir)); + dir_init(&dir); pl = add_pattern_list(&dir, EXC_CMDL, "manual exclude"); ignore_list = strbuf_split_max(&confirm, ' ', 0); @@ -698,7 +698,7 @@ static int filter_by_patterns_cmd(void) } strbuf_list_free(ignore_list); - clear_directory(&dir); + dir_free(&dir); } strbuf_release(&confirm); @@ -923,7 +923,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, options, builtin_clean_usage, 0); - memset(&dir, 0, sizeof(dir)); + dir_init(&dir); if (!interactive && !dry_run && !force) { if (config_set) die(_("clean.requireForce set to true and neither -i, -n, nor -f given; " @@ -1021,7 +1021,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix) string_list_append(&del_list, rel); } - clear_directory(&dir); + dir_free(&dir); if (interactive && del_list.nr > 0) interactive_main_loop(); diff --git a/builtin/grep.c b/builtin/grep.c index cee9db3477..fef2cc05ca 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -693,7 +693,7 @@ static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec, struct dir_struct dir; int i, hit = 0; - memset(&dir, 0, sizeof(dir)); + dir_init(&dir); if (!use_index) dir.flags |= DIR_NO_GITLINKS; if (exc_std) @@ -705,6 +705,7 @@ static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec, if (hit && opt->status_only) break; } + dir_free(&dir); return hit; } diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 30a4c10334..740feff53e 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -584,7 +584,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) if (argc == 2 && !strcmp(argv[1], "-h")) usage_with_options(ls_files_usage, builtin_ls_files_options); - memset(&dir, 0, sizeof(dir)); + dir_init(&dir); prefix = cmd_prefix; if (prefix) prefix_len = strlen(prefix); @@ -688,6 +688,6 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) return bad ? 1 : 0; } - UNLEAK(dir); + dir_free(&dir); return 0; } diff --git a/builtin/stash.c b/builtin/stash.c index da48533d49..85b646b7ad 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -864,7 +864,7 @@ static int get_untracked_files(const struct pathspec *ps, int include_untracked, int found = 0; struct dir_struct dir; - memset(&dir, 0, sizeof(dir)); + dir_init(&dir); if (include_untracked != INCLUDE_ALL_FILES) setup_standard_excludes(&dir); @@ -877,7 +877,7 @@ static int get_untracked_files(const struct pathspec *ps, int include_untracked, strbuf_addch(untracked_files, '\0'); } - clear_directory(&dir); + dir_free(&dir); return found; } diff --git a/dir.c b/dir.c index b136c037d9..e3c8e7ffd6 100644 --- a/dir.c +++ b/dir.c @@ -54,6 +54,11 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir, static int resolve_dtype(int dtype, struct index_state *istate, const char *path, int len); +void dir_init(struct dir_struct *dir) +{ + memset(dir, 0, sizeof(*dir)); +} + int count_slashes(const char *s) { int cnt = 0; @@ -3013,7 +3018,7 @@ int remove_path(const char *name) } /* Frees memory within dir which was allocated. Does not free dir itself. */ -void clear_directory(struct dir_struct *dir) +void dir_free(struct dir_struct *dir) { int i, j; struct exclude_list_group *group; diff --git a/dir.h b/dir.h index 7d76d0644f..7c55c1a460 100644 --- a/dir.h +++ b/dir.h @@ -19,22 +19,21 @@ * CE_SKIP_WORKTREE marked. If you want to exclude files, make sure you have * loaded the index first. * - * - Prepare `struct dir_struct dir` and clear it with `memset(&dir, 0, - * sizeof(dir))`. + * - Prepare `struct dir_struct dir` using `dir_init()` function. * * - To add single exclude pattern, call `add_pattern_list()` and then * `add_pattern()`. * * - To add patterns from a file (e.g. `.git/info/exclude`), call - * `add_patterns_from_file()` , and/or set `dir.exclude_per_dir`. A - * short-hand function `setup_standard_excludes()` can be used to set - * up the standard set of exclude settings. + * `add_patterns_from_file()` , and/or set `dir.exclude_per_dir`. * - * - Set options described in the Data Structure section above. + * - A short-hand function `setup_standard_excludes()` can be used to set + * up the standard set of exclude settings, instead of manually calling + * the add_pattern*() family of functions. * - * - Call `read_directory()`. + * - Call `fill_directory()`. * - * - Use `dir.entries[]`. + * - Use `dir.entries[]` and `dir.ignored[]`. * * - Call `clear_directory()` when the contained elements are no longer in use. * @@ -362,6 +361,8 @@ int match_pathspec(const struct index_state *istate, int report_path_error(const char *ps_matched, const struct pathspec *pathspec); int within_depth(const char *name, int namelen, int depth, int max_depth); +void dir_init(struct dir_struct *dir); + int fill_directory(struct dir_struct *dir, struct index_state *istate, const struct pathspec *pathspec); @@ -428,7 +429,7 @@ void parse_path_pattern(const char **string, int *patternlen, unsigned *flags, i void add_pattern(const char *string, const char *base, int baselen, struct pattern_list *pl, int srcpos); void clear_pattern_list(struct pattern_list *pl); -void clear_directory(struct dir_struct *dir); +void dir_free(struct dir_struct *dir); int repo_file_exists(struct repository *repo, const char *path); int file_exists(const char *); diff --git a/merge.c b/merge.c index 753e461659..ee149b87ea 100644 --- a/merge.c +++ b/merge.c @@ -80,8 +80,8 @@ int checkout_fast_forward(struct repository *r, } memset(&opts, 0, sizeof(opts)); + dir_init(&dir); if (overwrite_ignore) { - memset(&dir, 0, sizeof(dir)); dir.flags |= DIR_SHOW_IGNORED; setup_standard_excludes(&dir); opts.dir = &dir; @@ -102,6 +102,7 @@ int checkout_fast_forward(struct repository *r, clear_unpack_trees_porcelain(&opts); return -1; } + dir_free(&dir); clear_unpack_trees_porcelain(&opts); if (write_locked_index(r->index, &lock_file, COMMIT_LOCK)) diff --git a/wt-status.c b/wt-status.c index c00ea3e06a..5624a8ff7f 100644 --- a/wt-status.c +++ b/wt-status.c @@ -703,7 +703,7 @@ static void wt_status_collect_untracked(struct wt_status *s) if (!s->show_untracked_files) return; - memset(&dir, 0, sizeof(dir)); + dir_init(&dir); if (s->show_untracked_files != SHOW_ALL_UNTRACKED_FILES) dir.flags |= DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES; @@ -732,7 +732,7 @@ static void wt_status_collect_untracked(struct wt_status *s) string_list_insert(&s->ignored, ent->name); } - clear_directory(&dir); + dir_free(&dir); if (advice_status_u_option) s->untracked_in_ms = (getnanotime() - t_begin) / 1000000;