Skip to content

Commit 6c5211a

Browse files
committed
Fix bug #72455: Heap Overflow due to integer overflows
1 parent f6aef68 commit 6c5211a

File tree

1 file changed

+50
-42
lines changed

1 file changed

+50
-42
lines changed

ext/mcrypt/mcrypt.c

Lines changed: 50 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545
static int le_mcrypt;
4646

47-
typedef struct _php_mcrypt {
47+
typedef struct _php_mcrypt {
4848
MCRYPT td;
4949
zend_bool init;
5050
} php_mcrypt;
@@ -292,7 +292,7 @@ ZEND_DECLARE_MODULE_GLOBALS(mcrypt)
292292

293293
zend_module_entry mcrypt_module_entry = {
294294
STANDARD_MODULE_HEADER,
295-
"mcrypt",
295+
"mcrypt",
296296
mcrypt_functions,
297297
PHP_MINIT(mcrypt), PHP_MSHUTDOWN(mcrypt),
298298
NULL, NULL,
@@ -376,7 +376,7 @@ ZEND_GET_MODULE(mcrypt)
376376
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &mcryptind) == FAILURE) { \
377377
return; \
378378
} \
379-
ZEND_FETCH_RESOURCE (pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt);
379+
ZEND_FETCH_RESOURCE (pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt);
380380

381381
#define MCRYPT_GET_MODE_DIR_ARGS(DIRECTORY) \
382382
char *dir = NULL; \
@@ -407,7 +407,7 @@ PHP_INI_END()
407407
static void php_mcrypt_module_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
408408
{
409409
php_mcrypt *pm = (php_mcrypt *) rsrc->ptr;
410-
if (pm) {
410+
if (pm) {
411411
mcrypt_generic_deinit(pm->td);
412412
mcrypt_module_close(pm->td);
413413
efree(pm);
@@ -548,7 +548,7 @@ PHP_MINFO_FUNCTION(mcrypt) /* {{{ */
548548
smart_str_free(&tmp1);
549549
smart_str_free(&tmp2);
550550
php_info_print_table_end();
551-
551+
552552
DISPLAY_INI_ENTRIES();
553553
}
554554
/* }}} */
@@ -563,17 +563,17 @@ PHP_FUNCTION(mcrypt_module_open)
563563
int mode_len, mode_dir_len;
564564
MCRYPT td;
565565
php_mcrypt *pm;
566-
566+
567567
if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, "ssss",
568568
&cipher, &cipher_len, &cipher_dir, &cipher_dir_len,
569569
&mode, &mode_len, &mode_dir, &mode_dir_len)) {
570570
return;
571571
}
572-
572+
573573
td = mcrypt_module_open (
574574
cipher,
575575
cipher_dir_len > 0 ? cipher_dir : MCG(algorithms_dir),
576-
mode,
576+
mode,
577577
mode_dir_len > 0 ? mode_dir : MCG(modes_dir)
578578
);
579579

@@ -600,7 +600,7 @@ PHP_FUNCTION(mcrypt_generic_init)
600600
int max_key_size, key_size, iv_size;
601601
php_mcrypt *pm;
602602
int result = 0;
603-
603+
604604
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &mcryptind, &key, &key_len, &iv, &iv_len) == FAILURE) {
605605
return;
606606
}
@@ -679,7 +679,7 @@ PHP_FUNCTION(mcrypt_generic)
679679
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) {
680680
return;
681681
}
682-
682+
683683
ZEND_FETCH_RESOURCE(pm, php_mcrypt *, &mcryptind, -1, "MCrypt", le_mcrypt);
684684
PHP_MCRYPT_INIT_CHECK
685685

@@ -692,6 +692,10 @@ PHP_FUNCTION(mcrypt_generic)
692692
if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */
693693
block_size = mcrypt_enc_get_block_size(pm->td);
694694
data_size = (((data_len - 1) / block_size) + 1) * block_size;
695+
if (data_size <= 0) {
696+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Integer overflow in data size");
697+
RETURN_FALSE;
698+
}
695699
data_s = emalloc(data_size + 1);
696700
memset(data_s, 0, data_size);
697701
memcpy(data_s, data, data_len);
@@ -701,7 +705,7 @@ PHP_FUNCTION(mcrypt_generic)
701705
memset(data_s, 0, data_size);
702706
memcpy(data_s, data, data_len);
703707
}
704-
708+
705709
mcrypt_generic(pm->td, data_s, data_size);
706710
data_s[data_size] = '\0';
707711

@@ -720,11 +724,11 @@ PHP_FUNCTION(mdecrypt_generic)
720724
php_mcrypt *pm;
721725
char* data_s;
722726
int block_size, data_size;
723-
727+
724728
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &mcryptind, &data, &data_len) == FAILURE) {
725729
return;
726730
}
727-
731+
728732
ZEND_FETCH_RESOURCE(pm, php_mcrypt * , &mcryptind, -1, "MCrypt", le_mcrypt);
729733
PHP_MCRYPT_INIT_CHECK
730734

