From: Máté Kocsis Date: Wed, 17 Jun 2020 14:45:57 +0000 (+0200) Subject: Convert resources to objects in ext/zlib X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=314eedbc35116d61e97978f5fc822dfecd14053d;p=php Convert resources to objects in ext/zlib Closes GH-5680 --- diff --git a/UPGRADING b/UPGRADING index 794b91f943..b7670f813b 100644 --- a/UPGRADING +++ b/UPGRADING @@ -440,7 +440,7 @@ PHP 8.0 UPGRADE NOTES - Sysvmsg: . msg_get_queue() will now return an SysvMessageQueue object rather than a - resource. Return value checks using is_resource() should be replaced with + resource. Return value checks using is_resource() should be replaced with checks for `false`. - Sysvsem: @@ -474,6 +474,12 @@ PHP 8.0 UPGRADE NOTES - Zlib: . gzgetss() has been removed. + . inflate_init() will now return an InflateContext object rather than a + resource. Return value checks using is_resource() should be replaced with + checks for `false`. + . deflate_init() will now return a DeflateContext object rather than a + resource. Return value checks using is_resource() should be replaced with + checks for `false`. ======================================== 2. New Features diff --git a/ext/zlib/php_zlib.h b/ext/zlib/php_zlib.h index b8f25015ae..6c43625217 100644 --- a/ext/zlib/php_zlib.h +++ b/ext/zlib/php_zlib.h @@ -47,6 +47,7 @@ typedef struct _php_zlib_context { int status; size_t inflateDictlen; php_zlib_buffer buffer; + zend_object std; } php_zlib_context; ZEND_BEGIN_MODULE_GLOBALS(zlib) diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index 11753b0f83..aa3be3a513 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -29,12 +29,13 @@ #include "ext/standard/php_string.h" #include "php_zlib.h" #include "zlib_arginfo.h" +#include "Zend/zend_interfaces.h" /* * zlib include files can define the following preprocessor defines which rename * the corresponding PHP functions to gzopen64, gzseek64 and gztell64 and thereby * breaking some software, most notably PEAR's Archive_Tar, which halts execution - * without error message on gzip compressed archivesa. + * without error message on gzip compressed archives. * * This only seems to happen on 32bit systems with large file support. */ @@ -42,45 +43,94 @@ #undef gzseek #undef gztell -int le_deflate; -#define le_deflate_name "zlib deflate" -int le_inflate; -#define le_inflate_name "zlib inflate" - ZEND_DECLARE_MODULE_GLOBALS(zlib) -/* {{{ Memory management wrappers */ +/* InflateContext class */ -static voidpf php_zlib_alloc(voidpf opaque, uInt items, uInt size) -{ - return (voidpf)safe_emalloc(items, size, 0); +zend_class_entry *inflate_context_ce; +static zend_object_handlers inflate_context_object_handlers; + +static inline php_zlib_context *inflate_context_from_obj(zend_object *obj) { + return (php_zlib_context *)((char *)(obj) - XtOffsetOf(php_zlib_context, std)); } -static void php_zlib_free(voidpf opaque, voidpf address) +#define Z_INFLATE_CONTEXT_P(zv) inflate_context_from_obj(Z_OBJ_P(zv)) + +static zend_object *inflate_context_create_object(zend_class_entry *class_type) { + php_zlib_context *intern = zend_object_alloc(sizeof(php_zlib_context), class_type); + + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &inflate_context_object_handlers; + + return &intern->std; +} + +static zend_function *inflate_context_get_constructor(zend_object *object) { + zend_throw_error(NULL, "Cannot directly construct InflateContext, use inflate_init() instead"); + return NULL; +} + +static void inflate_context_free_obj(zend_object *object) { - efree((void*)address); + php_zlib_context *intern = inflate_context_from_obj(object); + + if (intern->inflateDict) { + efree(intern->inflateDict); + } + inflateEnd(&intern->Z); + + zend_object_std_dtor(&intern->std); } /* }}} */ -/* {{{ Incremental deflate/inflate resource destructors */ +/* DeflateContext class */ + +zend_class_entry *deflate_context_ce; +static zend_object_handlers deflate_context_object_handlers; + +static inline php_zlib_context *deflate_context_from_obj(zend_object *obj) { + return (php_zlib_context *)((char *)(obj) - XtOffsetOf(php_zlib_context, std)); +} + +#define Z_DEFLATE_CONTEXT_P(zv) deflate_context_from_obj(Z_OBJ_P(zv)) + +static zend_object *deflate_context_create_object(zend_class_entry *class_type) { + php_zlib_context *intern = zend_object_alloc(sizeof(php_zlib_context), class_type); + + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &deflate_context_object_handlers; + + return &intern->std; +} -void deflate_rsrc_dtor(zend_resource *res) +static zend_function *deflate_context_get_constructor(zend_object *object) { + zend_throw_error(NULL, "Cannot directly construct DeflateContext, use deflate_init() instead"); + return NULL; +} + +static void deflate_context_free_obj(zend_object *object) { - z_stream *ctx = zend_fetch_resource(res, le_deflate_name, le_deflate); - deflateEnd(ctx); - efree(ctx); + php_zlib_context *intern = deflate_context_from_obj(object); + + deflateEnd(&intern->Z); + + zend_object_std_dtor(&intern->std); } +/* }}} */ + +/* {{{ Memory management wrappers */ -void inflate_rsrc_dtor(zend_resource *res) +static voidpf php_zlib_alloc(voidpf opaque, uInt items, uInt size) { - z_stream *ctx = zend_fetch_resource(res, le_inflate_name, le_inflate); - if (((php_zlib_context *) ctx)->inflateDict) { - efree(((php_zlib_context *) ctx)->inflateDict); - } - inflateEnd(ctx); - efree(ctx); + return (voidpf)safe_emalloc(items, size, 0); } +static void php_zlib_free(voidpf opaque, voidpf address) +{ + efree((void*)address); +} /* }}} */ /* {{{ php_zlib_output_conflict_check() */ @@ -826,11 +876,11 @@ static zend_bool zlib_create_dictionary_string(HashTable *options, char **dict, return 1; } -/* {{{ proto resource inflate_init(int encoding) +/* {{{ proto InflateContext inflate_init(int encoding) Initialize an incremental inflate context with the specified encoding */ PHP_FUNCTION(inflate_init) { - z_stream *ctx; + php_zlib_context *ctx; zend_long encoding, window = 15; char *dict = NULL; size_t dictlen = 0; @@ -850,7 +900,7 @@ PHP_FUNCTION(inflate_init) } if (!zlib_create_dictionary_string(options, &dict, &dictlen)) { - RETURN_FALSE; + RETURN_THROWS(); } switch (encoding) { @@ -863,12 +913,14 @@ PHP_FUNCTION(inflate_init) RETURN_THROWS(); } - ctx = ecalloc(1, sizeof(php_zlib_context)); - ctx->zalloc = php_zlib_alloc; - ctx->zfree = php_zlib_free; - ((php_zlib_context *) ctx)->inflateDict = dict; - ((php_zlib_context *) ctx)->inflateDictlen = dictlen; - ((php_zlib_context *) ctx)->status = Z_OK; + object_init_ex(return_value, inflate_context_ce); + ctx = Z_INFLATE_CONTEXT_P(return_value); + + ctx->Z.zalloc = php_zlib_alloc; + ctx->Z.zfree = php_zlib_free; + ctx->inflateDict = dict; + ctx->inflateDictlen = dictlen; + ctx->status = Z_OK; if (encoding < 0) { encoding += 15 - window; @@ -876,31 +928,29 @@ PHP_FUNCTION(inflate_init) encoding -= 15 - window; } - if (Z_OK == inflateInit2(ctx, encoding)) { - if (encoding == PHP_ZLIB_ENCODING_RAW && dictlen > 0) { - php_zlib_context *php_ctx = (php_zlib_context *) ctx; - switch (inflateSetDictionary(ctx, (Bytef *) php_ctx->inflateDict, php_ctx->inflateDictlen)) { - case Z_OK: - efree(php_ctx->inflateDict); - php_ctx->inflateDict = NULL; - break; - case Z_DATA_ERROR: - php_error_docref(NULL, E_WARNING, "Dictionary does not match expected dictionary (incorrect adler32 hash)"); - efree(php_ctx->inflateDict); - php_ctx->inflateDict = NULL; - EMPTY_SWITCH_DEFAULT_CASE() - } - } - RETURN_RES(zend_register_resource(ctx, le_inflate)); - } else { - efree(ctx); + if (inflateInit2(&ctx->Z, encoding) != Z_OK) { + zval_ptr_dtor(return_value); php_error_docref(NULL, E_WARNING, "Failed allocating zlib.inflate context"); RETURN_FALSE; } + + if (encoding == PHP_ZLIB_ENCODING_RAW && dictlen > 0) { + switch (inflateSetDictionary(&ctx->Z, (Bytef *) ctx->inflateDict, ctx->inflateDictlen)) { + case Z_OK: + efree(ctx->inflateDict); + ctx->inflateDict = NULL; + break; + case Z_DATA_ERROR: + php_error_docref(NULL, E_WARNING, "Dictionary does not match expected dictionary (incorrect adler32 hash)"); + efree(ctx->inflateDict); + ctx->inflateDict = NULL; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } /* }}} */ -/* {{{ proto string inflate_add(resource context, string encoded_data[, int flush_mode = ZLIB_SYNC_FLUSH]) +/* {{{ proto string inflate_add(InflateContext context, string encoded_data[, int flush_mode = ZLIB_SYNC_FLUSH]) Incrementally inflate encoded data in the specified context */ PHP_FUNCTION(inflate_add) { @@ -908,17 +958,15 @@ PHP_FUNCTION(inflate_add) char *in_buf; size_t in_len, buffer_used = 0, CHUNK_SIZE = 8192; zval *res; - z_stream *ctx; + php_zlib_context *ctx; zend_long flush_type = Z_SYNC_FLUSH; int status; - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "rs|l", &res, &in_buf, &in_len, &flush_type)) { + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "Os|l", &res, inflate_context_ce, &in_buf, &in_len, &flush_type)) { RETURN_THROWS(); } - if ((ctx = zend_fetch_resource(Z_RES_P(res), le_inflate_name, le_inflate)) == NULL) { - RETURN_THROWS(); - } + ctx = Z_INFLATE_CONTEXT_P(res); switch (flush_type) { case Z_NO_FLUSH: @@ -930,16 +978,15 @@ PHP_FUNCTION(inflate_add) break; default: - zend_value_error( - "Flush mode must be ZLIB_NO_FLUSH, ZLIB_PARTIAL_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_BLOCK or ZLIB_FINISH"); + zend_argument_value_error(3, "must be one of ZLIB_NO_FLUSH, ZLIB_PARTIAL_FLUSH, ZLIB_SYNC_FLUSH, ZLIB_FULL_FLUSH, ZLIB_BLOCK, or ZLIB_FINISH"); RETURN_THROWS(); } /* Lazy-resetting the zlib stream so ctx->total_in remains available until the next inflate_add() call. */ - if (((php_zlib_context *) ctx)->status == Z_STREAM_END) + if (ctx->status == Z_STREAM_END) { - ((php_zlib_context *) ctx)->status = Z_OK; - inflateReset(ctx); + ctx->status = Z_OK; + inflateReset(&ctx->Z); } if (in_len <= 0 && flush_type != Z_FINISH) { @@ -947,24 +994,24 @@ PHP_FUNCTION(inflate_add) } out = zend_string_alloc((in_len > CHUNK_SIZE) ? in_len : CHUNK_SIZE, 0); - ctx->next_in = (Bytef *) in_buf; - ctx->next_out = (Bytef *) ZSTR_VAL(out); - ctx->avail_in = in_len; - ctx->avail_out = ZSTR_LEN(out); + ctx->Z.next_in = (Bytef *) in_buf; + ctx->Z.next_out = (Bytef *) ZSTR_VAL(out); + ctx->Z.avail_in = in_len; + ctx->Z.avail_out = ZSTR_LEN(out); do { - status = inflate(ctx, flush_type); - buffer_used = ZSTR_LEN(out) - ctx->avail_out; + status = inflate(&ctx->Z, flush_type); + buffer_used = ZSTR_LEN(out) - ctx->Z.avail_out; - ((php_zlib_context *) ctx)->status = status; /* Save status for exposing to userspace */ + ctx->status = status; /* Save status for exposing to userspace */ switch (status) { case Z_OK: - if (ctx->avail_out == 0) { + if (ctx->Z.avail_out == 0) { /* more output buffer space needed; realloc and try again */ out = zend_string_realloc(out, ZSTR_LEN(out) + CHUNK_SIZE, 0); - ctx->avail_out = CHUNK_SIZE; - ctx->next_out = (Bytef *) ZSTR_VAL(out) + buffer_used; + ctx->Z.avail_out = CHUNK_SIZE; + ctx->Z.next_out = (Bytef *) ZSTR_VAL(out) + buffer_used; break; } else { goto complete; @@ -972,29 +1019,28 @@ PHP_FUNCTION(inflate_add) case Z_STREAM_END: goto complete; case Z_BUF_ERROR: - if (flush_type == Z_FINISH && ctx->avail_out == 0) { + if (flush_type == Z_FINISH && ctx->Z.avail_out == 0) { /* more output buffer space needed; realloc and try again */ out = zend_string_realloc(out, ZSTR_LEN(out) + CHUNK_SIZE, 0); - ctx->avail_out = CHUNK_SIZE; - ctx->next_out = (Bytef *) ZSTR_VAL(out) + buffer_used; + ctx->Z.avail_out = CHUNK_SIZE; + ctx->Z.next_out = (Bytef *) ZSTR_VAL(out) + buffer_used; break; } else { /* No more input data; we're finished */ goto complete; } case Z_NEED_DICT: - if (((php_zlib_context *) ctx)->inflateDict) { - php_zlib_context *php_ctx = (php_zlib_context *) ctx; - switch (inflateSetDictionary(ctx, (Bytef *) php_ctx->inflateDict, php_ctx->inflateDictlen)) { + if (ctx->inflateDict) { + switch (inflateSetDictionary(&ctx->Z, (Bytef *) ctx->inflateDict, ctx->inflateDictlen)) { case Z_OK: - efree(php_ctx->inflateDict); - php_ctx->inflateDict = NULL; + efree(ctx->inflateDict); + ctx->inflateDict = NULL; break; case Z_DATA_ERROR: - php_error_docref(NULL, E_WARNING, "Dictionary does not match expected dictionary (incorrect adler32 hash)"); - efree(php_ctx->inflateDict); + efree(ctx->inflateDict); + ctx->inflateDict = NULL; zend_string_release_ex(out, 0); - php_ctx->inflateDict = NULL; + php_error_docref(NULL, E_WARNING, "Dictionary does not match expected dictionary (incorrect adler32 hash)"); RETURN_FALSE; EMPTY_SWITCH_DEFAULT_CASE() } @@ -1010,11 +1056,10 @@ PHP_FUNCTION(inflate_add) } } while (1); - complete: { - out = zend_string_realloc(out, buffer_used, 0); - ZSTR_VAL(out)[buffer_used] = 0; - RETURN_STR(out); - } +complete: + out = zend_string_realloc(out, buffer_used, 0); + ZSTR_VAL(out)[buffer_used] = 0; + RETURN_STR(out); } /* }}} */ @@ -1023,18 +1068,15 @@ PHP_FUNCTION(inflate_add) PHP_FUNCTION(inflate_get_status) { zval *res; - z_stream *ctx; + php_zlib_context *ctx; - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "r", &res)) - { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &res, inflate_context_ce) != SUCCESS) { RETURN_THROWS(); } - if ((ctx = zend_fetch_resource(Z_RES_P(res), le_inflate_name, le_inflate)) == NULL) { - RETURN_THROWS(); - } + ctx = Z_INFLATE_CONTEXT_P(res); - RETURN_LONG(((php_zlib_context *) ctx)->status); + RETURN_LONG(ctx->status); } /* }}} */ @@ -1043,26 +1085,23 @@ PHP_FUNCTION(inflate_get_status) PHP_FUNCTION(inflate_get_read_len) { zval *res; - z_stream *ctx; + php_zlib_context *ctx; - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "r", &res)) - { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &res, inflate_context_ce) != SUCCESS) { RETURN_THROWS(); } - if ((ctx = zend_fetch_resource(Z_RES_P(res), le_inflate_name, le_inflate)) == NULL) { - RETURN_THROWS(); - } + ctx = Z_INFLATE_CONTEXT_P(res); - RETURN_LONG(ctx->total_in); + RETURN_LONG(ctx->Z.total_in); } /* }}} */ -/* {{{ proto resource deflate_init(int encoding[, array options]) +/* {{{ proto DeflateContext deflate_init(int encoding[, array options]) Initialize an incremental deflate context using the specified encoding */ PHP_FUNCTION(deflate_init) { - z_stream *ctx; + php_zlib_context *ctx; zend_long encoding, level = -1, memory = 8, window = 15, strategy = Z_DEFAULT_STRATEGY; char *dict = NULL; size_t dictlen = 0; @@ -1113,7 +1152,7 @@ PHP_FUNCTION(deflate_init) } if (!zlib_create_dictionary_string(options, &dict, &dictlen)) { - RETURN_FALSE; + RETURN_THROWS(); } switch (encoding) { @@ -1126,9 +1165,11 @@ PHP_FUNCTION(deflate_init) RETURN_THROWS(); } - ctx = ecalloc(1, sizeof(php_zlib_context)); - ctx->zalloc = php_zlib_alloc; - ctx->zfree = php_zlib_free; + object_init_ex(return_value, deflate_context_ce); + ctx = Z_DEFLATE_CONTEXT_P(return_value); + + ctx->Z.zalloc = php_zlib_alloc; + ctx->Z.zfree = php_zlib_free; if (encoding < 0) { encoding += 15 - window; @@ -1136,23 +1177,21 @@ PHP_FUNCTION(deflate_init) encoding -= 15 - window; } - if (Z_OK == deflateInit2(ctx, level, Z_DEFLATED, encoding, memory, strategy)) { - if (dict) { - int success = deflateSetDictionary(ctx, (Bytef *) dict, dictlen); - ZEND_ASSERT(success == Z_OK); - efree(dict); - } - - RETURN_RES(zend_register_resource(ctx, le_deflate)); - } else { - efree(ctx); + if (deflateInit2(&ctx->Z, level, Z_DEFLATED, encoding, memory, strategy) != Z_OK) { + zval_ptr_dtor(return_value); php_error_docref(NULL, E_WARNING, "Failed allocating zlib.deflate context"); RETURN_FALSE; } + + if (dict) { + int success = deflateSetDictionary(&ctx->Z, (Bytef *) dict, dictlen); + ZEND_ASSERT(success == Z_OK); + efree(dict); + } } /* }}} */ -/* {{{ proto string deflate_add(resource context, string data[, int flush_mode = ZLIB_SYNC_FLUSH]) +/* {{{ proto string deflate_add(DeflateContext context, string data[, int flush_mode = ZLIB_SYNC_FLUSH]) Incrementally deflate data in the specified context */ PHP_FUNCTION(deflate_add) { @@ -1160,17 +1199,15 @@ PHP_FUNCTION(deflate_add) char *in_buf; size_t in_len, out_size, buffer_used; zval *res; - z_stream *ctx; + php_zlib_context *ctx; zend_long flush_type = Z_SYNC_FLUSH; int status; - if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "rs|l", &res, &in_buf, &in_len, &flush_type)) { + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "Os|l", &res, deflate_context_ce, &in_buf, &in_len, &flush_type)) { RETURN_THROWS(); } - if ((ctx = zend_fetch_resource(Z_RES_P(res), le_deflate_name, le_deflate)) == NULL) { - RETURN_THROWS(); - } + ctx = Z_DEFLATE_CONTEXT_P(res); switch (flush_type) { case Z_BLOCK: @@ -1198,35 +1235,35 @@ PHP_FUNCTION(deflate_add) out_size = (out_size < 64) ? 64 : out_size; out = zend_string_alloc(out_size, 0); - ctx->next_in = (Bytef *) in_buf; - ctx->next_out = (Bytef *) ZSTR_VAL(out); - ctx->avail_in = in_len; - ctx->avail_out = ZSTR_LEN(out); + ctx->Z.next_in = (Bytef *) in_buf; + ctx->Z.next_out = (Bytef *) ZSTR_VAL(out); + ctx->Z.avail_in = in_len; + ctx->Z.avail_out = ZSTR_LEN(out); buffer_used = 0; do { - if (ctx->avail_out == 0) { + if (ctx->Z.avail_out == 0) { /* more output buffer space needed; realloc and try again */ /* adding 64 more bytes solved every issue I have seen */ out = zend_string_realloc(out, ZSTR_LEN(out) + 64, 0); - ctx->avail_out = 64; - ctx->next_out = (Bytef *) ZSTR_VAL(out) + buffer_used; + ctx->Z.avail_out = 64; + ctx->Z.next_out = (Bytef *) ZSTR_VAL(out) + buffer_used; } - status = deflate(ctx, flush_type); - buffer_used = ZSTR_LEN(out) - ctx->avail_out; - } while (status == Z_OK && ctx->avail_out == 0); + status = deflate(&ctx->Z, flush_type); + buffer_used = ZSTR_LEN(out) - ctx->Z.avail_out; + } while (status == Z_OK && ctx->Z.avail_out == 0); switch (status) { case Z_OK: - ZSTR_LEN(out) = (char *) ctx->next_out - ZSTR_VAL(out); + ZSTR_LEN(out) = (char *) ctx->Z.next_out - ZSTR_VAL(out); ZSTR_VAL(out)[ZSTR_LEN(out)] = 0; RETURN_STR(out); break; case Z_STREAM_END: - ZSTR_LEN(out) = (char *) ctx->next_out - ZSTR_VAL(out); + ZSTR_LEN(out) = (char *) ctx->Z.next_out - ZSTR_VAL(out); ZSTR_VAL(out)[ZSTR_LEN(out)] = 0; - deflateReset(ctx); + deflateReset(&ctx->Z); RETURN_STR(out); break; default: @@ -1319,8 +1356,33 @@ static PHP_MINIT_FUNCTION(zlib) php_output_handler_conflict_register(ZEND_STRL("ob_gzhandler"), php_zlib_output_conflict_check); php_output_handler_conflict_register(ZEND_STRL(PHP_ZLIB_OUTPUT_HANDLER_NAME), php_zlib_output_conflict_check); - le_deflate = zend_register_list_destructors_ex(deflate_rsrc_dtor, NULL, "zlib.deflate", module_number); - le_inflate = zend_register_list_destructors_ex(inflate_rsrc_dtor, NULL, "zlib.inflate", module_number); + zend_class_entry inflate_ce; + INIT_CLASS_ENTRY(inflate_ce, "InflateContext", class_InflateContext_methods); + inflate_context_ce = zend_register_internal_class(&inflate_ce); + inflate_context_ce->ce_flags |= ZEND_ACC_FINAL; + inflate_context_ce->create_object = inflate_context_create_object; + inflate_context_ce->serialize = zend_class_serialize_deny; + inflate_context_ce->unserialize = zend_class_unserialize_deny; + + memcpy(&inflate_context_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + inflate_context_object_handlers.offset = XtOffsetOf(php_zlib_context, std); + inflate_context_object_handlers.free_obj = inflate_context_free_obj; + inflate_context_object_handlers.get_constructor = inflate_context_get_constructor; + inflate_context_object_handlers.clone_obj = NULL; + + zend_class_entry deflate_ce; + INIT_CLASS_ENTRY(deflate_ce, "DeflateContext", class_DeflateContext_methods); + deflate_context_ce = zend_register_internal_class(&deflate_ce); + deflate_context_ce->ce_flags |= ZEND_ACC_FINAL; + deflate_context_ce->create_object = deflate_context_create_object; + deflate_context_ce->serialize = zend_class_serialize_deny; + deflate_context_ce->unserialize = zend_class_unserialize_deny; + + memcpy(&deflate_context_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + deflate_context_object_handlers.offset = XtOffsetOf(php_zlib_context, std); + deflate_context_object_handlers.free_obj = deflate_context_free_obj; + deflate_context_object_handlers.get_constructor = deflate_context_get_constructor; + deflate_context_object_handlers.clone_obj = NULL; REGISTER_LONG_CONSTANT("FORCE_GZIP", PHP_ZLIB_ENCODING_GZIP, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FORCE_DEFLATE", PHP_ZLIB_ENCODING_DEFLATE, CONST_CS|CONST_PERSISTENT); diff --git a/ext/zlib/zlib.stub.php b/ext/zlib/zlib.stub.php index c3f87e5ccc..8f4ba12c79 100644 --- a/ext/zlib/zlib.stub.php +++ b/ext/zlib/zlib.stub.php @@ -2,6 +2,14 @@ /** @generate-function-entries */ +final class InflateContext +{ +} + +final class DeflateContext +{ +} + function ob_gzhandler(string $data, int $flags): string|false {} function zlib_get_coding_type(): string|false {} @@ -95,20 +103,14 @@ function gzread($fp, int $length): string|false {} */ function gzgets($fp, int $length = 1024): string|false {} -/** @return resource|false */ -function deflate_init(int $encoding, array $options = []) {} +function deflate_init(int $encoding, array $options = []): DeflateContext|false {} -/** @param resource $resource */ -function deflate_add($resource, string $add, int $flush_behavior = ZLIB_SYNC_FLUSH): string|false {} +function deflate_add(DeflateContext $context, string $add, int $flush_behavior = ZLIB_SYNC_FLUSH): string|false {} -/** @return resource|false */ -function inflate_init(int $encoding, array $options = []) {} +function inflate_init(int $encoding, array $options = []): InflateContext|false {} -/** @param resource $context */ -function inflate_add($context, string $encoded_data, int $flush_mode = ZLIB_SYNC_FLUSH): string|false {} +function inflate_add(InflateContext $context, string $encoded_data, int $flush_mode = ZLIB_SYNC_FLUSH): string|false {} -/** @param resource $resource */ -function inflate_get_status($resource): int {} +function inflate_get_status(InflateContext $context): int {} -/** @param resource $resource */ -function inflate_get_read_len($resource): int {} +function inflate_get_read_len(InflateContext $context): int {} diff --git a/ext/zlib/zlib_arginfo.h b/ext/zlib/zlib_arginfo.h index b86926c906..2a5112391e 100644 --- a/ext/zlib/zlib_arginfo.h +++ b/ext/zlib/zlib_arginfo.h @@ -103,27 +103,30 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_gzgets, 0, 1, MAY_BE_STRING|MAY_ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, length, IS_LONG, 0, "1024") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_deflate_init, 0, 0, 1) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_deflate_init, 0, 1, DeflateContext, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, encoding, IS_LONG, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "[]") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_deflate_add, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) - ZEND_ARG_INFO(0, resource) + ZEND_ARG_OBJ_INFO(0, context, DeflateContext, 0) ZEND_ARG_TYPE_INFO(0, add, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flush_behavior, IS_LONG, 0, "ZLIB_SYNC_FLUSH") ZEND_END_ARG_INFO() -#define arginfo_inflate_init arginfo_deflate_init +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_inflate_init, 0, 1, InflateContext, MAY_BE_FALSE) + ZEND_ARG_TYPE_INFO(0, encoding, IS_LONG, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "[]") +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_inflate_add, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) - ZEND_ARG_INFO(0, context) + ZEND_ARG_OBJ_INFO(0, context, InflateContext, 0) ZEND_ARG_TYPE_INFO(0, encoded_data, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flush_mode, IS_LONG, 0, "ZLIB_SYNC_FLUSH") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_inflate_get_status, 0, 1, IS_LONG, 0) - ZEND_ARG_INFO(0, resource) + ZEND_ARG_OBJ_INFO(0, context, InflateContext, 0) ZEND_END_ARG_INFO() #define arginfo_inflate_get_read_len arginfo_inflate_get_status @@ -193,3 +196,13 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(inflate_get_read_len, arginfo_inflate_get_read_len) ZEND_FE_END }; + + +static const zend_function_entry class_InflateContext_methods[] = { + ZEND_FE_END +}; + + +static const zend_function_entry class_DeflateContext_methods[] = { + ZEND_FE_END +};