Vulnerability: Multiple integer overflows in mcrypt.c in the mcrypt extension in PHP before 5.5.37, 5.6.x before 5.6.23, and 7.x before 7.0.8 allow remote attackers to cause a denial of service (heap-based buffer overflow and application crash) or possibly have unspecified other impact via a crafted length value, related to the (1) mcrypt_generic and (2) mdecrypt_generic functions.
Vulnerability ID: CVE-2016-5769
CWE: CWE-190
Severity score: 6.4
Project: http://github.com/php/php-src
Published: 2016-08-07
File: ext/mcrypt/mcrypt.c
Commit message: Fix bug #72455:  Heap Overflow due to integer overflows
Commit author: Stanislav Malyshev

Vulnerable version (before fix):
  static int le_mcrypt;  typedef struct _php_mcrypt {  	MCRYPT td; 	zend_bool init; } php_mcrypt; ZEND_DECLARE_MODULE_GLOBALS(mcrypt)  zend_module_entry mcrypt_module_entry = { 	STANDARD_MODULE_HEADER, 	"mcrypt",  	mcrypt_functions, 	PHP_MINIT(mcrypt), PHP_MSHUTDOWN(mcrypt), 	NULL, NULL, ZEND_GET_MODULE(mcrypt) 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mcryptind) == FAILURE) {			\ 		return;																\ 	}																						\ 	ZEND_FETCH_RESOURCE (pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt);				  #define MCRYPT_GET_MODE_DIR_ARGS(DIRECTORY)								\ 	char *dir = NULL;                                                   \ PHP_INI_END() static void php_mcrypt_module_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ { 	php_mcrypt *pm = (php_mcrypt *) rsrc->ptr; 	if (pm) {	 		mcrypt_generic_deinit(pm->td); 		mcrypt_module_close(pm->td); 		efree(pm); PHP_MINFO_FUNCTION(mcrypt) /* {{{ */ 	smart_str_free(&tmp1); 	smart_str_free(&tmp2); 	php_info_print_table_end(); 	 	DISPLAY_INI_ENTRIES(); } /* }}} */ PHP_FUNCTION(mcrypt_module_open) 	int   mode_len,   mode_dir_len; 	MCRYPT td; 	php_mcrypt *pm;     	if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, "ssss", 		&cipher, &cipher_len, &cipher_dir, &cipher_dir_len, 		&mode,   &mode_len,   &mode_dir,   &mode_dir_len)) { 		return; 	} 	 	td = mcrypt_module_open ( 		cipher, 		cipher_dir_len > 0 ? cipher_dir : MCG(algorithms_dir), 		mode,  		mode_dir_len > 0 ? mode_dir : MCG(modes_dir) 	);  PHP_FUNCTION(mcrypt_generic_init) 	int max_key_size, key_size, iv_size; 	php_mcrypt *pm; 	int result = 0; 	 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &mcryptind, &key, &key_len, &iv, &iv_len) == FAILURE) { 		return; 	} PHP_FUNCTION(mcrypt_generic) 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) { 		return; 	} 	 	ZEND_FETCH_RESOURCE(pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt); 	PHP_MCRYPT_INIT_CHECK  PHP_FUNCTION(mcrypt_generic) 	if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */ 		block_size = mcrypt_enc_get_block_size(pm->td); 		data_size = (((data_len - 1) / block_size) + 1) * block_size; 		data_s = emalloc(data_size + 1); 		memset(data_s, 0, data_size); 		memcpy(data_s, data, data_len); PHP_FUNCTION(mcrypt_generic) 		memset(data_s, 0, data_size); 		memcpy(data_s, data, data_len); 	} 	 	mcrypt_generic(pm->td, data_s, data_size); 	data_s[data_size] = '\0';  PHP_FUNCTION(mdecrypt_generic) 	php_mcrypt *pm; 	char* data_s; 	int block_size, data_size; 	 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) { 		return; 	} 	 	ZEND_FETCH_RESOURCE(pm, php_mcrypt * , &mcryptind, -1, "MCrypt", le_mcrypt); 	PHP_MCRYPT_INIT_CHECK  PHP_FUNCTION(mdecrypt_generic) 	if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */ 		block_size = mcrypt_enc_get_block_size(pm->td); 		data_size = (((data_len - 1) / block_size) + 1) * block_size; 		data_s = emalloc(data_size + 1); 		memset(data_s, 0, data_size); 		memcpy(data_s, data, data_len); PHP_FUNCTION(mdecrypt_generic) 		memset(data_s, 0, data_size); 		memcpy(data_s, data, data_len); 	} 	 	mdecrypt_generic(pm->td, data_s, data_size);  	RETVAL_STRINGL(data_s, data_size, 1); PHP_FUNCTION(mcrypt_enc_get_supported_key_sizes) { 	int i, count = 0; 	int *key_sizes; 	 	MCRYPT_GET_TD_ARG 	array_init(return_value);  PHP_FUNCTION(mcrypt_enc_is_block_algorithm) 	MCRYPT_GET_TD_ARG  	if (mcrypt_enc_is_block_algorithm(pm->td) == 1) { 		RETURN_TRUE  	} else { 		RETURN_FALSE 	} PHP_FUNCTION(mcrypt_enc_get_modes_name) PHP_FUNCTION(mcrypt_module_self_test) { 	MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir); 	 	if (mcrypt_module_self_test(module, dir) == 0) { 		RETURN_TRUE; 	} else { PHP_FUNCTION(mcrypt_module_self_test) PHP_FUNCTION(mcrypt_module_is_block_algorithm_mode) { 	MCRYPT_GET_MODE_DIR_ARGS(modes_dir) 	 	if (mcrypt_module_is_block_algorithm_mode(module, dir) == 1) { 		RETURN_TRUE; 	} else { PHP_FUNCTION(mcrypt_module_is_block_algorithm_mode) PHP_FUNCTION(mcrypt_module_is_block_algorithm) { 	MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir) 	 	if (mcrypt_module_is_block_algorithm(module, dir) == 1) { 		RETURN_TRUE; 	} else { PHP_FUNCTION(mcrypt_module_is_block_algorithm) PHP_FUNCTION(mcrypt_module_is_block_mode) { 	MCRYPT_GET_MODE_DIR_ARGS(modes_dir) 	 	if (mcrypt_module_is_block_mode(module, dir) == 1) { 		RETURN_TRUE; 	} else { PHP_FUNCTION(mcrypt_module_is_block_mode) PHP_FUNCTION(mcrypt_module_get_algo_block_size) { 	MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir) 	 	RETURN_LONG(mcrypt_module_get_algo_block_size(module, dir)); } /* }}} */ PHP_FUNCTION(mcrypt_module_get_algo_block_size) PHP_FUNCTION(mcrypt_module_get_algo_key_size) { 	MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir); 	 	RETURN_LONG(mcrypt_module_get_algo_key_size(module, dir)); } /* }}} */ PHP_FUNCTION(mcrypt_module_get_supported_key_sizes) { 	int i, count = 0; 	int *key_sizes; 	 	MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir) 	array_init(return_value);  PHP_FUNCTION(mcrypt_list_algorithms) 		&lib_dir, &lib_dir_len) == FAILURE) { 		return; 	} 	 	array_init(return_value); 	modules = mcrypt_list_algorithms(lib_dir, &count);  PHP_FUNCTION(mcrypt_get_key_size) { 	char *cipher; 	char *module; 	int   cipher_len, module_len;  	char *cipher_dir_string; 	char *module_dir_string; 	MCRYPT td; PHP_FUNCTION(mcrypt_get_key_size) 		&cipher, &cipher_len, &module, &module_len) == FAILURE) { 		return; 	} 	 	td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string); 	if (td != MCRYPT_FAILED) { 		RETVAL_LONG(mcrypt_enc_get_key_size(td)); PHP_FUNCTION(mcrypt_get_block_size) { 	char *cipher; 	char *module; 	int   cipher_len, module_len;  	char *cipher_dir_string; 	char *module_dir_string; 	MCRYPT td; PHP_FUNCTION(mcrypt_get_block_size) 		&cipher, &cipher_len, &module, &module_len) == FAILURE) { 		return; 	} 	 	td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string); 	if (td != MCRYPT_FAILED) { 		RETVAL_LONG(mcrypt_enc_get_block_size(td)); PHP_FUNCTION(mcrypt_get_iv_size) { 	char *cipher; 	char *module; 	int   cipher_len, module_len;  	char *cipher_dir_string; 	char *module_dir_string; 	MCRYPT td; PHP_FUNCTION(mcrypt_get_iv_size) 		&cipher, &cipher_len, &module, &module_len) == FAILURE) { 		return; 	} 	 	td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string); 	if (td != MCRYPT_FAILED) { 		RETVAL_LONG(mcrypt_enc_get_iv_size(td)); static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, cons 	} else { /* dertermine smallest supported key > length of requested key */ 		use_key_length = max_key_length; /* start with max key length */ 		for (i = 0; i < count; i++) { 			if (key_length_sizes[i] >= key_len &&  				key_length_sizes[i] < use_key_length) 			{ 				use_key_length = key_length_sizes[i]; static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, cons 		memcpy(key_s, key, MIN(key_len, use_key_length)); 	} 	mcrypt_free (key_length_sizes); 	 	/* Check IV */ 	iv_s = NULL; 	iv_size = mcrypt_enc_get_iv_size (td); 	 	/* IV is required */ 	if (mcrypt_enc_mode_has_iv(td) == 1) { 		if (argc == 5) { static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, cons 	} else { 		mdecrypt_generic(td, data_s, data_size); 	} 	 	RETVAL_STRINGL(data_s, data_size, 1);  	/* freeing vars */ PHP_FUNCTION(mcrypt_encrypt) 	zval **mode; 	char *cipher, *key, *data, *iv = NULL; 	int cipher_len, key_len, data_len, iv_len = 0; 	 	MCRYPT_GET_CRYPT_ARGS 	 	convert_to_string_ex(mode);  	php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, Z_STRVAL_PP(mode), iv, iv_len, ZEND_NUM_ARGS(), MCRYPT_ENCRYPT, return_value TSRMLS_CC); PHP_FUNCTION(mcrypt_decrypt) 	int cipher_len, key_len, data_len, iv_len = 0;  	MCRYPT_GET_CRYPT_ARGS 	 	convert_to_string_ex(mode);  	php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, Z_STRVAL_PP(mode), iv, iv_len, ZEND_NUM_ARGS(), MCRYPT_DECRYPT, return_value TSRMLS_CC); PHP_FUNCTION(mcrypt_ecb) 	zval **mode; 	char *cipher, *key, *data, *iv = NULL; 	int cipher_len, key_len, data_len, iv_len = 0; 	 	MCRYPT_GET_CRYPT_ARGS  	convert_to_long_ex(mode); PHP_FUNCTION(mcrypt_cfb) 	zval **mode; 	char *cipher, *key, *data, *iv = NULL; 	int cipher_len, key_len, data_len, iv_len = 0; 	 	MCRYPT_GET_CRYPT_ARGS  	convert_to_long_ex(mode); PHP_FUNCTION(mcrypt_ofb) 	zval **mode; 	char *cipher, *key, *data, *iv = NULL; 	int cipher_len, key_len, data_len, iv_len = 0; 	 	MCRYPT_GET_CRYPT_ARGS  	convert_to_long_ex(mode); PHP_FUNCTION(mcrypt_create_iv) 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create an IV with a size of less than 1 or greater than %d", INT_MAX); 		RETURN_FALSE; 	} 	 	iv = ecalloc(size + 1, 1); 	 	if (source == RANDOM || source == URANDOM) { #if PHP_WIN32 		/* random/urandom equivalent on Windows */

