Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

PR for Password Hash RFC #191

Merged
merged 48 commits into from

4 participants

@ircmaxell

This is the pull request for the Password Hash RFC which was accepted.

Please review the changes, and if all looks good I will merge the PR in.

Thanks

Anthony

Anthony Ferrara and others added some commits
Anthony Ferrara Base structure for passsword_create and password_make_salt c77f2c2
Anthony Ferrara Actually complete password_create() 7e41980
Anthony Ferrara Implement password_verify 6574028
Anthony Ferrara Fix memory leak on branch f7097d9
Anthony Ferrara Basic random generator added to make_salt 18d3bd9
Anthony Ferrara More error checking, and some cleaning up for password.c 618f262
@ircmaxell ircmaxell Implement openssl support for make_salt 41d7374
Anthony Ferrara Refactor salt generation, rename password_create to password_hash 2d4b7cb
Anthony Ferrara Implement php.ini setting password.bcrypt_cost 232da90
Anthony Ferrara Add tests for password hashing e505316
Anthony Ferrara Update tests to check ini setting 2b9591f
Anthony Ferrara Add tests and error checking for large salt requested values to preve…
…nt overflow on allocation
5f44be0
@ircmaxell ircmaxell Fix formatting issues in password.c 0dd2f16
@ircmaxell ircmaxell Refactor crypt to use an external working function 6bb3865
@ircmaxell ircmaxell Refactor password.c a bit, add different error checking da3d8bf
@ircmaxell ircmaxell Merge remote branch 'upstream/master' into hash_password
Conflicts:
	ext/standard/crypt.c
