summaryrefslogtreecommitdiff
path: root/usr.bin/make/dir.c
diff options
context:
space:
mode:
authorrillig <rillig@NetBSD.org>2020-11-29 16:37:10 +0000
committerrillig <rillig@NetBSD.org>2020-11-29 16:37:10 +0000
commit966d5ca1a8f1e7b1bdbec76eb7594ac2e7233124 (patch)
tree016d821cf2c475ffacf0981dd467f4c2bcb403b5 /usr.bin/make/dir.c
parent5f790b1a6047237bf86ea45a186f9787a93a93b3 (diff)
make(1): fix the reference count of dotLast going negative
The memory management for dotLast is quite simple. It is initialized exactly once main_Init > Init_Objdir > Dir_InitDir and freed exactly once in main_CleanUp > Dir_End. Previously, dotLast was not freed at all. The first call to CachedDir_Unref decremented the refCount to 0 but didn't free anything. Next, CachedDir_Destroy was called, which decremented the reference count to -1, therefore skipping the actual freeing. This was probably an implementation mistake. Since Dir_End is called at the very end of main_CleanUp, no code accesses dotLast after it has been freed.
Diffstat (limited to 'usr.bin/make/dir.c')
-rw-r--r--usr.bin/make/dir.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/usr.bin/make/dir.c b/usr.bin/make/dir.c
index c2c13342901..8135005580a 100644
--- a/usr.bin/make/dir.c
+++ b/usr.bin/make/dir.c
@@ -1,4 +1,4 @@
-/* $NetBSD: dir.c,v 1.239 2020/11/29 16:04:34 rillig Exp $ */
+/* $NetBSD: dir.c,v 1.240 2020/11/29 16:37:10 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -136,7 +136,7 @@
#include "job.h"
/* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */
-MAKE_RCSID("$NetBSD: dir.c,v 1.239 2020/11/29 16:04:34 rillig Exp $");
+MAKE_RCSID("$NetBSD: dir.c,v 1.240 2020/11/29 16:37:10 rillig Exp $");
#define DIR_DEBUG0(text) DEBUG0(DIR, text)
#define DIR_DEBUG1(fmt, arg1) DEBUG1(DIR, fmt, arg1)
@@ -271,8 +271,8 @@ static int bigmisses; /* Sought by itself */
static CachedDir *dot; /* contents of current directory */
static CachedDir *cur; /* contents of current directory, if not dot */
-static CachedDir *dotLast; /* a fake path entry indicating we need to
- * look for . last */
+/* A fake path entry indicating we need to look for '.' last. */
+static CachedDir *dotLast = NULL;
/* Results of doing a last-resort stat in Dir_FindFile -- if we have to go to
* the system to find the file, we might as well have its mtime on record.
@@ -341,6 +341,20 @@ CachedDir_Destroy(CachedDir *dir)
CachedDir_Free0(dir);
}
+/* Update the value of the CachedDir variable, updating the reference counts. */
+static void
+CachedDir_Assign(CachedDir **var, CachedDir *dir)
+{
+ CachedDir *prev;
+
+ prev = *var;
+ *var = dir;
+ if (dir != NULL)
+ CachedDir_Ref(dir);
+ if (prev != NULL)
+ CachedDir_Destroy(prev);
+}
+
static void
OpenDirs_Init(OpenDirs *odirs)
{
@@ -466,7 +480,7 @@ Dir_InitDir(const char *cdname)
{
Dir_InitCur(cdname);
- dotLast = CachedDir_Ref(CachedDir_New(".DOTLAST"));
+ CachedDir_Assign(&dotLast, CachedDir_New(".DOTLAST"));
}
/*
@@ -537,8 +551,7 @@ Dir_End(void)
CachedDir_Unref(cur); /* XXX: why unref twice? */
CachedDir_Destroy(cur);
}
- CachedDir_Unref(dotLast); /* XXX: why unref twice? */
- CachedDir_Destroy(dotLast);
+ CachedDir_Assign(&dotLast, NULL);
CachedDir_Unref(dot); /* XXX: why unref twice? */
CachedDir_Destroy(dot);
SearchPath_Clear(&dirSearchPath);