@@ -113,37 +113,47 @@ static zend_string* php_password_get_salt(zval *unused_, size_t required_salt_le
113113
114114/* bcrypt implementation */
115115
116- static bool php_password_bcrypt_valid (const zend_string * hash ) {
116+ static bool php_password_bcrypt_get_cost (const zend_string * hash , zend_long * cost ) {
117117 const char * h = ZSTR_VAL (hash );
118- return (ZSTR_LEN (hash ) == 60 ) &&
119- (h [0 ] == '$' ) && (h [1 ] == '2' ) && (h [2 ] == 'y' );
118+
119+ if ((ZSTR_LEN (hash ) != 60 ) ||
120+ (h [0 ] != '$' ) || (h [1 ] != '2' ) || (h [2 ] != 'y' ) || (h [3 ] != '$' ) ||
121+ !ZEND_IS_DIGIT (h [4 ]) || !ZEND_IS_DIGIT (h [5 ]) || (h [6 ] != '$' )) {
122+ return false;
123+ }
124+
125+ * cost = (h [4 ] - '0' ) * 10 + (h [5 ] - '0' );
126+
127+ return * cost >= 4 && * cost <= 31 ;
128+ }
129+
130+ static bool php_password_bcrypt_valid (const zend_string * hash ) {
131+ zend_long cost ;
132+
133+ return php_password_bcrypt_get_cost (hash , & cost );
120134}
121135
122136static int php_password_bcrypt_get_info (zval * return_value , const zend_string * hash ) {
123- zend_long cost = PHP_PASSWORD_BCRYPT_COST ;
137+ zend_long cost ;
124138
125- if (!php_password_bcrypt_valid (hash )) {
139+ if (!php_password_bcrypt_get_cost (hash , & cost )) {
126140 /* Should never get called this way. */
127141 return FAILURE ;
128142 }
129-
130- sscanf (ZSTR_VAL (hash ), "$2y$" ZEND_LONG_FMT "$" , & cost );
131143 add_assoc_long (return_value , "cost" , cost );
132144
133145 return SUCCESS ;
134146}
135147
136148static bool php_password_bcrypt_needs_rehash (const zend_string * hash , zend_array * options ) {
137149 zval * znew_cost ;
138- zend_long old_cost = PHP_PASSWORD_BCRYPT_COST ;
150+ zend_long old_cost ;
139151 zend_long new_cost = PHP_PASSWORD_BCRYPT_COST ;
140152
141- if (!php_password_bcrypt_valid (hash )) {
153+ if (!php_password_bcrypt_get_cost (hash , & old_cost )) {
142154 /* Should never get called this way. */
143155 return 1 ;
144156 }
145-
146- sscanf (ZSTR_VAL (hash ), "$2y$" ZEND_LONG_FMT "$" , & old_cost );
147157 if (options && (znew_cost = zend_hash_str_find (options , "cost" , sizeof ("cost" )- 1 )) != NULL ) {
148158 new_cost = zval_get_long (znew_cost );
149159 }
0 commit comments