php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login

Patch php-move-upladed-files-race-condition.patch for Filesystem function related Bug #55576

Patch version 2011-09-03 11:35 UTC

Return to Bug #55576 | Download this patch
Patch Revisions:

Developer: cjk@wwwtech.de

diff -ru php-5.3.8-orig//ext/standard/basic_functions.c php-5.3.8/ext/standard/basic_functions.c
--- php-5.3.8-orig//ext/standard/basic_functions.c	2011-09-03 12:46:32.559176875 +0200
+++ php-5.3.8/ext/standard/basic_functions.c	2011-09-03 13:33:41.478176780 +0200
@@ -117,6 +117,8 @@
 #include "php_fopen_wrappers.h"
 #include "streamsfuncs.h"
 
+#include <fcntl.h>
+
 static zend_class_entry *incomplete_class_entry = NULL;
 
 typedef struct _php_shutdown_function_entry {
@@ -834,9 +836,10 @@
 	ZEND_ARG_INFO(0, path)
 ZEND_END_ARG_INFO()
 
-ZEND_BEGIN_ARG_INFO(arginfo_move_uploaded_file, 0)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_move_uploaded_file, 0, 0, 2)
 	ZEND_ARG_INFO(0, path)
 	ZEND_ARG_INFO(0, new_path)
+    ZEND_ARG_INFO(0, dont_overwrite)
 ZEND_END_ARG_INFO()
 
 ZEND_BEGIN_ARG_INFO_EX(arginfo_parse_ini_file, 0, 0, 1)
@@ -5814,8 +5817,8 @@
 PHP_FUNCTION(move_uploaded_file)
 {
 	char *path, *new_path;
-	int path_len, new_path_len;
-	zend_bool successful = 0;
+	int path_len, new_path_len, fd;
+	zend_bool successful = 0, dont_overwrite = 0;
 
 #ifndef PHP_WIN32
 	int oldmask; int ret;
@@ -5825,7 +5828,7 @@
 		RETURN_FALSE;
 	}
 
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &path, &path_len, &new_path, &new_path_len) == FAILURE) {
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &path, &path_len, &new_path, &new_path_len, &dont_overwrite) == FAILURE) {
 		return;
 	}
 
@@ -5849,7 +5852,20 @@
 		RETURN_FALSE;
 	}
 
-	VCWD_UNLINK(new_path);
+    if (!dont_overwrite) {
+        oldmask = umask(077);
+		umask(oldmask);
+
+        if ((fd = open (new_path, O_RDWR|O_CREAT|O_EXCL, 0666 & ~oldmask)) == -1) {
+            /* file exists, return false */
+            RETURN_FALSE;
+        }
+
+        /* file does not exist, we created it successfully exclusive, continue */
+        close (fd);
+    }
+
+    /* VCWD_UNLINK(new_path); no longer unlink() because of the race condition */
 	if (VCWD_RENAME(path, new_path) == 0) {
 		successful = 1;
 #ifndef PHP_WIN32
@@ -5870,6 +5886,10 @@
 	if (successful) {
 		zend_hash_del(SG(rfc1867_uploaded_files), path, path_len + 1);
 	} else {
+        if (dont_overwrite) {
+            VCWD_UNLINK(new_path); /* since we created a file with O_EXCL, we have to remove it again in error case */
+        }
+
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to move '%s' to '%s'", path, new_path);
 	}
 
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Thu Apr 17 03:01:55 2014 UTC