9e18e57
@ircmaxell ircmaxell More refactoring of crypt into php_crypt, and fixing memory allocation 9c1445c
@ircmaxell ircmaxell Update password.c to use safe_emalloc in sensitive places f53112f
Anthony Ferrara Remove php.ini setting for default bcrypt cost 6cc3c65
Anthony Ferrara Some more refactoring, make algo no longer optional 6943f2a
Anthony Ferrara Update signature info for changing algo to an ordinal 886527d
@ircmaxell ircmaxell Implement password_needs_rehash() function 5160dc1
@ircmaxell ircmaxell Fix issue with int vs long parameter db86d54
@ircmaxell ircmaxell Implement password_get_info() function ee7e799
@ircmaxell ircmaxell Cleanup whitespace issues 9d3630b
@ircmaxell ircmaxell Merge remote branch 'upstream/master' into hash_password
* upstream/master: (34 commits)
  Fixed Bug #62500 (Segfault in DateInterval class when extended)
  Fixed test bug #62312 (warnings changed one more time)
  fix valgrind warning
  fix valgrind warning
  fixed #62433 test for win
  update NEWS
  Fixed bug #62499 (curl_setopt($ch, CURLOPT_COOKIEFILE, "") returns false)
  appease MSVC (doesnt like unary minus of unsigned ints)
  appease MSVC (doesnt like unary minus of unsigned ints)
  appease MSVC (doesnt like unary minus of unsigned ints)
  - Fixed bug #62507 (['REQUEST_TIME'] under mod_php5 returns miliseconds instead of seconds)
  Fixed Bug #62500 (Segfault in DateInterval class when extended)
  Added in NEWS and UPGRADING for feature 55218
  Fix two issues with run-tests.php
  Fix potential integer overflow in nl2br
  Fix potential integer overflow in bin2hex
  This wil be PHP 5.3.16
  Revert change 3f3ad30: There shouldn't be new features in 5.3, especially not if they aren't in 5.4, too.
  fix (signed) integer overflow (part of bug #52550
  fix (signed) integer overflow (part of bug #52550
  ...
99b7956
@ircmaxell ircmaxell Switch second parameter to password_make_salt to be a flag 707c907
@ircmaxell ircmaxell Remove password_make_salt() from the implementation e05413c
@ircmaxell ircmaxell Merge remote branch 'upstream/master' into hash_password
* upstream/master: (393 commits)
  forked two tests for windows
  Fixed bug #50997 (SOAP Error when trying to submit 2nd Element of a choice)
  Fixed bug #50997 (SOAP Error when trying to submit 2nd Element of a choice).
  Fixed bug #50997 (SOAP Error when trying to submit 2nd Element of a choice).
  Fixed bug #50997 (SOAP Error when trying to submit 2nd Element of a choice)
  Fixed bug #50997 (SOAP Error when trying to submit 2nd Element of a choice)
  Bug #49510: Boolean validation fails with FILTER_NULL_ON_FAILURE with empty string or false
  Implemented ReflectionFunction::isGenerator()
  Allow null as a default value for length in mb_substr() and mb_strcut()
  Allow null as a default value for length in mb_substr() and mb_strcut()
  folder
  Initializing optional argument description in assert()
  Initializing optional argument description in assert()
  Fix test failed due to new Token T_YIELD
  fix NEWS
  Fix leak when yielding array as key
  Drop obsolete test
  Remove extra blank in notice message, should act as same as vm
  Fixed bug #62987 (Assigning to ArrayObject[null][something] overrides all undefined variables)
  assert() user message
  ...
824f1f4
@ircmaxell ircmaxell Refactoring to use size_t instead of int most places db41f9f
@ircmaxell ircmaxell Add tests for password_get_info and password_needs_rehash e8b7f5b
@ircmaxell ircmaxell Switch test to using strict comparison for crypt fallback e9a7bde
@ircmaxell ircmaxell Remove bcrypt_cost ini entry from declaration ebe0bd5
@ircmaxell ircmaxell Expose PASSWORD_BCRYPT_DEFAULT_COST constant and update test to use it 76f3295
@ircmaxell ircmaxell Merge remote branch 'upstream/master' into hash_password
* upstream/master:
  Generators & UPGRADING
  Capitalize the warning message
  Rearrange the codes, remove empty lines
  Provide a specific error message if date.timezone value is invalid.
  regenerate patch, and save a strlen
  Fix the wrong use of snprintf which is introduced in 1d2f619
  Fixed unintendent clearance of PHP_OUTPUT_ACTIVATED flag
  Fix doc bug #63032 (Number of release in documentation).
  fixed test for bug #52944 also for darwin
  -enable VC11 (vc2012)
  - Fixed bug #61767 (Shutdown functions not called in certain error situation) - Fixed bug #60909 (custom error handler throwing Exception + fatal error = no shutdown function)
  year++
  correct PHP version & year++
  Correct PHP version
  year++
  - fix build, there was no tsrm context there, doing a fetch but this is horribly slow, this fix needs improvement (or simply add a TSRM context in the signature in master
  - fix build, declarations must be 1st in a contextgit checkout -f master
  Fixed bug #62907 (Double free when use traits)
  Fixed bug #62991 (Segfault with generator and closure)
3e383dc
@ircmaxell ircmaxell Add news entry for password API 7161c3d
ext/standard/basic_functions.c
@@ -1854,6 +1854,25 @@
ZEND_BEGIN_ARG_INFO(arginfo_getlastmod, 0)
ZEND_END_ARG_INFO()
/* }}} */
+/* {{{ password.c */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_password_hash, 0, 0, 1)
@nikic Owner
nikic added a note

Shouldn't the last arg be 2 as the algo is also a required argument?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@nikic nikic commented on the diff
ext/standard/password.c
((67 lines not shown))
+
+ return 0;
+}
+
+static int php_password_salt_is_alphabet(const char *str, const size_t len) /* {{{ */
+{
+ size_t i = 0;
+
+ for (i = 0; i < len; i++) {
+ if (!((str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= 'a' && str[i] <= 'z') || (str[i] >= '0' && str[i] <= '9') || str[i] == '.' || str[i] == '/')) {
+ return 0;
+ }
+ }
+ return 1;
+}
+/* }}} */
@nikic Owner
nikic added a note

I'd make this function return a zend_bool. Not that it matters much, but would make the semantics of the return value more clear.

Done. It now returns a zend_bool...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@lstrojny lstrojny commented on the diff
ext/standard/crypt.c
((33 lines not shown))
+
+ /* This will produce suitable results if people depend on DES-encryption
+ * available (passing always 2-character salt). At least for glibc6.1 */
+ memset(&salt[1], '$', PHP_MAX_SALT_LEN - 1);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &str, &str_len, &salt_in, &salt_in_len) == FAILURE) {
+ return;
+ }
+
+ if (salt_in) {
+ memcpy(salt, salt_in, MIN(PHP_MAX_SALT_LEN, salt_in_len));
+ }
+
+ /* The automatic salt generation covers standard DES, md5-crypt and Blowfish (simple) */
+ if (!*salt) {
+#if PHP_MD5_CRYPT

Does that mean that my salt will change depending on the platform?

That's core crypt() code that exists right now (as of 5.3.0). The reason for the change here is that I refactored it into two functions so I could call the implementation from C.

But now, the salt will not change (assuming that you're comment is ment for this line)...

Ah, alright. Never mind :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@ircmaxell

I've just added a commit to switch the algorithms definition to an ENUM (cleaner and allows for better type checking in the algos functions...

ext/standard/php_password.h
((23 lines not shown))
+
+PHP_FUNCTION(password_hash);
+PHP_FUNCTION(password_verify);
+PHP_FUNCTION(password_needs_rehash);
+PHP_FUNCTION(password_get_info);
+
+PHP_MINIT_FUNCTION(password);
+
+#define PHP_PASSWORD_DEFAULT PASSWORD_BCRYPT
+
+#define PHP_PASSWORD_BCRYPT_COST 10
+
+typedef enum {
+ PASSWORD_UNKNOWN,
+ PASSWORD_BCRYPT
+} php_password_algos;
@nikic Owner
nikic added a note

I'd rather call this enum php_password_algo (singular) as it fits in better with parameters and return values. Also I don't see why you removed the PHP_ prefix for the enum values. Those are global, so they should be prefixed too. (Only C++11 has proper non-global enum class values.)

Fixed by the next push.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
ext/standard/password.c
((168 lines not shown))
+ efree(result);
+ efree(buffer);
+ ret[length] = 0;
+ return SUCCESS;
+}
+/* }}} */
+
+PHP_FUNCTION(password_get_info)
+{
+ php_password_algos algo;
+ int hash_len;
+ char *hash, *algoName;
+ zval *options;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &hash, &hash_len) == FAILURE) {
+ RETURN_NULL();
@nikic Owner
nikic added a note

Not that it makes a difference, but zpp failures normally use just return; instead of of any particular RETURN_* value.

Fixed by the next push.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@nikic nikic commented on the diff
ext/standard/password.c
((160 lines not shown))
+ if (php_password_salt_to64(buffer, raw_length, length, result) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Generated salt too short");
+ efree(buffer);
+ efree(result);
+ return FAILURE;
+ } else {
+ memcpy(ret, result, (int) length);
+ }
+ efree(result);
+ efree(buffer);
+ ret[length] = 0;
+ return SUCCESS;
+}
+/* }}} */
+
+PHP_FUNCTION(password_get_info)
@nikic Owner
nikic added a note