@@ -737,6 +741,10 @@ PHP_FUNCTION(mdecrypt_generic)
737741
if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */
738742
block_size = mcrypt_enc_get_block_size(pm->td);
739743
data_size = (((data_len - 1) / block_size) + 1) * block_size;
744+
if (data_size <= 0) {
745+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Integer overflow in data size");
746+
RETURN_FALSE;
747+
}
740748
data_s = emalloc(data_size + 1);
741749
memset(data_s, 0, data_size);
742750
memcpy(data_s, data, data_len);
@@ -746,7 +754,7 @@ PHP_FUNCTION(mdecrypt_generic)
746754
memset(data_s, 0, data_size);
747755
memcpy(data_s, data, data_len);
748756
}
749-
757+
750758
mdecrypt_generic(pm->td, data_s, data_size);
751759

752760
RETVAL_STRINGL(data_s, data_size, 1);
@@ -760,7 +768,7 @@ PHP_FUNCTION(mcrypt_enc_get_supported_key_sizes)
760768
{
761769
int i, count = 0;
762770
int *key_sizes;
763-
771+
764772
MCRYPT_GET_TD_ARG
765773
array_init(return_value);
766774

@@ -829,7 +837,7 @@ PHP_FUNCTION(mcrypt_enc_is_block_algorithm)
829837
MCRYPT_GET_TD_ARG
830838

831839
if (mcrypt_enc_is_block_algorithm(pm->td) == 1) {
832-
RETURN_TRUE
840+
RETURN_TRUE
833841
} else {
834842
RETURN_FALSE
835843
}
@@ -908,7 +916,7 @@ PHP_FUNCTION(mcrypt_enc_get_modes_name)
908916
PHP_FUNCTION(mcrypt_module_self_test)
909917
{
910918
MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir);
911-
919+
912920
if (mcrypt_module_self_test(module, dir) == 0) {
913921
RETURN_TRUE;
914922
} else {
@@ -922,7 +930,7 @@ PHP_FUNCTION(mcrypt_module_self_test)
922930
PHP_FUNCTION(mcrypt_module_is_block_algorithm_mode)
923931
{
924932
MCRYPT_GET_MODE_DIR_ARGS(modes_dir)
925-
933+
926934
if (mcrypt_module_is_block_algorithm_mode(module, dir) == 1) {
927935
RETURN_TRUE;
928936
} else {
@@ -936,7 +944,7 @@ PHP_FUNCTION(mcrypt_module_is_block_algorithm_mode)
936944
PHP_FUNCTION(mcrypt_module_is_block_algorithm)
937945
{
938946
MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir)
939-
947+
940948
if (mcrypt_module_is_block_algorithm(module, dir) == 1) {
941949
RETURN_TRUE;
942950
} else {
@@ -950,7 +958,7 @@ PHP_FUNCTION(mcrypt_module_is_block_algorithm)
950958
PHP_FUNCTION(mcrypt_module_is_block_mode)
951959
{
952960
MCRYPT_GET_MODE_DIR_ARGS(modes_dir)
953-
961+
954962
if (mcrypt_module_is_block_mode(module, dir) == 1) {
955963
RETURN_TRUE;
956964
} else {
@@ -964,7 +972,7 @@ PHP_FUNCTION(mcrypt_module_is_block_mode)
964972
PHP_FUNCTION(mcrypt_module_get_algo_block_size)
965973
{
966974
MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir)
967-
975+
968976
RETURN_LONG(mcrypt_module_get_algo_block_size(module, dir));
969977
}
970978
/* }}} */
@@ -974,7 +982,7 @@ PHP_FUNCTION(mcrypt_module_get_algo_block_size)
974982
PHP_FUNCTION(mcrypt_module_get_algo_key_size)
975983
{
976984
MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir);
977-
985+
978986
RETURN_LONG(mcrypt_module_get_algo_key_size(module, dir));
979987
}
980988
/* }}} */
@@ -985,7 +993,7 @@ PHP_FUNCTION(mcrypt_module_get_supported_key_sizes)
985993
{
986994
int i, count = 0;
987995
int *key_sizes;
988-
996+
989997
MCRYPT_GET_MODE_DIR_ARGS(algorithms_dir)
990998
array_init(return_value);
991999

@@ -1011,7 +1019,7 @@ PHP_FUNCTION(mcrypt_list_algorithms)
10111019
&lib_dir, &lib_dir_len) == FAILURE) {
10121020
return;
10131021
}
1014-
1022+
10151023
array_init(return_value);
10161024
modules = mcrypt_list_algorithms(lib_dir, &count);
10171025

@@ -1058,7 +1066,7 @@ PHP_FUNCTION(mcrypt_get_key_size)
10581066
{
10591067
char *cipher;
10601068
char *module;
1061-
int cipher_len, module_len;
1069+
int cipher_len, module_len;
10621070
char *cipher_dir_string;
10631071
char *module_dir_string;
10641072
MCRYPT td;
@@ -1069,7 +1077,7 @@ PHP_FUNCTION(mcrypt_get_key_size)
10691077
&cipher, &cipher_len, &module, &module_len) == FAILURE) {
10701078
return;
10711079
}
1072-
1080+
10731081
td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string);
10741082
if (td != MCRYPT_FAILED) {
10751083
RETVAL_LONG(mcrypt_enc_get_key_size(td));
@@ -1087,7 +1095,7 @@ PHP_FUNCTION(mcrypt_get_block_size)
10871095
{
10881096
char *cipher;
10891097
char *module;
1090-
int cipher_len, module_len;
1098+
int cipher_len, module_len;
10911099
char *cipher_dir_string;
10921100
char *module_dir_string;
10931101
MCRYPT td;
@@ -1098,7 +1106,7 @@ PHP_FUNCTION(mcrypt_get_block_size)
10981106
&cipher, &cipher_len, &module, &module_len) == FAILURE) {
10991107
return;
11001108
}
1101-
1109+
11021110
td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string);
11031111
if (td != MCRYPT_FAILED) {
11041112
RETVAL_LONG(mcrypt_enc_get_block_size(td));
@@ -1116,7 +1124,7 @@ PHP_FUNCTION(mcrypt_get_iv_size)
11161124
{
11171125
char *cipher;
11181126
char *module;
1119-
int cipher_len, module_len;
1127+
int cipher_len, module_len;
11201128
char *cipher_dir_string;
11211129
char *module_dir_string;
11221130
MCRYPT td;
@@ -1127,7 +1135,7 @@ PHP_FUNCTION(mcrypt_get_iv_size)
11271135
&cipher, &cipher_len, &module, &module_len) == FAILURE) {
11281136
return;
11291137
}
1130-
1138+
11311139
td = mcrypt_module_open(cipher, cipher_dir_string, module, module_dir_string);
11321140
if (td != MCRYPT_FAILED) {
11331141
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
12171225
} else { /* dertermine smallest supported key > length of requested key */
12181226
use_key_length = max_key_length; /* start with max key length */
12191227
for (i = 0; i < count; i++) {
1220-
if (key_length_sizes[i] >= key_len &&
1228+
if (key_length_sizes[i] >= key_len &&
12211229
key_length_sizes[i] < use_key_length)
12221230
{
12231231
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
12281236
memcpy(key_s, key, MIN(key_len, use_key_length));
12291237
}
12301238
mcrypt_free (key_length_sizes);
1231-
1239+
12321240
/* Check IV */
12331241
iv_s = NULL;
12341242
iv_size = mcrypt_enc_get_iv_size (td);
1235-
1243+
12361244
/* IV is required */
12371245
if (mcrypt_enc_mode_has_iv(td) == 1) {
12381246
if (argc == 5) {
@@ -1272,7 +1280,7 @@ static void php_mcrypt_do_crypt(char* cipher, const char *key, int key_len, cons
12721280
} else {
12731281
mdecrypt_generic(td, data_s, data_size);
12741282
}
1275-
1283+
12761284
RETVAL_STRINGL(data_s, data_size, 1);
12771285

12781286
/* freeing vars */
@@ -1294,9 +1302,9 @@ PHP_FUNCTION(mcrypt_encrypt)
12941302
zval **mode;
12951303
char *cipher, *key, *data, *iv = NULL;
12961304
int cipher_len, key_len, data_len, iv_len = 0;
1297-
1305+
12981306
MCRYPT_GET_CRYPT_ARGS
1299-
1307+
13001308
convert_to_string_ex(mode);
13011309

13021310
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)
13121320
int cipher_len, key_len, data_len, iv_len = 0;
13131321

13141322
MCRYPT_GET_CRYPT_ARGS
1315-
1323+
13161324
convert_to_string_ex(mode);
13171325

13181326
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)
13261334
zval **mode;
13271335
char *cipher, *key, *data, *iv = NULL;
13281336
int cipher_len, key_len, data_len, iv_len = 0;
1329-
1337+
13301338
MCRYPT_GET_CRYPT_ARGS
13311339

13321340
convert_to_long_ex(mode);
@@ -1358,7 +1366,7 @@ PHP_FUNCTION(mcrypt_cfb)
13581366
zval **mode;
13591367
char *cipher, *key, *data, *iv = NULL;
13601368
int cipher_len, key_len, data_len, iv_len = 0;
1361-
1369+
13621370
MCRYPT_GET_CRYPT_ARGS
13631371

13641372
convert_to_long_ex(mode);
@@ -1374,7 +1382,7 @@ PHP_FUNCTION(mcrypt_ofb)
13741382
zval **mode;
13751383
char *cipher, *key, *data, *iv = NULL;
13761384
int cipher_len, key_len, data_len, iv_len = 0;
1377-
1385+
13781386
MCRYPT_GET_CRYPT_ARGS
13791387

13801388
convert_to_long_ex(mode);
@@ -1400,9 +1408,9 @@ PHP_FUNCTION(mcrypt_create_iv)
14001408
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);
14011409
RETURN_FALSE;
14021410
}
1403-
1411+
14041412
iv = ecalloc(size + 1, 1);
1405-
1413+
14061414
if (source == RANDOM || source == URANDOM) {
14071415
#if PHP_WIN32
14081416
/* random/urandom equivalent on Windows */

0 commit comments

Comments
 (0)