Fixed version (after fix):
  static int le_mcrypt;  typedef struct _php_mcrypt { 	MCRYPT td; 	zend_bool init; } php_mcrypt; ZEND_DECLARE_MODULE_GLOBALS(mcrypt)  zend_module_entry mcrypt_module_entry = { 	STANDARD_MODULE_HEADER, 	"mcrypt", 	mcrypt_functions, 	PHP_MINIT(mcrypt), PHP_MSHUTDOWN(mcrypt), 	NULL, NULL, ZEND_GET_MODULE(mcrypt) 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mcryptind) == FAILURE) {			\ 		return;																\ 	}																						\ 	ZEND_FETCH_RESOURCE (pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt);  #define MCRYPT_GET_MODE_DIR_ARGS(DIRECTORY)								\ 	char *dir = NULL;                                                   \ PHP_INI_END() static void php_mcrypt_module_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ { 	php_mcrypt *pm = (php_mcrypt *) rsrc->ptr; 	if (pm) { 		mcrypt_generic_deinit(pm->td); 		mcrypt_module_close(pm->td); 		efree(pm); PHP_MINFO_FUNCTION(mcrypt) /* {{{ */ 	smart_str_free(&tmp1); 	smart_str_free(&tmp2); 	php_info_print_table_end();  	DISPLAY_INI_ENTRIES(); } /* }}} */ PHP_FUNCTION(mcrypt_module_open) 	int   mode_len,   mode_dir_len; 	MCRYPT td; 	php_mcrypt *pm;  	if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, "ssss", 		&cipher, &cipher_len, &cipher_dir, &cipher_dir_len, 		&mode,   &mode_len,   &mode_dir,   &mode_dir_len)) { 		return; 	}  	td = mcrypt_module_open ( 		cipher, 		cipher_dir_len > 0 ? cipher_dir : MCG(algorithms_dir), 		mode, 		mode_dir_len > 0 ? mode_dir : MCG(modes_dir) 	);  PHP_FUNCTION(mcrypt_generic_init) 	int max_key_size, key_size, iv_size; 	php_mcrypt *pm; 	int result = 0;  	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &mcryptind, &key, &key_len, &iv, &iv_len) == FAILURE) { 		return; 	} PHP_FUNCTION(mcrypt_generic) 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) { 		return; 	}  	ZEND_FETCH_RESOURCE(pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt); 	PHP_MCRYPT_INIT_CHECK  PHP_FUNCTION(mcrypt_generic) 	if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */ 		block_size = mcrypt_enc_get_block_size(pm->td); 		data_size = (((data_len - 1) / block_size) + 1) * block_size; 		if (data_size <= 0) { 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Integer overflow in data size"); 			RETURN_FALSE; 		} 		data_s = emalloc(data_size + 1); 		memset(data_s, 0, data_size); 		memcpy(data_s, data, data_len); PHP_FUNCTION(mcrypt_generic) 		memset(data_s, 0, data_size); 		memcpy(data_s, data, data_len); 	}  	mcrypt_generic(pm->td, data_s, data_size); 	data_s[data_size] = '\0';  PHP_FUNCTION(mdecrypt_generic) 	php_mcrypt *pm; 	char* data_s; 	int block_size, data_size;  	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) { 		return; 	}  	ZEND_FETCH_RESOURCE(pm, php_mcrypt * , &mcryptind, -1, "MCrypt", le_mcrypt); 	PHP_MCRYPT_INIT_CHECK  PHP_FUNCTION(mdecrypt_generic) 	if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */ 		block_size = mcrypt_enc_get_block_size(pm->td); 		data_size = (((data_len - 1) / block_size) + 1) * block_size; 		if (data_size <= 0) { 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Integer overflow in data size"); 			RETURN_FALSE; 		} 		data_s = emalloc(data_size + 1); 		memset(data_s, 0, data_size); 		memcpy(data_s, data, data_len); PHP_FUNCTION(mdecrypt_generic) 		memset(data_s, 0, data_size); 		memcpy(data_s, data, data_len); 	}  	mdecrypt_generic(pm->td, data_s, data_size);  	RETVAL_STRINGL(data_s, data_size, 1); PHP_FUNCTION(mcrypt_enc_get_supported_key_sizes) { 	int i, count = 0; 	int *key_sizes;  	MCRYPT_GET_TD_ARG 	array_init(return_value);  PHP_FUNCTION(mcrypt_enc_is_block_algorithm) 	MCRYPT_GET_TD_ARG  	if (mcrypt_enc_is_block_algorithm(pm->td) == 1) { 		RETURN_TRUE 	} else { 		RETURN_FALSE 	} PHP_FUNCTION(mcrypt_enc_get_modes_name) PHP_FUNCTION(mcrypt_module_self_test) { 	MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir);  	if (mcrypt_module_self_test(module, dir) == 0) { 		RETURN_TRUE; 	} else { PHP_FUNCTION(mcrypt_module_self_test) PHP_FUNCTION(mcrypt_module_is_block_algorithm_mode) { 	MCRYPT_GET_MODE_DIR_ARGS(modes_dir)  	if (mcrypt_module_is_block_algorithm_mode(module, dir) == 1) { 		RETURN_TRUE; 	} else { PHP_FUNCTION(mcrypt_module_is_block_algorithm_mode) PHP_FUNCTION(mcrypt_module_is_block_algorithm) { 	MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir)  	if (mcrypt_module_is_block_algorithm(module, dir) == 1) { 		RETURN_TRUE; 	} else { PHP_FUNCTION(mcrypt_module_is_block_algorithm) PHP_FUNCTION(mcrypt_module_is_block_mode) { 	MCRYPT_GET_MODE_DIR_ARGS(modes_dir)  	if (mcrypt_module_is_block_mode(module, dir) == 1) { 		RETURN_TRUE; 	} else { PHP_FUNCTION(mcrypt_module_is_block_mode) PHP_FUNCTION(mcrypt_module_get_algo_block_size) { 	MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir)  	RETURN_LONG(mcrypt_module_get_algo_block_size(module, dir)); } /* }}} */ PHP_FUNCTION(mcrypt_module_get_algo_block_size) PHP_FUNCTION(mcrypt_module_get_algo_key_size) { 	MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir);  	RETURN_LONG(mcrypt_module_get_algo_key_size(module, dir)); } /* }}} */ PHP_FUNCTION(mcrypt_module_get_supported_key_sizes) { 	int i, count = 0; 	int *key_sizes;  	MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir) 	array_init(return_value);  PHP_FUNCTION(mcrypt_list_algorithms) 		&lib_dir, &lib_dir_len) == FAILURE) { 		return; 	}  	array_init(return_value); 	modules = mcrypt_list_algorithms(lib_dir, &count);  PHP_FUNCTION(mcrypt_get_key_size) { 	char *cipher; 	char *module; 	int   cipher_len, module_len; 	char *cipher_dir_string; 	char *module_dir_string; 	MCRYPT td; PHP_FUNCTION(mcrypt_get_key_size) 		&cipher, &cipher_len, &module, &module_len) == FAILURE) { 		return; 	}  	td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string); 	if (td != MCRYPT_FAILED) { 		RETVAL_LONG(mcrypt_enc_get_key_size(td)); PHP_FUNCTION(mcrypt_get_block_size) { 	char *cipher; 	char *module; 	int   cipher_len, module_len; 	char *cipher_dir_string; 	char *module_dir_string; 	MCRYPT td; PHP_FUNCTION(mcrypt_get_block_size) 		&cipher, &cipher_len, &module, &module_len) == FAILURE) { 		return; 	}  	td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string); 	if (td != MCRYPT_FAILED) { 		RETVAL_LONG(mcrypt_enc_get_block_size(td)); PHP_FUNCTION(mcrypt_get_iv_size) { 	char *cipher; 	char *module; 	int   cipher_len, module_len; 	char *cipher_dir_string; 	char *module_dir_string; 	MCRYPT td; PHP_FUNCTION(mcrypt_get_iv_size) 		&cipher, &cipher_len, &module, &module_len) == FAILURE) { 		return; 	}  	td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string); 	if (td != MCRYPT_FAILED) { 		RETVAL_LONG(mcrypt_enc_get_iv_size(td)); static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, cons 	} else { /* dertermine smallest supported key > length of requested key */ 		use_key_length = max_key_length; /* start with max key length */ 		for (i = 0; i < count; i++) { 			if (key_length_sizes[i] >= key_len && 				key_length_sizes[i] < use_key_length) 			{ 				use_key_length = key_length_sizes[i]; static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, cons 		memcpy(key_s, key, MIN(key_len, use_key_length)); 	} 	mcrypt_free (key_length_sizes);  	/* Check IV */ 	iv_s = NULL; 	iv_size = mcrypt_enc_get_iv_size (td);  	/* IV is required */ 	if (mcrypt_enc_mode_has_iv(td) == 1) { 		if (argc == 5) { static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, cons 	} else { 		mdecrypt_generic(td, data_s, data_size); 	}  	RETVAL_STRINGL(data_s, data_size, 1);  	/* freeing vars */ PHP_FUNCTION(mcrypt_encrypt) 	zval **mode; 	char *cipher, *key, *data, *iv = NULL; 	int cipher_len, key_len, data_len, iv_len = 0;  	MCRYPT_GET_CRYPT_ARGS  	convert_to_string_ex(mode);  	php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, Z_STRVAL_PP(mode), iv, iv_len, ZEND_NUM_ARGS(), MCRYPT_ENCRYPT, return_value TSRMLS_CC); PHP_FUNCTION(mcrypt_decrypt) 	int cipher_len, key_len, data_len, iv_len = 0;  	MCRYPT_GET_CRYPT_ARGS  	convert_to_string_ex(mode);  	php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, Z_STRVAL_PP(mode), iv, iv_len, ZEND_NUM_ARGS(), MCRYPT_DECRYPT, return_value TSRMLS_CC); PHP_FUNCTION(mcrypt_ecb) 	zval **mode; 	char *cipher, *key, *data, *iv = NULL; 	int cipher_len, key_len, data_len, iv_len = 0;  	MCRYPT_GET_CRYPT_ARGS  	convert_to_long_ex(mode); PHP_FUNCTION(mcrypt_cfb) 	zval **mode; 	char *cipher, *key, *data, *iv = NULL; 	int cipher_len, key_len, data_len, iv_len = 0;  	MCRYPT_GET_CRYPT_ARGS  	convert_to_long_ex(mode); PHP_FUNCTION(mcrypt_ofb) 	zval **mode; 	char *cipher, *key, *data, *iv = NULL; 	int cipher_len, key_len, data_len, iv_len = 0;  	MCRYPT_GET_CRYPT_ARGS  	convert_to_long_ex(mode); PHP_FUNCTION(mcrypt_create_iv) 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create an IV with a size of less than 1 or greater than %d", INT_MAX); 		RETURN_FALSE; 	}  	iv = ecalloc(size + 1, 1);  	if (source == RANDOM || source == URANDOM) { #if PHP_WIN32 		/* random/urandom equivalent on Windows */

