php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #75525 Access Violation in vcruntime140.dll
Submitted: 2017-11-14 17:48 UTC Modified: 2017-11-15 19:36 UTC
From: john-stevenson at blueyonder dot co dot uk Assigned: ab (profile)
Status: Closed Package: Reproducible crash
PHP Version: 7.2.0RC6 OS: Windows 10
Private report: No CVE-ID: None
 [2017-11-14 17:48 UTC] john-stevenson at blueyonder dot co dot uk
Description:
------------
When running on Windows with PHP_INI_SCAN_DIR set, php will either crash or misreport information when running php --ini. This did not happen on pre-7.2 versions.

php_init_config() calls PHPAPI php_scandir and the directory list returned has corrupted dirent->d_name values. This either causes an access violation when calling strrchr from the runtime, or results in any ini file in the directory being correctly reported, not reported or reported multiple times.

The crashes seem to happen more frequently when the target folder contains 200 + entries, although the misreported data can happen with a single entry.

 

Test script:
---------------
// The crashes happen more frequently on a debug build, so:
configure --disable-all --enable-cli --enable-debug --disable-zts

// Using my temp folder which has lots of stuff in it
run: SET PHP_INI_SCAN_DIR=C:\Users\John\AppData\Local\Temp

add an .ini file to the chosen folder (for example 'scan-dir.ini'). It isn't actually needed but it helps show the misreported data.


run: php.exe --ini

Expected result:
----------------
Configuration File (php.ini) Path: C:\WINDOWS
Loaded Configuration File:         (none)
Scan for additional .ini files in: C:\Users\John\AppData\Local\Temp
Additional .ini files parsed:      C:\Users\John\AppData\Local\Temp\scan-dir.ini

Actual result:
--------------
A crash:

>	vcruntime140d.dll!strrchr(const char * string, int ch) Line 203	C	Non-user code. Symbols loaded.
 	php7_debug.dll!php_init_config() Line 687	C	Symbols loaded.
 	php7_debug.dll!php_module_startup(_sapi_module_struct * sf, _zend_module_entry * additional_modules, unsigned int num_additional_modules) Line 2250	C	Symbols loaded.
 	php.exe!php_cli_startup(_sapi_module_struct * sapi_module) Line 431	C	Symbols loaded.
 	php.exe!main(int argc, char * * argv) Line 1371	C	Symbols loaded.
 	[External Code]		Annotated Frame

Unhandled exception thrown: read access violation.
**string** was 0x193A4B4A600. occurred

-----
Or missing data:

Configuration File (php.ini) Path: C:\WINDOWS
Loaded Configuration File:         (none)
Scan for additional .ini files in: C:\Users\John\AppData\Local\Temp
Additional .ini files parsed:      (none

-----
Or duplicate data:

Configuration File (php.ini) Path: C:\WINDOWS
Loaded Configuration File:         (none)
Scan for additional .ini files in: C:\Users\John\AppData\Local\Temp
Additional .ini files parsed:      C:\Users\John\AppData\Local\Temp\scan-dir.ini,
C:\Users\John\AppData\Local\Temp\scan-dir.ini,
C:\Users\John\AppData\Local\Temp\scan-dir.ini

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-11-14 18:37 UTC] john-stevenson at blueyonder dot co dot uk
I added a printf to show the dirent data written in php_scandir:

php_scandir.c, line 104
printf("%d: %p, ino=%d, off=%d, reclen=%d,  %s\n", nfiles, newdp, dp->d_ino, dp->d_off, dp->d_reclen, dp->d_name);

and another to show the received data in php_init_config:

php_ini.c, line 685:
printf("%d: %p, ino=%d, off=%d, reclen=%d,  %s\n", i, namelist[i], namelist[i]->d_ino, namelist[i]->d_off, namelist[i]->d_reclen,
namelist[i]->d_name);

Here is the output with PHP_INI_SCAN_DIR set to a directory containing one file.

0: 00000218870E2D50, ino=1, off=1, reclen=1, name=.
1: 00000218870E28D0, ino=1, off=2, reclen=2, name=..
2: 00000218870E51E0, ino=1, off=3, reclen=12, name=scan-dir.ini

0: 00000218870E2D50, ino=1, off=1, reclen=1, name=¦¦¦¦¦¦
1: 00000218870E28D0, ino=1, off=2, reclen=2, name=¦¦¦¦¦¦¦¦¿nÄd
2: 00000218870E51E0, ino=1, off=3, reclen=12, name=¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦

On a 7.1.11 build (VC14) the received data is the same.
 [2017-11-15 09:15 UTC] ab@php.net
Automatic comment on behalf of ab
Revision: http://git.php.net/?p=php-src.git;a=commit;h=020fdfd55dc534eecab12a53bb3ef50d7a71e5cb
Log: Fixed bug #75525 Access Violation in vcruntime140.dll
 [2017-11-15 09:15 UTC] ab@php.net
-Status: Open +Status: Closed
 [2017-11-15 09:26 UTC] ab@php.net
-Status: Closed +Status: Feedback
 [2017-11-15 09:26 UTC] ab@php.net
Please check the current dev with the patch above.

Thanks.
 [2017-11-15 18:59 UTC] john-stevenson at blueyonder dot co dot uk
-Status: Feedback +Status: Open
 [2017-11-15 18:59 UTC] john-stevenson at blueyonder dot co dot uk
Thanks. I can confirm that the data is no longer corrupted (using https://github.com/php/php-src/commit/9acbab30ccb4d7a55a6b2685db0f251e8c997d6d)

Incidentally, I had to add an ifdef in ext/pcre/php_pcre.c to get it to compile:

static PHP_GINIT_FUNCTION(pcre) /* {{{ */
{
	zend_hash_init(&pcre_globals->pcre_cache, 0, NULL, php_free_pcre_cache, 1);
	pcre_globals->backtrack_limit = 0;
	pcre_globals->recursion_limit = 0;
	pcre_globals->error_code      = PHP_PCRE_NO_ERROR;

#ifdef HAVE_PCRE_JIT_SUPPORT
	pcre_globals->jit = 1;
#endif
	php_pcre_init_pcre2(1);
}
/* }}} */
 [2017-11-15 19:36 UTC] ab@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: ab
 [2017-11-15 19:36 UTC] ab@php.net
Oh, thanks for that catch, fixed the JIT issue right now.

The rev you mentioned 9acbab30ccb4d7a55a6b2685db0f251e8c997d6d is master only, for 7.2 unfortunately the padding quirk is needed because of the binary compatibility. Of course if you build all the needed stuff yourself, you can apply this one to 7.2, too. It saves perhaps 8 bytes per struct on 64-bit at least. But not critical anyway.

Btw. some ready to check snapshots are also available under http://windows.php.net/snapshots/ , they should have synced already. 

I'm closing this one then.

Thanks!
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 09:01:32 2024 UTC