From 345bff91ce9aeccf4add2463c94dd4b2b256a067 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Wed, 29 Jan 2025 11:36:01 +0900 Subject: [PATCH 1/2] When freeing BCG with PHP_GSHUTDOWN_FUNCTION, it is now forcibly freed regardless of the refcount. --- ext/bcmath/bcmath.c | 4 +--- ext/bcmath/libbcmath/src/bcmath.h | 2 ++ ext/bcmath/libbcmath/src/init.c | 14 ++++++++++++++ ext/bcmath/tests/gh17398.phpt | 10 ++++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 ext/bcmath/tests/gh17398.phpt diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index f53032fabc35..30b3f583c273 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -96,9 +96,7 @@ static PHP_GINIT_FUNCTION(bcmath) /* {{{ PHP_GSHUTDOWN_FUNCTION */ static PHP_GSHUTDOWN_FUNCTION(bcmath) { - _bc_free_num_ex(&bcmath_globals->_zero_, 1); - _bc_free_num_ex(&bcmath_globals->_one_, 1); - _bc_free_num_ex(&bcmath_globals->_two_, 1); + bc_force_free_numbers(); } /* }}} */ diff --git a/ext/bcmath/libbcmath/src/bcmath.h b/ext/bcmath/libbcmath/src/bcmath.h index de51ee745711..debc7e7364ab 100644 --- a/ext/bcmath/libbcmath/src/bcmath.h +++ b/ext/bcmath/libbcmath/src/bcmath.h @@ -87,6 +87,8 @@ typedef struct bc_struct { void bc_init_numbers(void); +void bc_force_free_numbers(void); + bc_num _bc_new_num_ex(size_t length, size_t scale, bool persistent); void _bc_free_num_ex(bc_num *num, bool persistent); diff --git a/ext/bcmath/libbcmath/src/init.c b/ext/bcmath/libbcmath/src/init.c index cef55324689f..f869624b77a8 100644 --- a/ext/bcmath/libbcmath/src/init.c +++ b/ext/bcmath/libbcmath/src/init.c @@ -82,6 +82,20 @@ void bc_init_numbers(void) BCG(_two_)->n_value[0] = 2; } +static void _bc_force_free_number(bc_num *num) +{ + pefree((*num)->n_ptr, 1); + pefree(*num, 1); + *num = NULL; +} + +void bc_force_free_numbers(void) +{ + _bc_force_free_number(&BCG(_zero_)); + _bc_force_free_number(&BCG(_one_)); + _bc_force_free_number(&BCG(_two_)); +} + /* Make a copy of a number! Just increments the reference count! */ bc_num bc_copy_num(bc_num num) diff --git a/ext/bcmath/tests/gh17398.phpt b/ext/bcmath/tests/gh17398.phpt new file mode 100644 index 000000000000..6a0cda09ec76 --- /dev/null +++ b/ext/bcmath/tests/gh17398.phpt @@ -0,0 +1,10 @@ +--TEST-- +GH-17398 (bcmul memory leak) +--EXTENSIONS-- +bcmath +--FILE-- + +--EXPECTF-- +Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d From f8a14df18b80c8e37163f7580c3e1c8462e29db9 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Wed, 29 Jan 2025 17:34:49 +0900 Subject: [PATCH 2/2] Address comments --- ext/bcmath/bcmath.c | 4 +++- ext/bcmath/libbcmath/src/bcmath.h | 2 +- ext/bcmath/libbcmath/src/init.c | 9 +-------- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index 30b3f583c273..bc78faa7b399 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -96,7 +96,9 @@ static PHP_GINIT_FUNCTION(bcmath) /* {{{ PHP_GSHUTDOWN_FUNCTION */ static PHP_GSHUTDOWN_FUNCTION(bcmath) { - bc_force_free_numbers(); + bc_force_free_number(&bcmath_globals->_zero_); + bc_force_free_number(&bcmath_globals->_one_); + bc_force_free_number(&bcmath_globals->_two_); } /* }}} */ diff --git a/ext/bcmath/libbcmath/src/bcmath.h b/ext/bcmath/libbcmath/src/bcmath.h index debc7e7364ab..0ec86f208619 100644 --- a/ext/bcmath/libbcmath/src/bcmath.h +++ b/ext/bcmath/libbcmath/src/bcmath.h @@ -87,7 +87,7 @@ typedef struct bc_struct { void bc_init_numbers(void); -void bc_force_free_numbers(void); +void bc_force_free_number(bc_num *num); bc_num _bc_new_num_ex(size_t length, size_t scale, bool persistent); diff --git a/ext/bcmath/libbcmath/src/init.c b/ext/bcmath/libbcmath/src/init.c index f869624b77a8..6bb538ef1cb1 100644 --- a/ext/bcmath/libbcmath/src/init.c +++ b/ext/bcmath/libbcmath/src/init.c @@ -82,20 +82,13 @@ void bc_init_numbers(void) BCG(_two_)->n_value[0] = 2; } -static void _bc_force_free_number(bc_num *num) +void bc_force_free_number(bc_num *num) { pefree((*num)->n_ptr, 1); pefree(*num, 1); *num = NULL; } -void bc_force_free_numbers(void) -{ - _bc_force_free_number(&BCG(_zero_)); - _bc_force_free_number(&BCG(_one_)); - _bc_force_free_number(&BCG(_two_)); -} - /* Make a copy of a number! Just increments the reference count! */ bc_num bc_copy_num(bc_num num)