Patch:
patch: @@ -44,7 +44,7 @@
 
 static int le_mcrypt;
 
-typedef struct _php_mcrypt { 
+typedef struct _php_mcrypt {
 	MCRYPT td;
 	zend_bool init;
 } php_mcrypt;
@@ -292,7 +292,7 @@ ZEND_DECLARE_MODULE_GLOBALS(mcrypt)
 
 zend_module_entry mcrypt_module_entry = {
 	STANDARD_MODULE_HEADER,
-	"mcrypt", 
+	"mcrypt",
 	mcrypt_functions,
 	PHP_MINIT(mcrypt), PHP_MSHUTDOWN(mcrypt),
 	NULL, NULL,
@@ -376,7 +376,7 @@ ZEND_GET_MODULE(mcrypt)
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mcryptind) == FAILURE) {			\
 		return;																\
 	}																						\
-	ZEND_FETCH_RESOURCE (pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt);				
+	ZEND_FETCH_RESOURCE (pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt);
 
 #define MCRYPT_GET_MODE_DIR_ARGS(DIRECTORY)								\
 	char *dir = NULL;                                                   \
@@ -407,7 +407,7 @@ PHP_INI_END()
 static void php_mcrypt_module_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
 {
 	php_mcrypt *pm = (php_mcrypt *) rsrc->ptr;
-	if (pm) {	
+	if (pm) {
 		mcrypt_generic_deinit(pm->td);
 		mcrypt_module_close(pm->td);
 		efree(pm);
@@ -548,7 +548,7 @@ PHP_MINFO_FUNCTION(mcrypt) /* {{{ */
 	smart_str_free(&tmp1);
 	smart_str_free(&tmp2);
 	php_info_print_table_end();
-	
+
 	DISPLAY_INI_ENTRIES();
 }
 /* }}} */
@@ -563,17 +563,17 @@ PHP_FUNCTION(mcrypt_module_open)
 	int   mode_len,   mode_dir_len;
 	MCRYPT td;
 	php_mcrypt *pm;
-   
+
 	if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, "ssss",
 		&cipher, &cipher_len, &cipher_dir, &cipher_dir_len,
 		&mode,   &mode_len,   &mode_dir,   &mode_dir_len)) {
 		return;
 	}
