]> granicus.if.org Git - php/commitdiff
Fixed bug #76422 ftruncate fails on files > 2GB
authorAnatol Belski <ab@php.net>
Sat, 9 Jun 2018 09:23:06 +0000 (11:23 +0200)
committerAnatol Belski <ab@php.net>
Sat, 9 Jun 2018 09:28:24 +0000 (11:28 +0200)
ext/standard/tests/file/ftruncate_bug76422.phpt [new file with mode: 0644]
ext/standard/tests/file/ftruncate_variation2-win32.phpt
main/streams/plain_wrapper.c

diff --git a/ext/standard/tests/file/ftruncate_bug76422.phpt b/ext/standard/tests/file/ftruncate_bug76422.phpt
new file mode 100644 (file)
index 0000000..46f52aa
--- /dev/null
@@ -0,0 +1,36 @@
+--TEST--\r
+Bug #76422 ftruncate fails on files > 2GB\r
+--SKIPIF--\r
+<?php\r
+if (PHP_INT_SIZE < 8) {\r
+    die('skip.. only valid for 64-bit');\r
+}\r
+?>\r
+--FILE--\r
+<?php\r
+\r
+$fn = dirname(__FILE__) . DIRECTORY_SEPARATOR . "test76422";\r
+\r
+$file_handle = fopen($fn,'cb');\r
+\r
+if (false === $file_handle) {\r
+    die('Cannot open test file :/');\r
+}\r
+\r
+$truncate_offset = 4 * 1024 * 1024 * 1024 + 1;\r
+$ftruncate_result = ftruncate($file_handle, $truncate_offset);\r
+\r
+if (false === $ftruncate_result) {\r
+    die('Truncate has failed :/');\r
+}\r
+\r
+fclose($file_handle);\r
+var_dump(filesize($fn) >= $truncate_offset);\r
+?>\r
+--CLEAN--\r
+<?php\r
+$fn = dirname(__FILE__) . "/test76422";\r
+unlink($fn);\r
+?>\r
+--EXPECT--\r
+bool(true)\r
index 535881206ac7977f3e66ffdcc22c87d1543ada53..6d62f75f1af74310b409e36e27172b1b36c12822 100644 (file)
@@ -77,7 +77,7 @@ echo "Done\n";
 -- Testing ftruncate(): truncate file to size = current size --
 int(1024)
 int(0)
-bool(true)
+bool(false)
 int(0)
 bool(false)
 int(1024)
@@ -85,7 +85,7 @@ int(1024)
 -- Testing ftruncate(): truncate file to size = current size --
 int(1024)
 int(0)
-bool(true)
+bool(false)
 int(0)
 bool(false)
 int(1024)
@@ -93,7 +93,7 @@ int(1024)
 -- Testing ftruncate(): truncate file to size = current size --
 int(1024)
 int(0)
-bool(true)
+bool(false)
 int(0)
 bool(false)
 int(1024)
@@ -271,7 +271,7 @@ int(1024)
 -- Testing ftruncate(): truncate file to size = current size --
 int(1024)
 int(0)
-bool(true)
+bool(false)
 int(0)
 bool(false)
 int(1024)
@@ -279,7 +279,7 @@ int(1024)
 -- Testing ftruncate(): truncate file to size = current size --
 int(1024)
 int(0)
-bool(true)
+bool(false)
 int(0)
 bool(false)
 int(1024)
@@ -287,7 +287,7 @@ int(1024)
 -- Testing ftruncate(): truncate file to size = current size --
 int(1024)
 int(0)
-bool(true)
+bool(false)
 int(0)
 bool(false)
 int(1024)
index 7657b35faf4c49aeaedf9c2370bbc6cc1f237c2b..285b12b0529b51953cb5782508aa8bea18cd710f 100644 (file)
@@ -854,7 +854,29 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
                                        if (new_size < 0) {
                                                return PHP_STREAM_OPTION_RETURN_ERR;
                                        }
+#ifdef PHP_WIN32
+                                       HANDLE h = (HANDLE) _get_osfhandle(fd);
+                                       if (INVALID_HANDLE_VALUE == h) {
+                                               return PHP_STREAM_OPTION_RETURN_ERR;
+                                       }
+                                       LARGE_INTEGER sz;
+#if defined(_WIN64)
+                                       sz.HighPart = (new_size >> 32);
+                                       sz.LowPart = (new_size & 0xffffffff);
+#else
+                                       sz.HighPart = 0;
+                                       sz.LowPart = new_size;
+#endif
+                                       if (INVALID_SET_FILE_POINTER == SetFilePointerEx(h, sz, NULL, FILE_BEGIN) && NO_ERROR != GetLastError()) {
+                                               return PHP_STREAM_OPTION_RETURN_ERR;
+                                       }
+                                       if (0 == SetEndOfFile(h)) {
+                                               return PHP_STREAM_OPTION_RETURN_ERR;
+                                       }
+                                       return PHP_STREAM_OPTION_RETURN_OK;
+#else
                                        return ftruncate(fd, new_size) == 0 ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;
+#endif
                                }
                        }