Bug Summary

File:dmake/unix/dcache.c
Location:line 158, column 12
Description:Access to field 'name' results in a dereference of a null pointer (loaded from variable 'ep')

Annotated Source Code

1/*
2--
3-- SYNOPSIS
4-- Directory cache management routines.
5--
6-- DESCRIPTION
7-- This is the code that maintains a directory cache for each directory
8-- that dmake visits. The entire directory is thus only read once and
9-- the need for performing costly 'stat' calls when performing target
10-- inference is much reduced. The improvement in performance should be
11-- significant for NFS or remote mounted file systems.
12--
13-- AUTHOR
14-- Dennis Vadura, dvadura@dmake.wticorp.com
15--
16-- WWW
17-- http://dmake.wticorp.com/
18--
19-- COPYRIGHT
20-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
21--
22-- This program is NOT free software; you can redistribute it and/or
23-- modify it under the terms of the Software License Agreement Provided
24-- in the file <distribution-root>/readme/license.txt.
25--
26-- LOG
27-- Use cvs log to obtain detailed change logs.
28*/
29
30/* For Borland 5.00 compile, for some reason they seem to insist on pulling
31 * in the winnt.h if __WIN32__ is defined and you include <dirent.h>. This
32 * is, in my opinion, a BUG! on Borland's part.
33 */
34#if defined(__BORLANDC__) && defined(__WIN32__)
35#undef __WIN32__
36#endif
37
38#ifdef __APPLE__
39#include <sys/types.h>
40#endif
41#include <dirent.h>
42#include "extern.h"
43#include "sysintf.h"
44
45
46typedef struct ent {
47 char *name;
48 uint32 hkey;
49 time_t mtime;
50 int isdir;
51 struct ent *next;
52} Entry, *EntryPtr;
53
54
55typedef struct mydir {
56 char *path;
57 uint32 hkey;
58 EntryPtr entries;
59 struct mydir *next;
60} DirEntry, *DirEntryPtr;
61
62static DirEntryPtr dtab[HASH_TABLE_SIZE200];
63
64
65/* Stat a path using the directory cache.
66 *
67 * We build a cannonical representation of the path using either an absolute
68 * path name if that is what 'path' is or the relative path name constructed
69 * from 'path' and the present value of Pwd.
70 *
71 * The present value of Pwd then gives a directory path that we search for
72 * in our cache using a hash lookup. If the directory component is located
73 * then we search the basename component of the path and return the result of
74 * the search: 0L if the component is not in the cache and it's time stamp
75 * otherwise.
76 *
77 * If the directory is not in our cache we insert it into the cache by
78 * openning the directory and reading all of the files within. Once read
79 * then we return the result of the above search.
80 *
81 * Optionally, if force is TRUE, and we did NOT read the directory to provide
82 * the result then stat the file anyway and update the internal cache.
83 */
84
85PUBLIC time_t
86CacheStat(path, force)
87char *path;
88int force;
89{
90 struct stat stbuf;
91 DirEntryPtr dp;
92 EntryPtr ep;
93 uint32 hkey;
94 uint16 hv;
95 char *fpath;
96 char *spath;
97 char *comp;
98 char *dir;
99 char *udir; /* Hold the unchanged (DcacheRespCase) directory. */
100 int loaded=FALSE0;
101
102 if (If_root_path(path))
1
Taking false branch
103 spath = path;
104 else
105 spath = Build_path(Pwd,path);
106
107 fpath = DmStrDup(spath);
108
109 comp = Basename(fpath); /* Use before the Filedir() call. */
110 dir = Filedir(fpath);
111
112 /* do caching and comparing lower case if told so. */
113 if( !STOBOOL(DcacheRespCase)(DcacheRespCase && ((*DcacheRespCase | 0x20) == 'y')) ) {
2
Taking true branch
114 udir = DmStrDup(dir);
115 strlwr(comp);
116 strlwr(dir);
117 } else
118 udir = dir;
119
120 hv = Hash(dir,&hkey);
121
122 for(dp=dtab[hv]; dp; dp=dp->next)
3
Loop condition is false. Execution continues on line 126
123 if (hkey == dp->hkey && strcmp(dp->path,dir) == 0)
124 break;
125
126 if (!dp) {
4
Taking true branch
127 /* Not cached yet, doing it now. */
128 DIR *dirp;
129 struct dirent *direntp;
130
131 if( Verbose & V_DIR_CACHE0x04 )
5
Taking false branch
132 printf( "%s: Caching directory [%s]\n", Pname, dir );
133
134 /* Load the directory, we have the right hash position already */
135 loaded = TRUE1;
136
137 TALLOC(dp,1,DirEntry)if ((dp = (DirEntry*) calloc((unsigned int)(1), (size_t)sizeof
(DirEntry))) == (DirEntry*)0) {No_ram();}
;
138 dp->next = dtab[hv];
139 dtab[hv] = dp;
140 dp->path = DmStrDup(dir);
141 dp->hkey = hkey;
142
143 /* We use the unchanged (not potentially lowercased because of
144 * DcacheRespCase) directory as this would fail on a case sensitive
145 * file system.
146 * Note: Using case insensitive directory caching on case sensitive
147 * file systems is a *BAD* idea. If in doubt use case sensitive
148 * directory caching even on case insensitive file systems as the
149 * worst case in this szenario is that /foo/bar/ and /foo/BAR/ are
150 * cached separately (with the same content) even though they are
151 * the same directory. This would only happen if different targets
152 * using different upper/lower case spellings for the same directory
153 * and is *never* a good idea. */
154 if (Set_dir(udir) == 0) {
6
Taking true branch
155 if((dirp=opendir(".")) != NIL(DIR)((DIR*)((void*)0))) {
7
Taking true branch
156 while((direntp=readdir(dirp)) != NULL((void*)0)) {
8
Loop condition is true. Entering loop body
157 TALLOC(ep,1,Entry)if ((ep = (Entry*) calloc((unsigned int)(1), (size_t)sizeof(Entry
))) == (Entry*)0) {No_ram();}
;
9
Within the expansion of the macro 'TALLOC':
a
Value assigned to 'ep'
b
Assuming pointer value is null
158 ep->name = DmStrDup(direntp->d_name); /* basename only */
10
Access to field 'name' results in a dereference of a null pointer (loaded from variable 'ep')
159 if( !STOBOOL(DcacheRespCase)(DcacheRespCase && ((*DcacheRespCase | 0x20) == 'y')) )
160 strlwr(ep->name);
161
162 Hash(ep->name, &ep->hkey); /* This sets ep->hkey. */
163
164 ep->next = dp->entries;
165 dp->entries = ep;
166 DMSTATstat(direntp->d_name,&stbuf);
167 ep->isdir = (stbuf.st_mode & S_IFDIR0040000);
168 ep->mtime = stbuf.st_mtimest_mtim.tv_sec;
169 }
170 closedir(dirp);
171 }
172 Set_dir(Pwd);
173 }
174 }
175
176 Hash(comp, &hkey); /* Calculate hkey. */
177
178 /* search in dp->entries for comp. */
179 if (dp) {
180 for(ep=dp->entries; ep; ep=ep->next)
181 if(hkey == ep->hkey && strcmp(ep->name,comp) == 0)
182 break;
183 }
184 else
185 ep = NULL((void*)0);
186
187 if( force && !loaded) {
188 if (strlen(comp) > NameMax || DMSTATstat(spath,&stbuf) != 0) {
189 /* Either file to long or the stat failed. */
190 if (strlen(comp) > NameMax)
191 Warning( "File [%s] longer than value of NAMEMAX [%d].\n\
192 Assume unix time 0.\n", comp, NameMax );
193 if(ep)
194 ep->mtime = 0L;
195 }
196 else {
197 if (!ep) {
198 TALLOC(ep,1,Entry)if ((ep = (Entry*) calloc((unsigned int)(1), (size_t)sizeof(Entry
))) == (Entry*)0) {No_ram();}
;
199 ep->name = DmStrDup(comp);
200 if( !STOBOOL(DcacheRespCase)(DcacheRespCase && ((*DcacheRespCase | 0x20) == 'y')) )
201 strlwr(ep->name);
202 Hash(ep->name, &ep->hkey);
203 ep->next = dp->entries;
204 ep->isdir = (stbuf.st_mode & S_IFDIR0040000);
205 dp->entries = ep;
206 }
207
208 ep->mtime = stbuf.st_mtimest_mtim.tv_sec;
209 }
210
211 if( Verbose & V_DIR_CACHE0x04 )
212 printf("%s: Updating dir cache entry for [%s], new time is %ld\n",
213 Pname, spath, ep ? ep->mtime : 0L);
214 }
215
216 if( udir != dir )
217 FREE(udir)free((char*)(udir)); /* Keep this before the free of fpath. */
218
219 FREE(fpath)free((char*)(fpath));
220 return(!ep ? (time_t)0L : ((STOBOOL(Augmake)(Augmake && ((*Augmake | 0x20) == 'y')) && ep->isdir)?0L:ep->mtime));
221}