-	
+
 	td = mcrypt_module_open (
 		cipher,
 		cipher_dir_len > 0 ? cipher_dir : MCG(algorithms_dir),
-		mode, 
+		mode,
 		mode_dir_len > 0 ? mode_dir : MCG(modes_dir)
 	);
 
@@ -600,7 +600,7 @@ PHP_FUNCTION(mcrypt_generic_init)
 	int max_key_size, key_size, iv_size;
 	php_mcrypt *pm;
 	int result = 0;
-	
+
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &mcryptind, &key, &key_len, &iv, &iv_len) == FAILURE) {
 		return;
 	}
@@ -679,7 +679,7 @@ PHP_FUNCTION(mcrypt_generic)
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) {
 		return;
 	}
-	
+
 	ZEND_FETCH_RESOURCE(pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt);
 	PHP_MCRYPT_INIT_CHECK
 
@@ -692,6 +692,10 @@ PHP_FUNCTION(mcrypt_generic)
 	if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */
 		block_size = mcrypt_enc_get_block_size(pm->td);
 		data_size = (((data_len - 1) / block_size) + 1) * block_size;
+		if (data_size <= 0) {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Integer overflow in data size");
+			RETURN_FALSE;
+		}
 		data_s = emalloc(data_size + 1);
 		memset(data_s, 0, data_size);
 		memcpy(data_s, data, data_len);