password_get_info will return ['algo' => 'unknown', 'options' => []] on failure. Why was this chosen over returning false for example?

Mainly because I wanted a consistent return value. Having it always return an array seemed the better option to requiring yet another branch...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
ext/standard/password.c
((174 lines not shown))
+
+PHP_FUNCTION(password_get_info)
+{
+ php_password_algos algo;
+ int hash_len;
+ char *hash, *algoName;
+ zval *options;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &hash, &hash_len) == FAILURE) {
+ RETURN_NULL();
+ }
+
+ if (hash_len < 0 || (size_t) hash_len < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Supplied Password Hash Too Long To Safely Identify");
+ RETURN_FALSE;
+ }
@nikic Owner
nikic added a note

When can this happen? How can a string length be negative? And can size_t ever be smaller than int?

@nikic The string length could theoretically be negative if it exceeds the length of an int (overflow). I would rather check if hash_len is less than SIZE_MAX, but that's not defined on all systems...

@nikic Owner
nikic added a note

I see what you mean. But that's a general problem that all functions accepting a string have in PHP. Not sure whether it makes sense to check for it. But if you keep the check the error message shouldn't use ucwords (just normal lowercase).

If I wasn't casting to size_t for the internal operations, I wouldn't check for it. But with the cast, I felt that it would be prudent to at least check for it... I'll fix the error message (force of habit)...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
ext/standard/password.c
((164 lines not shown))
+ return FAILURE;
+ } else {
+ memcpy(ret, result, (int) length);
+ }
+ efree(result);
+ efree(buffer);
+ ret[length] = 0;
+ return SUCCESS;
+}
+/* }}} */
+
+PHP_FUNCTION(password_get_info)
+{
+ php_password_algos algo;
+ int hash_len;
+ char *hash, *algoName;
@nikic Owner
nikic added a note

I can't quote anything on this, but afaik PHP is using names_with_underscores instead of camel case.

Fixed with the next push.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
ext/standard/basic_functions.c
@@ -1854,6 +1854,25 @@
ZEND_BEGIN_ARG_INFO(arginfo_getlastmod, 0)
ZEND_END_ARG_INFO()
/* }}} */
+/* {{{ password.c */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_password_hash, 0, 0, 2)
+ ZEND_ARG_INFO(0, password)
+ ZEND_ARG_INFO(0, algo)
+ ZEND_ARG_INFO(0, options)
+ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_password_get_info, 0, 0, 1)
+ ZEND_ARG_INFO(0, hash)
+ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_password_needs_rehash, 0, 0, 1)
@nikic Owner
nikic added a note

