Skip to content

Commit d169bc2

Browse files
committed
Improve randomness of uploaded file names and files created by tempnam()
1 parent 8a87206 commit d169bc2

File tree

2 files changed

+36
-19
lines changed

2 files changed

+36
-19
lines changed

ext/standard/tests/file/tempnam_variation9.phpt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,17 @@ if (file_exists($file_path)) {
5757
--EXPECTF--
5858
*** Testing tempnam() maximum prefix size ***
5959
-- Iteration 0 --
60-
File name is => begin_%rx{7}%r_end%r.{6}%r
61-
File name length is => 23
60+
File name is => begin_%rx{7}%r_end%r.{38}%r
61+
File name length is => 55
6262
-- Iteration 1 --
63-
File name is => begin_%rx{53}%r_end%r.{6}%r
64-
File name length is => 69
63+
File name is => begin_%rx{53}%r_end%r.{38}%r
64+
File name length is => 101
6565
-- Iteration 2 --
66-
File name is => begin_%rx{54}%r_en%r.{6}%r
67-
File name length is => 69
66+
File name is => begin_%rx{54}%r_en%r.{38}%r
67+
File name length is => 101
6868
-- Iteration 3 --
69-
File name is => begin_%rx{55}%r_e%r.{6}%r
70-
File name length is => 69
69+
File name is => begin_%rx{55}%r_e%r.{38}%r
70+
File name length is => 101
7171
-- Iteration 4 --
72-
File name is => begin_%rx{57}%r%r.{6}%r
73-
File name length is => 69
72+
File name is => begin_%rx{57}%r%r.{38}%r
73+
File name length is => 101

main/php_open_temporary_file.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
*/
1616

1717
#include "php.h"
18+
#include "zend_long.h"
1819
#include "php_open_temporary_file.h"
20+
#include "ext/random/php_random.h"
1921

2022
#include <errno.h>
2123
#include <sys/types.h>
@@ -89,11 +91,13 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, zend_st
8991
#ifdef PHP_WIN32
9092
char *opened_path = NULL;
9193
size_t opened_path_len;
92-
wchar_t *cwdw, *pfxw, pathw[MAXPATHLEN];
94+
wchar_t *cwdw, *random_prefix_w, pathw[MAXPATHLEN];
9395
#else
9496
char opened_path[MAXPATHLEN];
9597
char *trailing_slash;
9698
#endif
99+
uint64_t random[2];
100+
char *random_prefix;
97101
char cwd[MAXPATHLEN];
98102
cwd_state new_state;
99103
int fd = -1;
@@ -128,34 +132,45 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, zend_st
128132
return -1;
129133
}
130134

135+
/* Extend the prefix to increase randomness */
136+
if (php_random_bytes_silent(&random, sizeof(random)) == FAILURE) {
137+
random[0] = php_random_generate_fallback_seed();
138+
random[1] = php_random_generate_fallback_seed();
139+
}
140+
141+
spprintf(&random_prefix, 0, "%s%016" PRIx64 "%016" PRIx64, pfx, random[0], random[1]);
142+
131143
#ifndef PHP_WIN32
132144
if (IS_SLASH(new_state.cwd[new_state.cwd_length - 1])) {
133145
trailing_slash = "";
134146
} else {
135147
trailing_slash = "/";
136148
}
137149

138-
if (snprintf(opened_path, MAXPATHLEN, "%s%s%sXXXXXX", new_state.cwd, trailing_slash, pfx) >= MAXPATHLEN) {
150+
if (snprintf(opened_path, MAXPATHLEN, "%s%s%sXXXXXX", new_state.cwd, trailing_slash, random_prefix) >= MAXPATHLEN) {
151+
efree(random_prefix);
139152
efree(new_state.cwd);
140153
return -1;
141154
}
142155
#endif
143156

144157
#ifdef PHP_WIN32
145158
cwdw = php_win32_ioutil_any_to_w(new_state.cwd);
146-
pfxw = php_win32_ioutil_any_to_w(pfx);
147-
if (!cwdw || !pfxw) {
159+
random_prefix_w = php_win32_ioutil_any_to_w(random_prefix);
160+
if (!cwdw || !random_prefix_w) {
148161
free(cwdw);
149-
free(pfxw);
162+
free(random_prefix_w);
163+
efree(random_prefix);
150164
efree(new_state.cwd);
151165
return -1;
152166
}
153167

154-
if (GetTempFileNameW(cwdw, pfxw, 0, pathw)) {
168+
if (GetTempFileNameW(cwdw, random_prefix_w, 0, pathw)) {
155169
opened_path = php_win32_ioutil_conv_w_to_any(pathw, PHP_WIN32_CP_IGNORE_LEN, &opened_path_len);
156170
if (!opened_path || opened_path_len >= MAXPATHLEN) {
157171
free(cwdw);
158-
free(pfxw);
172+
free(random_prefix_w);
173+
efree(random_prefix);
159174
efree(new_state.cwd);
160175
return -1;
161176
}
@@ -165,7 +180,8 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, zend_st
165180
* which means that opening it will fail... */
166181
if (VCWD_CHMOD(opened_path, 0600)) {
167182
free(cwdw);
168-
free(pfxw);
183+
free(random_prefix_w);
184+
efree(random_prefix);
169185
efree(new_state.cwd);
170186
free(opened_path);
171187
return -1;
@@ -174,7 +190,7 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, zend_st
174190
}
175191

176192
free(cwdw);
177-
free(pfxw);
193+
free(random_prefix_w);
178194
#elif defined(HAVE_MKSTEMP)
179195
fd = mkstemp(opened_path);
180196
#else
@@ -194,6 +210,7 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, zend_st
194210
}
195211
#endif
196212
efree(new_state.cwd);
213+
efree(random_prefix);
197214
return fd;
198215
}
199216
/* }}} */

0 commit comments

Comments
 (0)