@@ -701,7 +705,7 @@ PHP_FUNCTION(mcrypt_generic)
 		memset(data_s, 0, data_size);
 		memcpy(data_s, data, data_len);
 	}
-	
+
 	mcrypt_generic(pm->td, data_s, data_size);
 	data_s[data_size] = '\0';
 
@@ -720,11 +724,11 @@ PHP_FUNCTION(mdecrypt_generic)
 	php_mcrypt *pm;
 	char* data_s;
 	int block_size, data_size;
-	
+
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) {
 		return;
 	}
-	
+
 	ZEND_FETCH_RESOURCE(pm, php_mcrypt * , &mcryptind, -1, "MCrypt", le_mcrypt);
 	PHP_MCRYPT_INIT_CHECK
 
@@ -737,6 +741,10 @@ PHP_FUNCTION(mdecrypt_generic)
 	if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */
 		block_size = mcrypt_enc_get_block_size(pm->td);
 		data_size = (((data_len - 1) / block_size) + 1) * block_size;
+		if (data_size <= 0) {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Integer overflow in data size");
+			RETURN_FALSE;
+		}
 		data_s = emalloc(data_size + 1);
 		memset(data_s, 0, data_size);
 		memcpy(data_s, data, data_len);
@@ -746,7 +754,7 @@ PHP_FUNCTION(mdecrypt_generic)
 		memset(data_s, 0, data_size);
 		memcpy(data_s, data, data_len);
 	}
