Module Name: src Committed By: rillig Date: Sun Nov 29 16:37:10 UTC 2020
Modified Files: src/usr.bin/make: dir.c Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.239 -r1.240 src/usr.bin/make/dir.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/make/dir.c diff -u src/usr.bin/make/dir.c:1.239 src/usr.bin/make/dir.c:1.240 --- src/usr.bin/make/dir.c:1.239 Sun Nov 29 16:04:34 2020 +++ src/usr.bin/make/dir.c Sun Nov 29 16:37:10 2020 @@ -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 itse 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);