From 6786fc8713db2bb05a89c1f67c8ed3980992c6fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Mon, 6 Jul 2020 11:28:10 +0200 Subject: [PATCH 1/3] Explode _php_image_output_ctx() into multiple functions --- ext/gd/gd.c | 295 ++++++++++++++++++++++++++++++++------------ ext/gd/gd.stub.php | 4 + ext/gd/gd_arginfo.h | 7 +- 3 files changed, 224 insertions(+), 82 deletions(-) diff --git a/ext/gd/gd.c b/ext/gd/gd.c index eb35655f33a22..c0dfa8cdb9559 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -135,6 +135,13 @@ static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS); static gdImagePtr _php_image_create_from_string(zend_string *Data, char *tn, gdImagePtr (*ioctx_func_p)()); static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)()); static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)()); +static void _php_image_output_putc(struct gdIOCtx *ctx, int c); +static int _php_image_output_putbuf(struct gdIOCtx *ctx, const void* buf, int l); +static void _php_image_output_ctxfree(struct gdIOCtx *ctx); +static void _php_image_stream_putc(struct gdIOCtx *ctx, int c); +static int _php_image_stream_putbuf(struct gdIOCtx *ctx, const void* buf, int l); +static void _php_image_stream_ctxfreeandclose(struct gdIOCtx *ctx); +static void _php_image_stream_ctxfree(struct gdIOCtx *ctx); static int _php_image_type(char data[12]); /* output streaming (formerly gd_ctx.c) */ @@ -155,10 +162,6 @@ typedef struct _gd_ext_image_object { static zend_object_handlers php_gd_image_object_handlers; -static const zend_function_entry gd_image_object_methods[] = { - PHP_FE_END -}; - static zend_function *php_gd_image_object_get_constructor(zend_object *object) { zend_throw_error(NULL, "You cannot initialize a GdImage object except through helper functions"); @@ -221,7 +224,7 @@ void php_gd_assign_libgdimageptr_as_extgdimage(zval *val, gdImagePtr image) static void php_gd_object_minit_helper() { zend_class_entry ce; - INIT_CLASS_ENTRY(ce, "GdImage", gd_image_object_methods); + INIT_CLASS_ENTRY(ce, "GdImage", class_GdImage_methods); gd_image_ce = zend_register_internal_class(&ce); gd_image_ce->ce_flags |= ZEND_ACC_FINAL; gd_image_ce->create_object = php_gd_image_object_create; @@ -1869,7 +1872,52 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char /* {{{ Output XBM image to browser or file */ PHP_FUNCTION(imagexbm) { - _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XBM, "XBM", gdImageXbmCtx); + zval *imgind; + char *file = NULL; + size_t file_len = 0; + zend_long foreground_color = -1; + gdImagePtr im; + int argc = ZEND_NUM_ARGS(); + int i; + gdIOCtx *ctx = NULL; + php_stream *stream; + + if (zend_parse_parameters(argc, "Op!|l", &imgind, gd_image_ce, &file, &file_len, &foreground_color) == FAILURE) { + RETURN_THROWS(); + } + + im = php_gd_libgdimageptr_from_zval_p(imgind); + + if (argc > 1 && file != NULL) { + stream = php_stream_open_wrapper(file, "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL); + if (stream == NULL) { + RETURN_FALSE; + } + + ctx = ecalloc(1, sizeof(gdIOCtx)); + ctx->putC = _php_image_stream_putc; + ctx->putBuf = _php_image_stream_putbuf; + ctx->gd_free = _php_image_stream_ctxfreeandclose; + ctx->data = (void *)stream; + } else { + ctx = ecalloc(1, sizeof(gdIOCtx)); + ctx->putC = _php_image_output_putc; + ctx->putBuf = _php_image_output_putbuf; + ctx->gd_free = _php_image_output_ctxfree; + } + + if (argc < 3) { + for (i=0; i < gdImageColorsTotal(im); i++) { + if (!gdImageRed(im, i) && !gdImageGreen(im, i) && !gdImageBlue(im, i)) break; + } + foreground_color = i; + } + + gdImageXbmCtx(im, file ? file : "", (int) foreground_color, ctx); + + ctx->gd_free(ctx); + + RETURN_TRUE; } /* }}} */ @@ -1889,7 +1937,6 @@ PHP_FUNCTION(imagepng) /* }}} */ #endif /* HAVE_GD_PNG */ - #ifdef HAVE_GD_WEBP /* {{{ Output WEBP image to browser or file */ PHP_FUNCTION(imagewebp) @@ -1899,7 +1946,6 @@ PHP_FUNCTION(imagewebp) /* }}} */ #endif /* HAVE_GD_WEBP */ - #ifdef HAVE_GD_JPG /* {{{ Output JPEG image to browser or file */ PHP_FUNCTION(imagejpeg) @@ -1912,7 +1958,74 @@ PHP_FUNCTION(imagejpeg) /* {{{ Output WBMP image to browser or file */ PHP_FUNCTION(imagewbmp) { - _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "WBMP", gdImageWBMPCtx); + zval *imgind; + zend_long foreground_color = -1; + gdImagePtr im; + int argc = ZEND_NUM_ARGS(); + int i; + gdIOCtx *ctx = NULL; + zval *to_zval = NULL; + php_stream *stream; + int close_stream = 1; + + if (zend_parse_parameters(argc, "O|z!l", &imgind, gd_image_ce, &to_zval, &foreground_color) == FAILURE) { + RETURN_THROWS(); + } + + im = php_gd_libgdimageptr_from_zval_p(imgind); + + if (argc > 1 && to_zval != NULL) { + if (Z_TYPE_P(to_zval) == IS_RESOURCE) { + php_stream_from_zval_no_verify(stream, to_zval); + if (stream == NULL) { + RETURN_FALSE; + } + close_stream = 0; + } else if (Z_TYPE_P(to_zval) == IS_STRING) { + if (CHECK_ZVAL_NULL_PATH(to_zval)) { + zend_argument_type_error(2, "must not contain null bytes"); + RETURN_THROWS(); + } + + stream = php_stream_open_wrapper(Z_STRVAL_P(to_zval), "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL); + if (stream == NULL) { + RETURN_FALSE; + } + } else { + zend_argument_type_error(2, "must be a filename or a stream resource, %s given", zend_zval_type_name(to_zval)); + RETURN_THROWS(); + } + + ctx = ecalloc(1, sizeof(gdIOCtx)); + ctx->putC = _php_image_stream_putc; + ctx->putBuf = _php_image_stream_putbuf; + if (close_stream) { + ctx->gd_free = _php_image_stream_ctxfreeandclose; + } else { + ctx->gd_free = _php_image_stream_ctxfree; + } + ctx->data = (void *)stream; + } else { + ctx = ecalloc(1, sizeof(gdIOCtx)); + ctx->putC = _php_image_output_putc; + ctx->putBuf = _php_image_output_putbuf; + ctx->gd_free = _php_image_output_ctxfree; + } + + if (argc < 3) { + for (i=0; i < gdImageColorsTotal(im); i++) { + if (!gdImageRed(im, i) && !gdImageGreen(im, i) && !gdImageBlue(im, i)) + break; + } + + foreground_color = i; + } + + gdImageWBMPCtx(im, foreground_color, ctx); + + ctx->gd_free(ctx); + + RETURN_TRUE; } /* }}} */ @@ -1934,7 +2047,64 @@ PHP_FUNCTION(imagegd2) /* {{{ Output BMP image to browser or file */ PHP_FUNCTION(imagebmp) { - _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_BMP, "BMP", gdImageBmpCtx); + zval *imgind; + zend_bool compressed = 1; + gdImagePtr im; + int argc = ZEND_NUM_ARGS(); + gdIOCtx *ctx = NULL; + zval *to_zval = NULL; + php_stream *stream; + int close_stream = 1; + + if (zend_parse_parameters(argc, "O|z!b", &imgind, gd_image_ce, &to_zval, &compressed) == FAILURE) { + RETURN_THROWS(); + } + + im = php_gd_libgdimageptr_from_zval_p(imgind); + + if (argc > 1 && to_zval != NULL) { + if (Z_TYPE_P(to_zval) == IS_RESOURCE) { + php_stream_from_zval_no_verify(stream, to_zval); + if (stream == NULL) { + RETURN_FALSE; + } + close_stream = 0; + } else if (Z_TYPE_P(to_zval) == IS_STRING) { + if (CHECK_ZVAL_NULL_PATH(to_zval)) { + zend_argument_type_error(2, "must not contain null bytes"); + RETURN_THROWS(); + } + + stream = php_stream_open_wrapper(Z_STRVAL_P(to_zval), "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL); + if (stream == NULL) { + RETURN_FALSE; + } + } else { + zend_argument_type_error(2, "must be a filename or a stream resource, %s given", zend_zval_type_name(to_zval)); + RETURN_THROWS(); + } + + ctx = ecalloc(1, sizeof(gdIOCtx)); + ctx->putC = _php_image_stream_putc; + ctx->putBuf = _php_image_stream_putbuf; + if (close_stream) { + ctx->gd_free = _php_image_stream_ctxfreeandclose; + } else { + ctx->gd_free = _php_image_stream_ctxfree; + } + ctx->data = (void *)stream; + } else { + ctx = ecalloc(1, sizeof(gdIOCtx)); + ctx->putC = _php_image_output_putc; + ctx->putBuf = _php_image_output_putbuf; + ctx->gd_free = _php_image_output_ctxfree; + } + + gdImageBmpCtx(im, ctx, (int) compressed); + + ctx->gd_free(ctx); + + RETURN_TRUE; } /* }}} */ #endif @@ -3998,58 +4168,31 @@ static void _php_image_stream_ctxfreeandclose(struct gdIOCtx *ctx) /* {{{ */ } } /* }}} */ -/* {{{ _php_image_output_ctx */ + static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)()) { zval *imgind; - char *file = NULL; - size_t file_len = 0; - zend_long quality, basefilter; - zend_bool compressed = 1; + zend_long quality = -1, basefilter = -1; gdImagePtr im; int argc = ZEND_NUM_ARGS(); - int q = -1, i; - int f = -1; + int i; gdIOCtx *ctx = NULL; zval *to_zval = NULL; php_stream *stream; int close_stream = 1; - /* The third (quality) parameter for Wbmp and Xbm stands for the foreground color index when called - * from imagey(). - */ - switch (image_type) { - case PHP_GDIMG_TYPE_XBM: - if (zend_parse_parameters(argc, "Op!|ll", &imgind, gd_image_ce, &file, &file_len, &quality, &basefilter) == FAILURE) { - RETURN_THROWS(); - } - break; - case PHP_GDIMG_TYPE_BMP: - if (zend_parse_parameters(argc, "O|z!b", &imgind, gd_image_ce, &to_zval, &compressed) == FAILURE) { - RETURN_THROWS(); - } - break; - default: - /* PHP_GDIMG_TYPE_GIF - * PHP_GDIMG_TYPE_PNG - * PHP_GDIMG_TYPE_JPG - * PHP_GDIMG_TYPE_WBM - * PHP_GDIMG_TYPE_WEBP - * */ - if (zend_parse_parameters(argc, "O|z!ll", &imgind, gd_image_ce, &to_zval, &quality, &basefilter) == FAILURE) { - RETURN_THROWS(); - } + if (image_type == PHP_GDIMG_TYPE_PNG) { + if (zend_parse_parameters(argc, "O|z!ll", &imgind, gd_image_ce, &to_zval, &quality, &basefilter) == FAILURE) { + RETURN_THROWS(); + } + } else { + if (zend_parse_parameters(argc, "O|z!l", &imgind, gd_image_ce, &to_zval, &quality) == FAILURE) { + RETURN_THROWS(); + } } im = php_gd_libgdimageptr_from_zval_p(imgind); - if (image_type != PHP_GDIMG_TYPE_BMP && argc >= 3) { - q = quality; /* or colorindex for foreground of BW images (defaults to black) */ - if (argc == 4) { - f = basefilter; - } - } - if (argc > 1 && to_zval != NULL) { if (Z_TYPE_P(to_zval) == IS_RESOURCE) { php_stream_from_zval_no_verify(stream, to_zval); @@ -4068,22 +4211,10 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, RETURN_FALSE; } } else { - php_error_docref(NULL, E_WARNING, "Invalid 2nd parameter, it must a filename or a stream"); - RETURN_FALSE; - } - } else if (argc > 1 && file != NULL) { - stream = php_stream_open_wrapper(file, "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL); - if (stream == NULL) { - RETURN_FALSE; + zend_argument_type_error(2, "must be a filename or a stream resource, %s given", zend_zval_type_name(to_zval)); + RETURN_THROWS(); } - } else { - ctx = ecalloc(1, sizeof(gdIOCtx)); - ctx->putC = _php_image_output_putc; - ctx->putBuf = _php_image_output_putbuf; - ctx->gd_free = _php_image_output_ctxfree; - } - if (!ctx) { ctx = ecalloc(1, sizeof(gdIOCtx)); ctx->putC = _php_image_stream_putc; ctx->putBuf = _php_image_stream_putbuf; @@ -4093,45 +4224,47 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, ctx->gd_free = _php_image_stream_ctxfree; } ctx->data = (void *)stream; + } else { + ctx = ecalloc(1, sizeof(gdIOCtx)); + ctx->putC = _php_image_output_putc; + ctx->putBuf = _php_image_output_putbuf; + ctx->gd_free = _php_image_output_ctxfree; } - switch(image_type) { + switch (image_type) { case PHP_GDIMG_TYPE_JPG: - (*func_p)(im, ctx, q); + (*func_p)(im, ctx, (int) quality); break; case PHP_GDIMG_TYPE_WEBP: - if (q == -1) { - q = 80; + if (quality == -1) { + quality = 80; } - (*func_p)(im, ctx, q); + (*func_p)(im, ctx, (int) quality); break; case PHP_GDIMG_TYPE_PNG: - (*func_p)(im, ctx, q, f); + (*func_p)(im, ctx, (int) quality, (int) basefilter); break; - case PHP_GDIMG_TYPE_XBM: case PHP_GDIMG_TYPE_WBM: if (argc < 3) { - for(i=0; i < gdImageColorsTotal(im); i++) { - if(!gdImageRed(im, i) && !gdImageGreen(im, i) && !gdImageBlue(im, i)) break; + for (i=0; i < gdImageColorsTotal(im); i++) { + if (!gdImageRed(im, i) && !gdImageGreen(im, i) && !gdImageBlue(im, i)) break; } - q = i; + quality = (int) i; } - if (image_type == PHP_GDIMG_TYPE_XBM) { - (*func_p)(im, file ? file : "", q, ctx); - } else { - (*func_p)(im, q, ctx); - } - break; - case PHP_GDIMG_TYPE_BMP: - (*func_p)(im, ctx, (int) compressed); + + (*func_p)(im, (int) quality, ctx); break; - default: + case PHP_GDIMG_TYPE_GIF: (*func_p)(im, ctx); break; + + default: + ZEND_UNREACHABLE(); } ctx->gd_free(ctx); RETURN_TRUE; } + /* }}} */ diff --git a/ext/gd/gd.stub.php b/ext/gd/gd.stub.php index 3202a8b54190a..a284944102e1f 100644 --- a/ext/gd/gd.stub.php +++ b/ext/gd/gd.stub.php @@ -2,6 +2,10 @@ /** @generate-function-entries */ +final class GdImage +{ +} + function gd_info(): array {} function imageloadfont(string $filename): int|false {} diff --git a/ext/gd/gd_arginfo.h b/ext/gd/gd_arginfo.h index b8e95e7cd9887..5209f7a34c279 100644 --- a/ext/gd/gd_arginfo.h +++ b/ext/gd/gd_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: ce2eb70f449197eca39ca5d8c53ee1369577b035 */ + * Stub hash: bb1f9f45ea75ccb96886d8fe5a2bc8f5c06e6661 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gd_info, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -855,3 +855,8 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(imageresolution, arginfo_imageresolution) ZEND_FE_END }; + + +static const zend_function_entry class_GdImage_methods[] = { + ZEND_FE_END +}; From a021780d3d7ac37a4f1cdf4d195dbe0e47a01670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Sun, 12 Jul 2020 14:28:15 +0200 Subject: [PATCH 2/3] Address the first batch of review comments --- ext/gd/gd.c | 99 ++++++++++++++++++++--------------------------------- 1 file changed, 37 insertions(+), 62 deletions(-) diff --git a/ext/gd/gd.c b/ext/gd/gd.c index c0dfa8cdb9559..d1ce0fc202788 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -135,13 +135,8 @@ static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS); static gdImagePtr _php_image_create_from_string(zend_string *Data, char *tn, gdImagePtr (*ioctx_func_p)()); static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)()); static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)()); -static void _php_image_output_putc(struct gdIOCtx *ctx, int c); -static int _php_image_output_putbuf(struct gdIOCtx *ctx, const void* buf, int l); -static void _php_image_output_ctxfree(struct gdIOCtx *ctx); -static void _php_image_stream_putc(struct gdIOCtx *ctx, int c); -static int _php_image_stream_putbuf(struct gdIOCtx *ctx, const void* buf, int l); -static void _php_image_stream_ctxfreeandclose(struct gdIOCtx *ctx); -static void _php_image_stream_ctxfree(struct gdIOCtx *ctx); +static gdIOCtx *create_stream_context(php_stream *stream, int close_stream); +static gdIOCtx *create_output_context(); static int _php_image_type(char data[12]); /* output streaming (formerly gd_ctx.c) */ @@ -1824,8 +1819,7 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char } (*func_p)(im, fp, q, t); break; - default: - ZEND_UNREACHABLE(); + EMPTY_SWITCH_DEFAULT_CASE() } fflush(fp); fclose(fp); @@ -1851,8 +1845,7 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char } (*func_p)(im, tmp, q, t); break; - default: - ZEND_UNREACHABLE(); + EMPTY_SWITCH_DEFAULT_CASE() } fseek(tmp, 0, SEEK_SET); @@ -1894,16 +1887,9 @@ PHP_FUNCTION(imagexbm) RETURN_FALSE; } - ctx = ecalloc(1, sizeof(gdIOCtx)); - ctx->putC = _php_image_stream_putc; - ctx->putBuf = _php_image_stream_putbuf; - ctx->gd_free = _php_image_stream_ctxfreeandclose; - ctx->data = (void *)stream; + ctx = create_stream_context(stream, 1); } else { - ctx = ecalloc(1, sizeof(gdIOCtx)); - ctx->putC = _php_image_output_putc; - ctx->putBuf = _php_image_output_putbuf; - ctx->gd_free = _php_image_output_ctxfree; + ctx = create_output_context(); } if (argc < 3) { @@ -1996,20 +1982,9 @@ PHP_FUNCTION(imagewbmp) RETURN_THROWS(); } - ctx = ecalloc(1, sizeof(gdIOCtx)); - ctx->putC = _php_image_stream_putc; - ctx->putBuf = _php_image_stream_putbuf; - if (close_stream) { - ctx->gd_free = _php_image_stream_ctxfreeandclose; - } else { - ctx->gd_free = _php_image_stream_ctxfree; - } - ctx->data = (void *)stream; + ctx = create_stream_context(stream, close_stream); } else { - ctx = ecalloc(1, sizeof(gdIOCtx)); - ctx->putC = _php_image_output_putc; - ctx->putBuf = _php_image_output_putbuf; - ctx->gd_free = _php_image_output_ctxfree; + ctx = create_output_context(); } if (argc < 3) { @@ -2084,20 +2059,9 @@ PHP_FUNCTION(imagebmp) RETURN_THROWS(); } - ctx = ecalloc(1, sizeof(gdIOCtx)); - ctx->putC = _php_image_stream_putc; - ctx->putBuf = _php_image_stream_putbuf; - if (close_stream) { - ctx->gd_free = _php_image_stream_ctxfreeandclose; - } else { - ctx->gd_free = _php_image_stream_ctxfree; - } - ctx->data = (void *)stream; + ctx = create_stream_context(stream, close_stream); } else { - ctx = ecalloc(1, sizeof(gdIOCtx)); - ctx->putC = _php_image_output_putc; - ctx->putBuf = _php_image_output_putbuf; - ctx->gd_free = _php_image_output_ctxfree; + ctx = create_output_context(); } gdImageBmpCtx(im, ctx, (int) compressed); @@ -4168,6 +4132,30 @@ static void _php_image_stream_ctxfreeandclose(struct gdIOCtx *ctx) /* {{{ */ } } /* }}} */ +static gdIOCtx *create_stream_context(php_stream *stream, int close_stream) { + gdIOCtx *ctx = ecalloc(1, sizeof(gdIOCtx)); + + ctx->putC = _php_image_stream_putc; + ctx->putBuf = _php_image_stream_putbuf; + if (close_stream) { + ctx->gd_free = _php_image_stream_ctxfreeandclose; + } else { + ctx->gd_free = _php_image_stream_ctxfree; + } + ctx->data = (void *)stream; + + return ctx; +} + +static gdIOCtx *create_output_context() { + gdIOCtx *ctx = ecalloc(1, sizeof(gdIOCtx)); + + ctx->putC = _php_image_output_putc; + ctx->putBuf = _php_image_output_putbuf; + ctx->gd_free = _php_image_output_ctxfree; + + return ctx; +} static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)()) { @@ -4215,20 +4203,9 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, RETURN_THROWS(); } - ctx = ecalloc(1, sizeof(gdIOCtx)); - ctx->putC = _php_image_stream_putc; - ctx->putBuf = _php_image_stream_putbuf; - if (close_stream) { - ctx->gd_free = _php_image_stream_ctxfreeandclose; - } else { - ctx->gd_free = _php_image_stream_ctxfree; - } - ctx->data = (void *)stream; + ctx = create_stream_context(stream, close_stream); } else { - ctx = ecalloc(1, sizeof(gdIOCtx)); - ctx->putC = _php_image_output_putc; - ctx->putBuf = _php_image_output_putbuf; - ctx->gd_free = _php_image_output_ctxfree; + ctx = create_output_context(); } switch (image_type) { @@ -4257,9 +4234,7 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, case PHP_GDIMG_TYPE_GIF: (*func_p)(im, ctx); break; - - default: - ZEND_UNREACHABLE(); + EMPTY_SWITCH_DEFAULT_CASE() } ctx->gd_free(ctx); From e479815be03f0c176f762fcef21ed9b9c59fd7c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Tue, 14 Jul 2020 09:38:42 +0200 Subject: [PATCH 3/3] Extract stream handling --- ext/gd/gd.c | 107 +++++++++++++++++++--------------------------------- 1 file changed, 38 insertions(+), 69 deletions(-) diff --git a/ext/gd/gd.c b/ext/gd/gd.c index d1ce0fc202788..a64f02aa22c3d 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -135,6 +135,7 @@ static void php_image_filter_scatter(INTERNAL_FUNCTION_PARAMETERS); static gdImagePtr _php_image_create_from_string(zend_string *Data, char *tn, gdImagePtr (*ioctx_func_p)()); static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)()); static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)()); +static gdIOCtx *create_stream_context_from_zval(zval *to_zval); static gdIOCtx *create_stream_context(php_stream *stream, int close_stream); static gdIOCtx *create_output_context(); static int _php_image_type(char data[12]); @@ -1951,8 +1952,6 @@ PHP_FUNCTION(imagewbmp) int i; gdIOCtx *ctx = NULL; zval *to_zval = NULL; - php_stream *stream; - int close_stream = 1; if (zend_parse_parameters(argc, "O|z!l", &imgind, gd_image_ce, &to_zval, &foreground_color) == FAILURE) { RETURN_THROWS(); @@ -1961,28 +1960,10 @@ PHP_FUNCTION(imagewbmp) im = php_gd_libgdimageptr_from_zval_p(imgind); if (argc > 1 && to_zval != NULL) { - if (Z_TYPE_P(to_zval) == IS_RESOURCE) { - php_stream_from_zval_no_verify(stream, to_zval); - if (stream == NULL) { - RETURN_FALSE; - } - close_stream = 0; - } else if (Z_TYPE_P(to_zval) == IS_STRING) { - if (CHECK_ZVAL_NULL_PATH(to_zval)) { - zend_argument_type_error(2, "must not contain null bytes"); - RETURN_THROWS(); - } - - stream = php_stream_open_wrapper(Z_STRVAL_P(to_zval), "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL); - if (stream == NULL) { - RETURN_FALSE; - } - } else { - zend_argument_type_error(2, "must be a filename or a stream resource, %s given", zend_zval_type_name(to_zval)); - RETURN_THROWS(); + ctx = create_stream_context_from_zval(to_zval); + if (!ctx) { + RETURN_FALSE; } - - ctx = create_stream_context(stream, close_stream); } else { ctx = create_output_context(); } @@ -2028,8 +2009,6 @@ PHP_FUNCTION(imagebmp) int argc = ZEND_NUM_ARGS(); gdIOCtx *ctx = NULL; zval *to_zval = NULL; - php_stream *stream; - int close_stream = 1; if (zend_parse_parameters(argc, "O|z!b", &imgind, gd_image_ce, &to_zval, &compressed) == FAILURE) { RETURN_THROWS(); @@ -2038,28 +2017,10 @@ PHP_FUNCTION(imagebmp) im = php_gd_libgdimageptr_from_zval_p(imgind); if (argc > 1 && to_zval != NULL) { - if (Z_TYPE_P(to_zval) == IS_RESOURCE) { - php_stream_from_zval_no_verify(stream, to_zval); - if (stream == NULL) { - RETURN_FALSE; - } - close_stream = 0; - } else if (Z_TYPE_P(to_zval) == IS_STRING) { - if (CHECK_ZVAL_NULL_PATH(to_zval)) { - zend_argument_type_error(2, "must not contain null bytes"); - RETURN_THROWS(); - } - - stream = php_stream_open_wrapper(Z_STRVAL_P(to_zval), "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL); - if (stream == NULL) { - RETURN_FALSE; - } - } else { - zend_argument_type_error(2, "must be a filename or a stream resource, %s given", zend_zval_type_name(to_zval)); - RETURN_THROWS(); + ctx = create_stream_context_from_zval(to_zval); + if (!ctx) { + RETURN_FALSE; } - - ctx = create_stream_context(stream, close_stream); } else { ctx = create_output_context(); } @@ -4132,6 +4093,34 @@ static void _php_image_stream_ctxfreeandclose(struct gdIOCtx *ctx) /* {{{ */ } } /* }}} */ +static gdIOCtx *create_stream_context_from_zval(zval *to_zval) { + php_stream *stream; + int close_stream = 1; + + if (Z_TYPE_P(to_zval) == IS_RESOURCE) { + php_stream_from_zval_no_verify(stream, to_zval); + if (stream == NULL) { + return NULL; + } + close_stream = 0; + } else if (Z_TYPE_P(to_zval) == IS_STRING) { + if (CHECK_ZVAL_NULL_PATH(to_zval)) { + zend_argument_type_error(2, "must not contain null bytes"); + return NULL; + } + + stream = php_stream_open_wrapper(Z_STRVAL_P(to_zval), "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL); + if (stream == NULL) { + return NULL; + } + } else { + zend_argument_type_error(2, "must be a file name or a stream resource, %s given", zend_zval_type_name(to_zval)); + return NULL; + } + + return create_stream_context(stream, close_stream); +} + static gdIOCtx *create_stream_context(php_stream *stream, int close_stream) { gdIOCtx *ctx = ecalloc(1, sizeof(gdIOCtx)); @@ -4166,8 +4155,6 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, int i; gdIOCtx *ctx = NULL; zval *to_zval = NULL; - php_stream *stream; - int close_stream = 1; if (image_type == PHP_GDIMG_TYPE_PNG) { if (zend_parse_parameters(argc, "O|z!ll", &imgind, gd_image_ce, &to_zval, &quality, &basefilter) == FAILURE) { @@ -4182,28 +4169,10 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, im = php_gd_libgdimageptr_from_zval_p(imgind); if (argc > 1 && to_zval != NULL) { - if (Z_TYPE_P(to_zval) == IS_RESOURCE) { - php_stream_from_zval_no_verify(stream, to_zval); - if (stream == NULL) { - RETURN_FALSE; - } - close_stream = 0; - } else if (Z_TYPE_P(to_zval) == IS_STRING) { - if (CHECK_ZVAL_NULL_PATH(to_zval)) { - zend_argument_type_error(2, "must not contain null bytes"); - RETURN_THROWS(); - } - - stream = php_stream_open_wrapper(Z_STRVAL_P(to_zval), "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL); - if (stream == NULL) { - RETURN_FALSE; - } - } else { - zend_argument_type_error(2, "must be a filename or a stream resource, %s given", zend_zval_type_name(to_zval)); - RETURN_THROWS(); + ctx = create_stream_context_from_zval(to_zval); + if (!ctx) { + RETURN_FALSE; } - - ctx = create_stream_context(stream, close_stream); } else { ctx = create_output_context(); }