-	
+
 	mdecrypt_generic(pm->td, data_s, data_size);
 
 	RETVAL_STRINGL(data_s, data_size, 1);
@@ -760,7 +768,7 @@ PHP_FUNCTION(mcrypt_enc_get_supported_key_sizes)
 {
 	int i, count = 0;
 	int *key_sizes;
-	
+
 	MCRYPT_GET_TD_ARG
 	array_init(return_value);
 
@@ -829,7 +837,7 @@ PHP_FUNCTION(mcrypt_enc_is_block_algorithm)
 	MCRYPT_GET_TD_ARG
 
 	if (mcrypt_enc_is_block_algorithm(pm->td) == 1) {
-		RETURN_TRUE 
+		RETURN_TRUE
 	} else {
 		RETURN_FALSE
 	}
@@ -908,7 +916,7 @@ PHP_FUNCTION(mcrypt_enc_get_modes_name)
 PHP_FUNCTION(mcrypt_module_self_test)
 {
 	MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir);
-	
+
 	if (mcrypt_module_self_test(module, dir) == 0) {
 		RETURN_TRUE;
 	} else {
@@ -922,7 +930,7 @@ PHP_FUNCTION(mcrypt_module_self_test)
 PHP_FUNCTION(mcrypt_module_is_block_algorithm_mode)
 {
 	MCRYPT_GET_MODE_DIR_ARGS(modes_dir)
-	
+
 	if (mcrypt_module_is_block_algorithm_mode(module, dir) == 1) {
 		RETURN_TRUE;
 	} else {
@@ -936,7 +944,7 @@ PHP_FUNCTION(mcrypt_module_is_block_algorithm_mode)
 PHP_FUNCTION(mcrypt_module_is_block_algorithm)
 {
 	MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir)
-	
+
 	if (mcrypt_module_is_block_algorithm(module, dir) == 1) {
 		RETURN_TRUE;
 	} else {
@@ -950,7 +958,7 @@ PHP_FUNCTION(mcrypt_module_is_block_algorithm)
 PHP_FUNCTION(mcrypt_module_is_block_mode)
 {
 	MCRYPT_GET_MODE_DIR_ARGS(modes_dir)
-	
+
 	if (mcrypt_module_is_block_mode(module, dir) == 1) {
 		RETURN_TRUE;
 	} else {
@@ -964,7 +972,7 @@ PHP_FUNCTION(mcrypt_module_is_block_mode)
 PHP_FUNCTION(mcrypt_module_get_algo_block_size)
 {
 	MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir)
-	
+
 	RETURN_LONG(mcrypt_module_get_algo_block_size(module, dir));
 }
 /* }}} */
@@ -974,7 +982,7 @@ PHP_FUNCTION(mcrypt_module_get_algo_block_size)
 PHP_FUNCTION(mcrypt_module_get_algo_key_size)
 {
 	MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir);
-	
+
 	RETURN_LONG(mcrypt_module_get_algo_key_size(module, dir));
 }
 /* }}} */
@@ -985,7 +993,7 @@ PHP_FUNCTION(mcrypt_module_get_supported_key_sizes)
 {
 	int i, count = 0;
 	int *key_sizes;
-	
+
 	MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir)
 	array_init(return_value);
 
@@ -1011,7 +1019,7 @@ PHP_FUNCTION(mcrypt_list_algorithms)
 		&lib_dir, &lib_dir_len) == FAILURE) {
 		return;
 	}
-	
+
 	array_init(return_value);
 	modules = mcrypt_list_algorithms(lib_dir, &count);
 
@@ -1058,7 +1066,7 @@ PHP_FUNCTION(mcrypt_get_key_size)
 {
 	char *cipher;
 	char *module;
-	int   cipher_len, module_len; 
+	int   cipher_len, module_len;
 	char *cipher_dir_string;
 	char *module_dir_string;
 	MCRYPT td;
@@ -1069,7 +1077,7 @@ PHP_FUNCTION(mcrypt_get_key_size)
 		&cipher, &cipher_len, &module, &module_len) == FAILURE) {
 		return;
 	}
-	
+
 	td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string);
 	if (td != MCRYPT_FAILED) {
 		RETVAL_LONG(mcrypt_enc_get_key_size(td));
@@ -1087,7 +1095,7 @@ PHP_FUNCTION(mcrypt_get_block_size)
 {
 	char *cipher;
 	char *module;
-	int   cipher_len, module_len; 
+	int   cipher_len, module_len;
 	char *cipher_dir_string;
 	char *module_dir_string;
 	MCRYPT td;
@@ -1098,7 +1106,7 @@ PHP_FUNCTION(mcrypt_get_block_size)
 		&cipher, &cipher_len, &module, &module_len) == FAILURE) {
 		return;
 	}
-	
+
 	td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string);
 	if (td != MCRYPT_FAILED) {
 		RETVAL_LONG(mcrypt_enc_get_block_size(td));
@@ -1116,7 +1124,7 @@ PHP_FUNCTION(mcrypt_get_iv_size)
 {
 	char *cipher;
 	char *module;
-	int   cipher_len, module_len; 
+	int   cipher_len, module_len;
 	char *cipher_dir_string;
 	char *module_dir_string;
 	MCRYPT td;
@@ -1127,7 +1135,7 @@ PHP_FUNCTION(mcrypt_get_iv_size)
 		&cipher, &cipher_len, &module, &module_len) == FAILURE) {
 		return;
 	}