Here again the last arg should be 2 (as the algo is required too).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
ext/standard/password.c
((230 lines not shown))
+
+ if (hash_len < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Supplied password hash too long to safely identify");
+ RETURN_FALSE;
+ }
+
+ algo = php_password_determine_algo(hash, (size_t) hash_len);
+
+ if (algo != new_algo) {
+ RETURN_TRUE;
+ }
+
+ switch (algo) {
+ case PHP_PASSWORD_BCRYPT:
+ {
+ int newCost = PHP_PASSWORD_BCRYPT_COST, cost = 0;
@nikic Owner
nikic added a note

I think those two should rather be long (as you're fetching the LVAL). Also newCost is in camel case again ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
ext/standard/password.c
((232 lines not shown))
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Supplied password hash too long to safely identify");
+ RETURN_FALSE;
+ }
+
+ algo = php_password_determine_algo(hash, (size_t) hash_len);
+
+ if (algo != new_algo) {
+ RETURN_TRUE;
+ }
+
+ switch (algo) {
+ case PHP_PASSWORD_BCRYPT:
+ {
+ int newCost = PHP_PASSWORD_BCRYPT_COST, cost = 0;
+
+ if (options && zend_symtable_find(options, "cost", 5, (void **) &option_buffer) == SUCCESS) {
@nikic Owner
nikic added a note

Use of the symtable function is not necessary here (only required when you're taking user input as the key), could be just zend_hash_find. The 5 would be better written as sizeof("cost"), to clarify its meaning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
ext/standard/password.c
((235 lines not shown))
+
+ algo = php_password_determine_algo(hash, (size_t) hash_len);
+
+ if (algo != new_algo) {
+ RETURN_TRUE;
+ }
+
+ switch (algo) {
+ case PHP_PASSWORD_BCRYPT:
+ {
+ int newCost = PHP_PASSWORD_BCRYPT_COST, cost = 0;
+
+ if (options && zend_symtable_find(options, "cost", 5, (void **) &option_buffer) == SUCCESS) {
+ convert_to_long_ex(option_buffer);
+ newCost = Z_LVAL_PP(option_buffer);
+ zval_ptr_dtor(option_buffer);
@nikic Owner
nikic added a note

This zval_ptr_dtor isn't right here. zend_symtable_find does not add an additional ref. Though I'm a bit confused now how this should be properly done when convert_to_long_ex is used...

@nikic Owner
nikic added a note

An example what would usually happen:

==7601== Invalid read of size 4
==7601==    at 0x8250A1E: _zval_ptr_dtor (zend.h:404)
==7601==    by 0x826235E: _zval_ptr_dtor_wrapper (zend_variables.c:180)
==7601==    by 0x8276453: zend_hash_destroy (zend_hash.c:560)
==7601==    by 0x8261EFB: _zval_dtor_func (zend_variables.c:43)
==7601==    by 0x82A6E58: zend_do_fcall_common_helper_SPEC (zend_variables.h:35)
==7601==    by 0x82AE0B9: ZEND_DO_FCALL_SPEC_CONST_HANDLER (zend_vm_execute.h:2447)
==7601==    by 0x82A453E: execute_ex (zend_vm_execute.h:440)
==7601==    by 0x82A4614: execute (zend_vm_execute.h:464)
==7601==    by 0x826665C: zend_execute_scripts (zend.c:1309)
==7601==    by 0x81C861B: php_execute_script (main.c:2459)
==7601==    by 0x83C5358: do_cli (php_cli.c:988)
==7601==    by 0x83C6893: main (php_cli.c:1364)
==7601==  Address 0x43ebe68 is 8 bytes inside a block of size 20 free'd
==7601==    at 0x402B06C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==7601==    by 0x822C56A: _efree (zend_alloc.c:2433)
==7601==    by 0x8250AFD: _zval_ptr_dtor (zend_execute_API.c:440)
==7601==    by 0x81BDC94: zif_password_needs_rehash (password.c:250)
==7601==    by 0x82A5FBE: zend_do_fcall_common_helper_SPEC (zend_vm_execute.h:655)

=> The value is first freed here and later in the hash dtor.

All memory leaks that I could find have been rectified. Please test again...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
ext/standard/password.c
((355 lines not shown))
+ convert_to_string_ex(option_buffer);
+ if (Z_TYPE_PP(option_buffer) == IS_STRING) {
+ buffer = Z_STRVAL_PP(option_buffer);
+ buffer_len_int = Z_STRLEN_PP(option_buffer);
+ if (buffer_len_int < 0) {
+ zval_ptr_dtor(option_buffer);
+ efree(hash_format);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Supplied salt is too long");
+ }
+ buffer_len = (size_t) buffer_len_int;
+ break;
+ }
+ case IS_RESOURCE:
+ case IS_ARRAY:
+ default:
+ zval_ptr_dtor(option_buffer);
@nikic Owner
nikic added a note

Again, this zval_ptr_dtor isn't right here (and also the ones in lines 360, 377 and 395). (And also again the 5 in the above symtable find call).

A much better fix has been included...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
ext/standard/password.c
((98 lines not shown))
+ ret[pos] = '.';
+ } else if (buffer[pos] == '=') {
+ efree(buffer);
+ return FAILURE;
+ } else {
+ ret[pos] = buffer[pos];
+ }
+ }
+ efree(buffer);
+ return SUCCESS;
+}
+/* }}} */
+
+static int php_password_make_salt(size_t length, char *ret TSRMLS_DC) /* {{{ */
+{
+ int buffer_valid = 0;
@nikic Owner
nikic added a note

This could be zend_bool too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
ext/standard/password.c
((152 lines not shown))
+ }
+#endif
+ if (!buffer_valid) {
+ for (i = 0; i < raw_length; i++) {
+ buffer[i] ^= (char) (255.0 * php_rand(TSRMLS_C) / RAND_MAX);
+ }
+ }
+
+ result = safe_emalloc(length, 1, 1);
+ if (php_password_salt_to64(buffer, raw_length, length, result) == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Generated salt too short");
+ efree(buffer);
+ efree(result);
+ return FAILURE;
+ } else {
+ memcpy(ret, result, (int) length);
@nikic Owner
nikic added a note

(int) cast seems unnecessary here. (Also the else clause can be dropped.)

Else clause dropped...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@nikic
Owner

I'm still getting a lot of valgrind warnings, e.g.

=29932== Invalid read of size 1
==29932==    at 0x8261B61: _zval_dtor_func (zend_variables.c:35)
==29932==    by 0x82507FE: _zval_ptr_dtor (zend_variables.h:35)
==29932==    by 0x826208A: _zval_ptr_dtor_wrapper (zend_variables.c:180)
==29932==    by 0x827617F: zend_hash_destroy (zend_hash.c:560)
==29932==    by 0x8261C27: _zval_dtor_func (zend_variables.c:43)
==29932==    by 0x82A6B84: zend_do_fcall_common_helper_SPEC (zend_variables.h:35)
==29932==    by 0x82ADDE5: ZEND_DO_FCALL_SPEC_CONST_HANDLER (zend_vm_execute.h:2447)
==29932==    by 0x82A426A: execute_ex (zend_vm_execute.h:440)
==29932==    by 0x82A4340: execute (zend_vm_execute.h:464)
==29932==    by 0x8266388: zend_execute_scripts (zend.c:1309)
==29932==    by 0x81C8347: php_execute_script (main.c:2459)
==29932==    by 0x83C5084: do_cli (php_cli.c:988)
==29932==  Address 0x43ee77b is 3 bytes inside a block of size 4 free'd
==29932==    at 0x402B06C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==29932==    by 0x822C296: _efree (zend_alloc.c:2433)
==29932==    by 0x825953C: convert_to_long_base (zend_operators.c:394)
==29932==    by 0x82593FD: convert_to_long (zend_operators.c:364)
==29932==    by 0x81BDF0E: zif_password_hash (password.c:332)
==29932==    by 0x82A5CEA: zend_do_fcall_common_helper_SPEC (zend_vm_execute.h:655)
==29932==    by 0x82ADDE5: ZEND_DO_FCALL_SPEC_CONST_HANDLER (zend_vm_execute.h:2447)
==29932==    by 0x82A426A: execute_ex (zend_vm_execute.h:440)
==29932==    by 0x82A4340: execute (zend_vm_execute.h:464)
==29932==    by 0x8266388: zend_execute_scripts (zend.c:1309)
==29932==    by 0x81C8347: php_execute_script (main.c:2459)
==29932==    by 0x83C5084: do_cli (php_cli.c:988)

==29932== Invalid free() / delete / delete[] / realloc()
==29932==    at 0x402B06C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==29932==    by 0x822C296: _efree (zend_alloc.c:2433)
==29932==    by 0x8261BCA: _zval_dtor_func (zend_variables.c:36)
==29932==    by 0x82507FE: _zval_ptr_dtor (zend_variables.h:35)
==29932==    by 0x826208A: _zval_ptr_dtor_wrapper (zend_variables.c:180)
==29932==    by 0x827617F: zend_hash_destroy (zend_hash.c:560)
==29932==    by 0x8261C27: _zval_dtor_func (zend_variables.c:43)
==29932==    by 0x82A6B84: zend_do_fcall_common_helper_SPEC (zend_variables.h:35)
==29932==    by 0x82ADDE5: ZEND_DO_FCALL_SPEC_CONST_HANDLER (zend_vm_execute.h:2447)
==29932==    by 0x82A426A: execute_ex (zend_vm_execute.h:440)
==29932==    by 0x82A4340: execute (zend_vm_execute.h:464)
==29932==    by 0x8266388: zend_execute_scripts (zend.c:1309)
==29932==  Address 0x43ee778 is 0 bytes inside a block of size 4 free'd
==29932==    at 0x402B06C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==29932==    by 0x822C296: _efree (zend_alloc.c:2433)
==29932==    by 0x825953C: convert_to_long_base (zend_operators.c:394)
==29932==    by 0x82593FD: convert_to_long (zend_operators.c:364)
==29932==    by 0x81BDF0E: zif_password_hash (password.c:332)
==29932==    by 0x82A5CEA: zend_do_fcall_common_helper_SPEC (zend_vm_execute.h:655)
==29932==    by 0x82ADDE5: ZEND_DO_FCALL_SPEC_CONST_HANDLER (zend_vm_execute.h:2447)
==29932==    by 0x82A426A: execute_ex (zend_vm_execute.h:440)
==29932==    by 0x82A4340: execute (zend_vm_execute.h:464)
==29932==    by 0x8266388: zend_execute_scripts (zend.c:1309)
==29932==    by 0x81C8347: php_execute_script (main.c:2459)
==29932==    by 0x83C5084: do_cli (php_cli.c:988)
==29932==
@nikic
Owner

Also from a quick look at the new code, you're using INIT_PZVAL_COPY to copy the zval, but that macro doesn't invoke the copy constructor. You should use MAKE_COPY_ZVAL instead. (This might be related to the invalid reads above. The lack of copy_ctor probably causes a double free on a string.)

@ircmaxell
@nikic
Owner

@ircmaxell I get that when running ext/standard/tests/password/password_bcrypt_errors.phpt. I compiled using --disable-all --enable-debug --enable-maintainer-zts.

@php-pulls php-pulls merged commit 0bc9ca3 into php:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 25, 2012
  1. Base structure for passsword_create and password_make_salt

    Anthony Ferrara authored
  2. Actually complete password_create()

    Anthony Ferrara authored
  3. Implement password_verify

    Anthony Ferrara authored
  4. Fix memory leak on branch

    Anthony Ferrara authored
  5. Basic random generator added to make_salt

    Anthony Ferrara authored
  6. More error checking, and some cleaning up for password.c

    Anthony Ferrara authored
  7. @ircmaxell
Commits on Jun 26, 2012
Commits on Jun 27, 2012
  1. Implement php.ini setting password.bcrypt_cost

    Anthony Ferrara authored
  2. Add tests for password hashing

    Anthony Ferrara authored
  3. Update tests to check ini setting

    Anthony Ferrara authored
  4. Add tests and error checking for large salt requested values to preve…

    Anthony Ferrara authored
    …nt overflow on allocation
  5. @ircmaxell
Commits on Jun 28, 2012
  1. @ircmaxell
  2. @ircmaxell
Commits on Jun 29, 2012
  1. @ircmaxell

    Merge remote branch 'upstream/master' into hash_password

    ircmaxell authored
    Conflicts:
    	ext/standard/crypt.c
  2. @ircmaxell
  3. @ircmaxell
Commits on Jul 3, 2012
  1. Remove php.ini setting for default bcrypt cost

    Anthony Ferrara authored
  2. Some more refactoring, make algo no longer optional

    Anthony Ferrara authored
  3. Update signature info for changing algo to an ordinal

    Anthony Ferrara authored
Commits on Jul 5, 2012
  1. @ircmaxell
  2. @ircmaxell
  3. @ircmaxell
  4. @ircmaxell

    Cleanup whitespace issues

    ircmaxell authored
Commits on Jul 10, 2012
  1. @ircmaxell

    Merge remote branch 'upstream/master' into hash_password

    ircmaxell authored
    * upstream/master: (34 commits)
      Fixed Bug #62500 (Segfault in DateInterval class when extended)
      Fixed test bug #62312 (warnings changed one more time)
      fix valgrind warning
      fix valgrind warning
      fixed #62433 test for win
      update NEWS
      Fixed bug #62499 (curl_setopt($ch, CURLOPT_COOKIEFILE, "") returns false)
      appease MSVC (doesnt like unary minus of unsigned ints)
      appease MSVC (doesnt like unary minus of unsigned ints)
      appease MSVC (doesnt like unary minus of unsigned ints)
      - Fixed bug #62507 (['REQUEST_TIME'] under mod_php5 returns miliseconds instead of seconds)
      Fixed Bug #62500 (Segfault in DateInterval class when extended)
      Added in NEWS and UPGRADING for feature 55218
      Fix two issues with run-tests.php
      Fix potential integer overflow in nl2br
      Fix potential integer overflow in bin2hex
      This wil be PHP 5.3.16
      Revert change 3f3ad30: There shouldn't be new features in 5.3, especially not if they aren't in 5.4, too.
      fix (signed) integer overflow (part of bug #52550
      fix (signed) integer overflow (part of bug #52550
      ...
Commits on Jul 12, 2012
  1. @ircmaxell
Commits on Aug 28, 2012
  1. @ircmaxell
Commits on Sep 4, 2012
  1. @ircmaxell

    Merge remote branch 'upstream/master' into hash_password

    ircmaxell authored
    * upstream/master: (393 commits)
      forked two tests for windows
      Fixed bug #50997 (SOAP Error when trying to submit 2nd Element of a choice)
      Fixed bug #50997 (SOAP Error when trying to submit 2nd Element of a choice).
      Fixed bug #50997 (SOAP Error when trying to submit 2nd Element of a choice).
      Fixed bug #50997 (SOAP Error when trying to submit 2nd Element of a choice)
      Fixed bug #50997 (SOAP Error when trying to submit 2nd Element of a choice)
      Bug #49510: Boolean validation fails with FILTER_NULL_ON_FAILURE with empty string or false
      Implemented ReflectionFunction::isGenerator()
      Allow null as a default value for length in mb_substr() and mb_strcut()
      Allow null as a default value for length in mb_substr() and mb_strcut()
      folder
      Initializing optional argument description in assert()
      Initializing optional argument description in assert()
      Fix test failed due to new Token T_YIELD
      fix NEWS
      Fix leak when yielding array as key
      Drop obsolete test
      Remove extra blank in notice message, should act as same as vm
      Fixed bug #62987 (Assigning to ArrayObject[null][something] overrides all undefined variables)
      assert() user message
      ...
  2. @ircmaxell
Commits on Sep 12, 2012
  1. @ircmaxell
  2. @ircmaxell
  3. @ircmaxell
  4. @ircmaxell
  5. @ircmaxell

    Merge remote branch 'upstream/master' into hash_password

    ircmaxell authored
    * upstream/master:
      Generators & UPGRADING
      Capitalize the warning message
      Rearrange the codes, remove empty lines
      Provide a specific error message if date.timezone value is invalid.
      regenerate patch, and save a strlen
      Fix the wrong use of snprintf which is introduced in 1d2f619
      Fixed unintendent clearance of PHP_OUTPUT_ACTIVATED flag
      Fix doc bug #63032 (Number of release in documentation).
      fixed test for bug #52944 also for darwin
      -enable VC11 (vc2012)
      - Fixed bug #61767 (Shutdown functions not called in certain error situation) - Fixed bug #60909 (custom error handler throwing Exception + fatal error = no shutdown function)
      year++
      correct PHP version & year++
      Correct PHP version
      year++
      - fix build, there was no tsrm context there, doing a fetch but this is horribly slow, this fix needs improvement (or simply add a TSRM context in the signature in master
      - fix build, declarations must be 1st in a contextgit checkout -f master
      Fixed bug #62907 (Double free when use traits)
      Fixed bug #62991 (Segfault with generator and closure)
  6. @ircmaxell
  7. @ircmaxell
Commits on Sep 13, 2012
  1. @ircmaxell
Commits on Sep 17, 2012
  1. @ircmaxell
  2. @ircmaxell

    Fix ucwords error casing

    ircmaxell authored
  3. @ircmaxell
  4. @ircmaxell
Commits on Oct 5, 2012
  1. @ircmaxell
  2. @ircmaxell
Commits on Oct 6, 2012
  1. @ircmaxell
  2. @ircmaxell
Commits on Oct 7, 2012
  1. @ircmaxell
  2. @ircmaxell
Something went wrong with that request. Please try again.