Bug Summary

File:dmake/path.c
Location:line 135, column 4
Description:Dereference of null pointer (loaded from variable 'path')

Annotated Source Code

1/* RCS $Id: path.c,v 1.6 2008-03-05 18:29:34 kz Exp $
2--
3-- SYNOPSIS
4-- Pathname manipulation code
5--
6-- DESCRIPTION
7-- Pathname routines to handle building and pulling appart
8-- pathnames.
9--
10-- AUTHOR
11-- Dennis Vadura, dvadura@dmake.wticorp.com
12--
13-- WWW
14-- http://dmake.wticorp.com/
15--
16-- COPYRIGHT
17-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
18--
19-- This program is NOT free software; you can redistribute it and/or
20-- modify it under the terms of the Software License Agreement Provided
21-- in the file <distribution-root>/readme/license.txt.
22--
23-- LOG
24-- Use cvs log to obtain detailed change logs.
25*/
26
27#include "extern.h"
28#if __CYGWIN__
29#include <sys/cygwin.h>
30#include <errno.h>
31#endif
32
33
34/*
35** Return the suffix portion of a filename, assumed to begin with a `.'.
36*/
37PUBLIC char *
38Get_suffix(name)
39char *name;
40{
41 char *suff;
42
43 if(name == NIL(char)((char*)((void*)0)) || (suff = strrchr(name, '.')) == NIL(char)((char*)((void*)0)))
44 suff = ".NULL";
45
46 return (suff);
47}
48
49
50PUBLIC char *
51Basename(path)/*
52================
53 Return pointer to the basename part of path. path itself remains
54 unchanged. */
55char *path;
56{
57 char *p;
58 char *q;
59
60 if( path && *(q = path) ) {
61 for(; *(p=DmStrPbrk(q, DirBrkStr)) != '\0'; q = p+1 );
62 if( !*q ) {
63 for( p=q-1; p != path; --p )
64 if( strchr( DirBrkStr, *p ) == NIL(char)((char*)((void*)0)) ) return( p+1 );
65 return( strchr(DirBrkStr, *p)?path:(p+1) );
66 }
67 path = q;
68 }
69 return( path );
70}
71
72
73PUBLIC char *
74Filedir(path)
75char *path;
76{
77 char *p;
78 char *q;
79
80 if( path && *(q = path) ) {
81 for(; *(p=DmStrPbrk(q,DirBrkStr)) != '\0'; q=p+1 );
82
83 if (q == path) return("");
84
85 for(p=q-1; p!=path; --p)
86 if( strchr(DirBrkStr,*p) == NIL(char)((char*)((void*)0)) )
87 break;
88
89 p[1] = '\0';
90 }
91
92 return(path);
93}
94
95
96
97PUBLIC char *
98Build_path(dir, name)/*
99=======================
100 Return a path that is created by concatenating dir and name. A directory
101 separater is added between them if needed. If dir is empty name is stripped
102 of leading slashes (if there) and returned.
103
104 The returned path is also cleaned from unneeded './' and 'foo/../'
105 elements and also multiple consequtive '/' are removed.
106
107 Note, the returned path is built in a static buffer, if it is to be used
108 later strdup should be used on the result returned by Build_path to create
109 a copy. */
110
111char *dir;
112char *name;
113{
114 static char *path = NIL(char)((char*)((void*)0));
1
Variable 'path' initialized to a null pointer value
115 static unsigned buflen = 0;
116 int plen = 0;
117 int dlen = 0;
118 int len;
119
120 DB_ENTER( "Build_path" );
121
122 if( dir != NIL(char)((char*)((void*)0)) ) dlen = strlen( dir );
2
Taking false branch
123 if( name != NIL(char)((char*)((void*)0)) ) plen = strlen( name );
3
Taking true branch
124 len = plen+dlen+1+1; /* Reserve space for extra path separator. */
125
126 if( len > buflen ) {
4
Taking false branch
127 buflen = (len+16) & ~0xf; /* buf is always multiple of 16 */
128
129 if( path == NIL(char)((char*)((void*)0)) )
130 path = MALLOC( buflen, char )(char*) malloc((unsigned int)(buflen)*(size_t)sizeof(char));
131 else
132 path = realloc( path, (unsigned) (buflen*sizeof(char)) );
133 }
134
135 *path = '\0';
5
Dereference of null pointer (loaded from variable 'path')
136
137 if( dlen ) {
138 strcpy( path, dir );
139 if( *path && strchr(DirBrkStr, dir[dlen-1]) == NIL(char)((char*)((void*)0)) )
140 strcat( path, DirSepStr );
141 }
142
143 if ( plen ) {
144 while ( *name && strchr(DirBrkStr,*name) != 0 ) name++;
145 strcat( path, name );
146 }
147
148 DB_PRINT( "path", ("dir: %s name: %s", dir, name ));
149 DB_PRINT( "path", ("joined to: %s", path ));
150
151 Clean_path( path );
152 DB_PRINT( "path", ("cleaned to: %s", path ));
153
154 DB_RETURN( path )return (path);
155}
156
157
158void
159Clean_path(path)/*
160==================
161 Clean the path from irregular directory separators (if more than one are
162 allowed), remove unneeded './' and 'foo/../' elements and also multiple
163 consequtive '/'.
164
165 The resulting string is shorter than the original, therefore this function
166 works on the original string. */
167
168char *path;
169{
170 register char *p;
171 register char *q;
172 char *tpath;
173 int hasdriveletter = 0;
174 int delentry;
175 size_t len;
176
177 DB_ENTER( "Clean_path" );
178
179 /* Skip the root part. */
180 tpath=path;
181
182#ifdef HAVE_DRIVE_LETTERS
183
184 /* Change all occurrences from DirBrkStr to *DirSepStr. This assumes
185 * that when HAVE_DRIVE_LETTERS is set the directory separator is
186 * either '\' or '/'. */
187 if (*DirSepStr == '/')
188 for( q = tpath; (q = strchr(q, '\\')) != NIL(char)((char*)((void*)0)); )
189 *q = *DirSepStr;
190 else
191 for( q = tpath; (q = strchr(q, '/')) != NIL(char)((char*)((void*)0)); )
192 *q = *DirSepStr;
193
194 /* The following dosn't trigger often because normalize_path() uses
195 * a cygwin function and bypasses Clean_path() if it encounters a path
196 * with a drive letter. */
197 if( *tpath && tpath[1] == ':' && isalpha(*tpath)((*__ctype_b_loc ())[(int) ((*tpath))] & (unsigned short int
) _ISalpha)
) {
198 hasdriveletter = 1;
199 tpath+=2;
200 if( *tpath != *DirSepStr )
201 Warning("Malformed DOS path %s", path);
202 }
203
204#endif
205
206 /* Collapse > 2 ( > 1 if its an absolute DOS path ) into one slash.
207 * Keep // as it is reserved in posix. */
208 q = tpath;
209 for( ; *q == *DirSepStr ; ++q )
210 ;
211 if( q - tpath > 2 - hasdriveletter ) {
212 strcpy(tpath+1, q);
213 }
214
215 /* Set tpath after leading slash / drive letter. */
216 for( ; *tpath == *DirSepStr ; ++tpath )
217 ;
218 q = tpath;
219
220 while( *q ) {
221 char *t;
222
223 /* p is NULL or greater than q. */
224 p=strchr(q, *DirSepStr);
225 if( !p ) break;
226
227 /* Remove multiple consequtive DirSepStr. */
228 if( p[1] == *DirSepStr ) {
229 t = p++; /* t points to first, p to second DirStrSep. */
230 /* Move p after the second (or possible more) DirSepStr. */
231 do {
232 p++;
233 }
234 while( *p == *DirSepStr);
235 len = strlen(p)+1;
236 memmove(t+1,p,len);
237 continue;
238 }
239
240 /* Remove './'. If OOODMAKEMODE is set do this only if it is not at
241 * the start of the path. */
242 if ( p-q == 1 && *q == '.' && (q != path || !STOBOOL(OOoDmMode)(OOoDmMode && ((*OOoDmMode | 0x20) == 'y'))) ) {
243 len = strlen(p+1)+1;
244 memmove(q,p+1,len);
245 q = tpath;
246 continue;
247 }
248
249 /* If two '/' are in path check/remove 'foo/../' elements. */
250 t=strchr(p+1, *DirSepStr);
251 if( !t ) break;
252
253 /* Collaps this only if foo is neither '.' nor '..'. */
254 switch( p-q ) {
255 case 2:
256 delentry = !((q[0] == '.') && (q[1] == '.'));
257 break;
258 case 1:
259 delentry = !(q[0] == '.');
260 break;
261 default:
262 delentry = TRUE1;
263 break;
264 }
265
266 if ( delentry
267 && (t-p-1 == 2 && strncmp(p+1,"..",2) == 0) ) {
268 /* Skip one (or possible more) DirSepStr. */
269 do {
270 t++;
271 }
272 while( *t == *DirSepStr);
273 /* q points to first letter of the current directory/file. */
274 len = strlen(t)+1;
275 memmove(q,t,len);
276 q = tpath;
277 }
278 else
279 q = p+1;
280 }
281
282 DB_PRINT( "path", ("Cleaned path: %s", path ));
283
284 DB_VOID_RETURNreturn;
285}
286
287
288char *
289normalize_path(path)/*
290=======================
291 Normalize the given path unless it contains a $ indicating a dynamic
292 prerequisite.
293 Special case: For absolute DOSish paths under cygwin a cygwin API
294 function is used to normalize the path optherwise Clean_path() is used.
295
296 Note, the returned path is built in a static buffer, if it is to be used
297 later a copy should be created. */
298
299char *path;
300{
301 static char *cpath = NIL(char)((char*)((void*)0));
302
303 DB_ENTER( "normalize_path" );
304
305 if ( !cpath && ( (cpath = MALLOC( PATH_MAX, char)(char*) malloc((unsigned int)(4096)*(size_t)sizeof(char))) == NIL(char)((char*)((void*)0)) ) )
306 No_ram();
307
308 /* If there is a $ in the path this can either mean a '$' character in
309 * a target definition or a dynamic macro expression in a prerequisite
310 * list. As dynamic macro expression must not be normalized and is
311 * indistinguishable from a literal $ characters at this point we skip
312 * the normalization if a $ is found. */
313 if( strchr(path, '$') ) {
314 DB_RETURN( path )return (path);
315 }
316
317#if __CYGWIN__
318 /* Use cygwin function to convert a DOS path to a POSIX path. */
319 if( *path && path[1] == ':' && isalpha(*path)((*__ctype_b_loc ())[(int) ((*path))] & (unsigned short int
) _ISalpha)
) {
320 int err = cygwin_conv_to_posix_path(path, cpath);
321 if (err)
322 Fatal( "error converting \"%s\" - %s\n",
323 path, strerror (errno));
324 if( path[2] != '/' && path[2] != '\\' )
325 Warning("Malformed DOS path %s converted to %s", path, cpath);
326 }
327 else
328#endif
329 {
330 strcpy( cpath, path );
331 Clean_path( cpath );
332 }
333
334 DB_PRINT( "path", ("normalized: %s", cpath ));
335
336 DB_RETURN( cpath )return (cpath);
337}