-	
+
 	td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string);
 	if (td != MCRYPT_FAILED) {
 		RETVAL_LONG(mcrypt_enc_get_iv_size(td));
@@ -1217,7 +1225,7 @@ static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, cons
 	} else { /* dertermine smallest supported key > length of requested key */
 		use_key_length = max_key_length; /* start with max key length */
 		for (i = 0; i < count; i++) {
-			if (key_length_sizes[i] >= key_len && 
+			if (key_length_sizes[i] >= key_len &&
 				key_length_sizes[i] < use_key_length)
 			{
 				use_key_length = key_length_sizes[i];
@@ -1228,11 +1236,11 @@ static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, cons
 		memcpy(key_s, key, MIN(key_len, use_key_length));
 	}
 	mcrypt_free (key_length_sizes);
-	
+
 	/* Check IV */
 	iv_s = NULL;
 	iv_size = mcrypt_enc_get_iv_size (td);
-	
+
 	/* IV is required */
 	if (mcrypt_enc_mode_has_iv(td) == 1) {
 		if (argc == 5) {
@@ -1272,7 +1280,7 @@ static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, cons
 	} else {
 		mdecrypt_generic(td, data_s, data_size);
 	}
-	
+
 	RETVAL_STRINGL(data_s, data_size, 1);
 
 	/* freeing vars */
@@ -1294,9 +1302,9 @@ PHP_FUNCTION(mcrypt_encrypt)
 	zval **mode;
 	char *cipher, *key, *data, *iv = NULL;
 	int cipher_len, key_len, data_len, iv_len = 0;
-	
+
 	MCRYPT_GET_CRYPT_ARGS
-	
+
 	convert_to_string_ex(mode);
 
 	php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, Z_STRVAL_PP(mode), iv, iv_len, ZEND_NUM_ARGS(), MCRYPT_ENCRYPT, return_value TSRMLS_CC);
@@ -1312,7 +1320,7 @@ PHP_FUNCTION(mcrypt_decrypt)
 	int cipher_len, key_len, data_len, iv_len = 0;
 
 	MCRYPT_GET_CRYPT_ARGS
-	
+
 	convert_to_string_ex(mode);
 
 	php_mcrypt_do_crypt(cipher, key, key_len, data, data_len, Z_STRVAL_PP(mode), iv, iv_len, ZEND_NUM_ARGS(), MCRYPT_DECRYPT, return_value TSRMLS_CC);
@@ -1326,7 +1334,7 @@ PHP_FUNCTION(mcrypt_ecb)
 	zval **mode;
 	char *cipher, *key, *data, *iv = NULL;
 	int cipher_len, key_len, data_len, iv_len = 0;
-	
+
 	MCRYPT_GET_CRYPT_ARGS
 
 	convert_to_long_ex(mode);
@@ -1358,7 +1366,7 @@ PHP_FUNCTION(mcrypt_cfb)
 	zval **mode;
 	char *cipher, *key, *data, *iv = NULL;
 	int cipher_len, key_len, data_len, iv_len = 0;
-	
+
 	MCRYPT_GET_CRYPT_ARGS
 
 	convert_to_long_ex(mode);
@@ -1374,7 +1382,7 @@ PHP_FUNCTION(mcrypt_ofb)
 	zval **mode;
 	char *cipher, *key, *data, *iv = NULL;
 	int cipher_len, key_len, data_len, iv_len = 0;
-	
+
 	MCRYPT_GET_CRYPT_ARGS
 
 	convert_to_long_ex(mode);
@@ -1400,9 +1408,9 @@ PHP_FUNCTION(mcrypt_create_iv)
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create an IV with a size of less than 1 or greater than %d", INT_MAX);
 		RETURN_FALSE;
 	}
-	
+
 	iv = ecalloc(size + 1, 1);
-	
+
 	if (source == RANDOM || source == URANDOM) {
 #if PHP_WIN32
 		/* random/urandom equivalent on Windows */
path: ext/mcrypt/mcrypt.c