]> granicus.if.org Git - php/commitdiff
Fixed bug #76803 ftruncate changes file pointer
authorAnatol Belski <ab@php.net>
Tue, 28 Aug 2018 13:42:39 +0000 (15:42 +0200)
committerAnatol Belski <ab@php.net>
Tue, 28 Aug 2018 13:42:39 +0000 (15:42 +0200)
ext/standard/tests/file/ftruncate_bug76803.phpt [new file with mode: 0644]
main/streams/plain_wrapper.c

diff --git a/ext/standard/tests/file/ftruncate_bug76803.phpt b/ext/standard/tests/file/ftruncate_bug76803.phpt
new file mode 100644 (file)
index 0000000..7e99cf2
--- /dev/null
@@ -0,0 +1,38 @@
+--TEST--\r
+Bug #76803 ftruncate changes file pointer\r
+--FILE--\r
+<?php\r
+\r
+$fn = dirname(__FILE__) . DIRECTORY_SEPARATOR . "test76803";\r
+\r
+$f = fopen($fn, "w");\r
+fwrite($f, "Hello");\r
+ftruncate($f, 2);\r
+fwrite($f, "World");\r
+fclose($f);\r
+var_dump(addslashes(file_get_contents($fn)));\r
+\r
+$f = fopen($fn, "w");\r
+fwrite($f, "Hello");\r
+ftruncate($f, 2);\r
+fclose($f);\r
+var_dump(addslashes(file_get_contents($fn)));\r
+\r
+$f = fopen('php://memory', 'w+');\r
+fwrite($f, 'Hello');\r
+ftruncate($f, 2); // in 7.3 changes file pointer to 2\r
+fwrite($f, 'World');\r
+rewind($f);\r
+var_dump(addslashes(stream_get_contents($f)));\r
+fclose($f);\r
+\r
+?>\r
+--CLEAN--\r
+<?php\r
+$fn = dirname(__FILE__) . DIRECTORY_SEPARATOR . "test76803";\r
+unlink($fn);\r
+?>\r
+--EXPECT--\r
+string(13) "He\0\0\0World"\r
+string(2) "He"\r
+string(7) "HeWorld"\r
index 08c9380ddde77ca33d3f889e95c3751870c5aa41..b2fc00b2264573d7ebf8cba290aa8fe74d395cdd 100644 (file)
@@ -857,6 +857,12 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
                                        if (INVALID_HANDLE_VALUE == h) {
                                                return PHP_STREAM_OPTION_RETURN_ERR;
                                        }
+
+                                       LARGE_INTEGER old_sz;
+                                       if (!GetFileSizeEx(h, &old_sz)) {
+                                               return PHP_STREAM_OPTION_RETURN_ERR;
+                                       }
+
                                        LARGE_INTEGER sz;
 #if defined(_WIN64)
                                        sz.HighPart = (new_size >> 32);
@@ -871,6 +877,9 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
                                        if (0 == SetEndOfFile(h)) {
                                                return PHP_STREAM_OPTION_RETURN_ERR;
                                        }
+                                       if (INVALID_SET_FILE_POINTER == SetFilePointerEx(h, old_sz, NULL, FILE_BEGIN) && NO_ERROR != GetLastError()) {
+                                               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;