diff options
| author | rillig <rillig@NetBSD.org> | 2020-11-29 16:37:10 +0000 |
|---|---|---|
| committer | rillig <rillig@NetBSD.org> | 2020-11-29 16:37:10 +0000 |
| commit | 966d5ca1a8f1e7b1bdbec76eb7594ac2e7233124 (patch) | |
| tree | 016d821cf2c475ffacf0981dd467f4c2bcb403b5 /usr.bin/make | |
| parent | 5f790b1a6047237bf86ea45a186f9787a93a93b3 (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')
| -rw-r--r-- | usr.bin/make/dir.c | 27 |
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); |
