From 505fe2f0b87bba956d399f657f85a7073c978289 Mon Sep 17 00:00:00 2001 From: Mike Schroder Date: Fri, 16 Oct 2020 10:46:58 +0000 Subject: [PATCH] Media: Work around `use-cropbox` bug in Ghostscript 8.70 Wraps `Imagick::readImage()` for PDFs with exception handling, trying again without `use-cropbox` if this fails. Introduces `WP_Image_Editor_Imagick::pdf_load_source()`. Works around a known issue in Ghostscript 8.70 (fixed in 8.71) that results in a stack underflow. While it only affects this version, it remains a common version found on hosts, and prevented some PDF thumbnails from being generated. See this Ghostscript bug for more details: https://bugs.ghostscript.com/show_bug.cgi?id=690676 Props azaozz, joseaneto, cranewest, dantahoua, n5hzr, mikeschroder. Fixes #48853. git-svn-id: https://develop.svn.wordpress.org/trunk@49174 602fd350-edb4-49c9-b593-d223f7449a82 --- .../class-wp-image-editor-imagick.php | 53 +++++++++++++++---- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/src/wp-includes/class-wp-image-editor-imagick.php b/src/wp-includes/class-wp-image-editor-imagick.php index dbdf1607cd..0d2aa05ac7 100644 --- a/src/wp-includes/class-wp-image-editor-imagick.php +++ b/src/wp-includes/class-wp-image-editor-imagick.php @@ -140,15 +140,16 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor { try { $this->image = new Imagick(); $file_extension = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) ); - $filename = $this->file; if ( 'pdf' === $file_extension ) { - $filename = $this->pdf_setup(); - } + $pdf_loaded = $this->pdf_load_source(); - // Reading image after Imagick instantiation because `setResolution` - // only applies correctly before the image is read. - $this->image->readImage( $filename ); + if ( is_wp_error( $pdf_loaded ) ) { + return $pdf_loaded; + } + } else { + $this->image->readImage( $this->file ); + } if ( ! $this->image->valid() ) { return new WP_Error( 'invalid_image', __( 'File is not an image.' ), $this->file ); @@ -165,6 +166,7 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor { } $updated_size = $this->update_size(); + if ( is_wp_error( $updated_size ) ) { return $updated_size; } @@ -795,10 +797,6 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor { // We want the thumbnail to be readable, so increase the rendering DPI. $this->image->setResolution( 128, 128 ); - // When generating thumbnails from cropped PDF pages, Imagemagick uses the uncropped - // area (resulting in unnecessary whitespace) unless the following option is set. - $this->image->setOption( 'pdf:use-cropbox', true ); - // Only load the first page. return $this->file . '[0]'; } catch ( Exception $e ) { @@ -806,4 +804,39 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor { } } + /** + * Load the image produced by Ghostscript. + * + * Includes a workaround for a bug in Ghostscript 8.70 that prevents processing of some PDF files + * when `use-cropbox` is set. + * + * @since 5.6 + * + * @return true|WP_error + */ + protected function pdf_load_source() { + $filename = $this->pdf_setup(); + + if ( is_wp_error( $filename ) ) { + return $filename; + } + + try { + // When generating thumbnails from cropped PDF pages, Imagemagick uses the uncropped + // area (resulting in unnecessary whitespace) unless the following option is set. + $this->image->setOption( 'pdf:use-cropbox', true ); + + // Reading image after Imagick instantiation because `setResolution` + // only applies correctly before the image is read. + $this->image->readImage( $filename ); + } catch ( Exception $e ) { + // Attempt to run `gs` without the `use-cropbox` option. See #48853. + $this->image->setOption( 'pdf:use-cropbox', false ); + + $this->image->readImage( $filename ); + } + + return true; + } + }