summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2015-10-14 08:25:09 +1100
committerDamien Miller <djm@mindrot.org>2015-10-14 08:25:09 +1100
commit7365fe5b4859de2305e40ea132da3823830fa710 (patch)
tree1b01d108b2c88875126b6fb81246ec00dc8c265e
parente679c09cd1951f963793aa3d9748d1c3fdcf808f (diff)
upstream commit
revision 1.14 date: 2011/07/24 21:03:00; author: miod; state: Exp; lines: +35 -13; Recent Single Unix will malloc memory if the second argument of realpath() is NULL, and third-party software is starting to rely upon this. Adapted from FreeBSD via Jona Joachim (jaj ; hcl-club , .lu), with minor tweaks from nicm@ and yours truly.
-rw-r--r--openbsd-compat/realpath.c48
1 files changed, 35 insertions, 13 deletions
diff --git a/openbsd-compat/realpath.c b/openbsd-compat/realpath.c
index ba4cea938..6646330ca 100644
--- a/openbsd-compat/realpath.c
+++ b/openbsd-compat/realpath.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: realpath.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ 1/* $OpenBSD: realpath.c,v 1.14 2011/07/24 21:03:00 miod Exp $ */
2/* 2/*
3 * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru> 3 * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
4 * 4 *
@@ -51,16 +51,30 @@
51 * in which case the path which caused trouble is left in (resolved). 51 * in which case the path which caused trouble is left in (resolved).
52 */ 52 */
53char * 53char *
54realpath(const char *path, char resolved[PATH_MAX]) 54realpath(const char *path, char *resolved)
55{ 55{
56 struct stat sb; 56 struct stat sb;
57 char *p, *q, *s; 57 char *p, *q, *s;
58 size_t left_len, resolved_len; 58 size_t left_len, resolved_len;
59 unsigned symlinks; 59 unsigned symlinks;
60 int serrno, slen; 60 int serrno, slen, mem_allocated;
61 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; 61 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
62 62
63 if (path[0] == '\0') {
64 errno = ENOENT;
65 return (NULL);
66 }
67
63 serrno = errno; 68 serrno = errno;
69
70 if (resolved == NULL) {
71 resolved = malloc(PATH_MAX);
72 if (resolved == NULL)
73 return (NULL);
74 mem_allocated = 1;
75 } else
76 mem_allocated = 0;
77
64 symlinks = 0; 78 symlinks = 0;
65 if (path[0] == '/') { 79 if (path[0] == '/') {
66 resolved[0] = '/'; 80 resolved[0] = '/';
@@ -71,7 +85,10 @@ realpath(const char *path, char resolved[PATH_MAX])
71 left_len = strlcpy(left, path + 1, sizeof(left)); 85 left_len = strlcpy(left, path + 1, sizeof(left));
72 } else { 86 } else {
73 if (getcwd(resolved, PATH_MAX) == NULL) { 87 if (getcwd(resolved, PATH_MAX) == NULL) {
74 strlcpy(resolved, ".", PATH_MAX); 88 if (mem_allocated)
89 free(resolved);
90 else
91 strlcpy(resolved, ".", PATH_MAX);
75 return (NULL); 92 return (NULL);
76 } 93 }
77 resolved_len = strlen(resolved); 94 resolved_len = strlen(resolved);
@@ -79,7 +96,7 @@ realpath(const char *path, char resolved[PATH_MAX])
79 } 96 }
80 if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { 97 if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
81 errno = ENAMETOOLONG; 98 errno = ENAMETOOLONG;
82 return (NULL); 99 goto err;
83 } 100 }
84 101
85 /* 102 /*
@@ -94,7 +111,7 @@ realpath(const char *path, char resolved[PATH_MAX])
94 s = p ? p : left + left_len; 111 s = p ? p : left + left_len;
95 if (s - left >= (ptrdiff_t)sizeof(next_token)) { 112 if (s - left >= (ptrdiff_t)sizeof(next_token)) {
96 errno = ENAMETOOLONG; 113 errno = ENAMETOOLONG;
97 return (NULL); 114 goto err;
98 } 115 }
99 memcpy(next_token, left, s - left); 116 memcpy(next_token, left, s - left);
100 next_token[s - left] = '\0'; 117 next_token[s - left] = '\0';
@@ -104,7 +121,7 @@ realpath(const char *path, char resolved[PATH_MAX])
104 if (resolved[resolved_len - 1] != '/') { 121 if (resolved[resolved_len - 1] != '/') {
105 if (resolved_len + 1 >= PATH_MAX) { 122 if (resolved_len + 1 >= PATH_MAX) {
106 errno = ENAMETOOLONG; 123 errno = ENAMETOOLONG;
107 return (NULL); 124 goto err;
108 } 125 }
109 resolved[resolved_len++] = '/'; 126 resolved[resolved_len++] = '/';
110 resolved[resolved_len] = '\0'; 127 resolved[resolved_len] = '\0';
@@ -135,23 +152,23 @@ realpath(const char *path, char resolved[PATH_MAX])
135 resolved_len = strlcat(resolved, next_token, PATH_MAX); 152 resolved_len = strlcat(resolved, next_token, PATH_MAX);
136 if (resolved_len >= PATH_MAX) { 153 if (resolved_len >= PATH_MAX) {
137 errno = ENAMETOOLONG; 154 errno = ENAMETOOLONG;
138 return (NULL); 155 goto err;
139 } 156 }
140 if (lstat(resolved, &sb) != 0) { 157 if (lstat(resolved, &sb) != 0) {
141 if (errno == ENOENT && p == NULL) { 158 if (errno == ENOENT && p == NULL) {
142 errno = serrno; 159 errno = serrno;
143 return (resolved); 160 return (resolved);
144 } 161 }
145 return (NULL); 162 goto err;
146 } 163 }
147 if (S_ISLNK(sb.st_mode)) { 164 if (S_ISLNK(sb.st_mode)) {
148 if (symlinks++ > MAXSYMLINKS) { 165 if (symlinks++ > MAXSYMLINKS) {
149 errno = ELOOP; 166 errno = ELOOP;
150 return (NULL); 167 goto err;
151 } 168 }
152 slen = readlink(resolved, symlink, sizeof(symlink) - 1); 169 slen = readlink(resolved, symlink, sizeof(symlink) - 1);
153 if (slen < 0) 170 if (slen < 0)
154 return (NULL); 171 goto err;
155 symlink[slen] = '\0'; 172 symlink[slen] = '\0';
156 if (symlink[0] == '/') { 173 if (symlink[0] == '/') {
157 resolved[1] = 0; 174 resolved[1] = 0;
@@ -174,7 +191,7 @@ realpath(const char *path, char resolved[PATH_MAX])
174 if (slen + 1 >= 191 if (slen + 1 >=
175 (ptrdiff_t)sizeof(symlink)) { 192 (ptrdiff_t)sizeof(symlink)) {
176 errno = ENAMETOOLONG; 193 errno = ENAMETOOLONG;
177 return (NULL); 194 goto err;
178 } 195 }
179 symlink[slen] = '/'; 196 symlink[slen] = '/';
180 symlink[slen + 1] = 0; 197 symlink[slen + 1] = 0;
@@ -182,7 +199,7 @@ realpath(const char *path, char resolved[PATH_MAX])
182 left_len = strlcat(symlink, left, sizeof(left)); 199 left_len = strlcat(symlink, left, sizeof(left));
183 if (left_len >= sizeof(left)) { 200 if (left_len >= sizeof(left)) {
184 errno = ENAMETOOLONG; 201 errno = ENAMETOOLONG;
185 return (NULL); 202 goto err;
186 } 203 }
187 } 204 }
188 left_len = strlcpy(left, symlink, sizeof(left)); 205 left_len = strlcpy(left, symlink, sizeof(left));
@@ -196,5 +213,10 @@ realpath(const char *path, char resolved[PATH_MAX])
196 if (resolved_len > 1 && resolved[resolved_len - 1] == '/') 213 if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
197 resolved[resolved_len - 1] = '\0'; 214 resolved[resolved_len - 1] = '\0';
198 return (resolved); 215 return (resolved);
216
217err:
218 if (mem_allocated)
219 free(resolved);
220 return (NULL);
199} 221}
200#endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */ 222#endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */