From 89358bcb79812ae7232aad67c60b4bac1916a0eb Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 5 Dec 2024 21:13:55 +0100 Subject: [PATCH] Fix GH-17047: UAF on iconv filter failure The first while loop sets the bucket variable, and this is freed in out_failure. However, when the second "goto out_failure" is triggered then bucket still refers to the bucket from the first while loop, causing a UAF. Fix this by separating the error paths. --- ext/iconv/iconv.c | 11 +++-------- ext/iconv/tests/gh17047.phpt | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 8 deletions(-) create mode 100644 ext/iconv/tests/gh17047.phpt diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c index 75f78dd174238..8ac3bc9b3c480 100644 --- a/ext/iconv/iconv.c +++ b/ext/iconv/iconv.c @@ -2536,7 +2536,8 @@ static php_stream_filter_status_t php_iconv_stream_filter_do_filter( if (php_iconv_stream_filter_append_bucket(self, stream, filter, buckets_out, bucket->buf, bucket->buflen, &consumed, php_stream_is_persistent(stream)) != SUCCESS) { - goto out_failure; + php_stream_bucket_delref(bucket); + return PSFS_ERR_FATAL; } php_stream_bucket_delref(bucket); @@ -2546,7 +2547,7 @@ static php_stream_filter_status_t php_iconv_stream_filter_do_filter( if (php_iconv_stream_filter_append_bucket(self, stream, filter, buckets_out, NULL, 0, &consumed, php_stream_is_persistent(stream)) != SUCCESS) { - goto out_failure; + return PSFS_ERR_FATAL; } } @@ -2555,12 +2556,6 @@ static php_stream_filter_status_t php_iconv_stream_filter_do_filter( } return PSFS_PASS_ON; - -out_failure: - if (bucket != NULL) { - php_stream_bucket_delref(bucket); - } - return PSFS_ERR_FATAL; } /* }}} */ diff --git a/ext/iconv/tests/gh17047.phpt b/ext/iconv/tests/gh17047.phpt new file mode 100644 index 0000000000000..a0307ddbe5553 --- /dev/null +++ b/ext/iconv/tests/gh17047.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-17047 (UAF on iconv filter failure) +--EXTENSIONS-- +iconv +--FILE-- + +--EXPECTF-- +Warning: stream_get_contents(): iconv stream filter ("UTF-16BE"=>"UTF-16BE"): invalid multibyte sequence in %s on line %d +string(0) ""