From b808cba14add913c72f44cd7795ad5d36752fad3 Mon Sep 17 00:00:00 2001 From: Kleis Auke Wolthuizen Date: Wed, 27 Jul 2022 10:14:12 +0200 Subject: [PATCH 1/3] Remove unneeded adapter function for Emscripten (#2949) The `*_class_intern_init` functions have already been patched within wasm-vips to include the missing `class_data` member, so this adapter function was not needed. --- libvips/conversion/extract.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/libvips/conversion/extract.c b/libvips/conversion/extract.c index 694a9ab1..defa53d2 100644 --- a/libvips/conversion/extract.c +++ b/libvips/conversion/extract.c @@ -172,14 +172,6 @@ vips_extract_area_build( VipsObject *object ) return( 0 ); } -#ifdef __EMSCRIPTEN__ -static void -vips_crop_class_intern_init_adapter( gpointer class, void *dummy ) -{ - vips_extract_area_class_intern_init( class ); -} -#endif - static void vips_extract_area_class_init( VipsExtractAreaClass *class ) { @@ -290,11 +282,7 @@ vips_crop_get_type( void ) GType new_type = g_type_register_static_simple( VIPS_TYPE_CONVERSION, g_intern_static_string( "crop" ), sizeof( VipsExtractAreaClass ), -#ifdef __EMSCRIPTEN__ - (GClassInitFunc) vips_crop_class_intern_init_adapter, -#else (GClassInitFunc)(void (*)(void)) vips_extract_area_class_intern_init, -#endif sizeof( VipsExtractArea ), #ifdef __EMSCRIPTEN__ (GInstanceInitFunc) vips_crop_init_adapter, From a6fa62605c930fb8dccb7716b775338edf35d037 Mon Sep 17 00:00:00 2001 From: Kleis Auke Wolthuizen Date: Sun, 31 Jul 2022 11:09:00 +0200 Subject: [PATCH 2/3] Cherry-pick a couple of Meson improvements to 8.13 (#2968) * add a summary table at the end of configure Copied from the old autotools summary. Sample clipped from "meson setup": ``` Program python3 found: YES (/usr/bin/python3) Configuring variables.sh using configuration Message: *Build options enable debug ......................: true enable deprecated .................: true enable modules ....................: true enable gtk-doc ....................: true enable doxygen ....................: false enable introspection ..............: true enable RAD load/save ..............: true enable Analyze7 load/save .........: true enable PPM load/save ..............: true enable GIF load ...................: true *Optional external packages use fftw for FFTs .................: true accelerate loops with ORC .........: true ICC profile support with lcms .....: true zlib ..............................: true text rendering with pangocairo ....: true font file support with fontcongfig : true EXIF metadata support with libexif : true *External image format libraries JPEG load/save with libjpeg .......: true JXL load/save with libjxl .........: false JPEG2000 load/save with openjpeg ..: true PNG load/save with libspng ........: false PNG load/save with libpng .........: true selected quantisation package .....: imagequant TIFF load/save with libtiff .......: true image pyramid save with libgsf ....: true HEIC/AVIF load/save with libheif ..: true WebP load/save with libwebp .......: true PDF load with PDFium ..............: false PDF load with poppler-glib ........: true SVG load with librsvg .............: true EXR load/save with openexr ........: true OpenSlide load ....................: true Matlab load with libmatio .........: true NIfTI load/save with niftiio ......: true FITS load/save with cfitsio .......: true GIF save with cgif ................: true selected Magick package ...........: MagickCore Magick load/save ..................: true Build targets in project: 53 ... ``` * Meson: improve summary table (#2943) * Meson: improve summary table * Fix typo * Remove redundant whitespace * Fix libpng fall-back when build with `-Dspng=disabled` (#2955) * Meson: simplify dynamic module handling (#2956) * Deduplicate `--vips-config` with the build summary (#2957) * Deduplicate `--vips-config` with the build summary * Ensure output is identical Helps parses. * Fix summary when build with `-Dnifti=disabled` (#2963) * Update ChangeLog Co-authored-by: John Cupitt --- ChangeLog | 2 + libvips/foreign/meson.build | 10 ++-- libvips/include/vips/meson.build | 56 +++++-------------- libvips/meson.build | 10 ++-- meson.build | 95 ++++++++++++++++++++++++++++---- 5 files changed, 109 insertions(+), 64 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6b9f2753..54af4ecc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 24/7/22 started 8.13.1 - fix im7 feature detection in meson +- add a summary table at the end of configure in meson +- fix libpng fallback when spng is disabled in meson 21/11/21 started 8.13 - configure fails for requested but unmet dependencies [remicollet] diff --git a/libvips/foreign/meson.build b/libvips/foreign/meson.build index 019a32ed..a72f9c78 100644 --- a/libvips/foreign/meson.build +++ b/libvips/foreign/meson.build @@ -82,7 +82,7 @@ magick_module_headers = files( 'magick.h', ) -if not modules_enabled or get_option('magick-module').disabled() +if not magick_module foreign_sources += magick_module_sources foreign_headers += magick_module_headers endif @@ -92,7 +92,7 @@ jpeg_xl_module_sources = files( 'jxlsave.c', ) -if not modules_enabled or get_option('jpeg-xl-module').disabled() +if not libjxl_module foreign_sources += jpeg_xl_module_sources endif @@ -101,7 +101,7 @@ heif_module_sources = files( 'heifsave.c', ) -if not modules_enabled or get_option('heif-module').disabled() +if not libheif_module foreign_sources += heif_module_sources endif @@ -109,7 +109,7 @@ poppler_module_sources = files( 'popplerload.c', ) -if not modules_enabled or get_option('poppler-module').disabled() +if not libpoppler_module foreign_sources += poppler_module_sources endif @@ -117,7 +117,7 @@ openslide_module_sources = files( 'openslideload.c', ) -if not modules_enabled or get_option('openslide-module').disabled() +if not openslide_module foreign_sources += openslide_module_sources endif diff --git a/libvips/include/vips/meson.build b/libvips/include/vips/meson.build index 2c21cc3b..426d637c 100644 --- a/libvips/include/vips/meson.build +++ b/libvips/include/vips/meson.build @@ -84,48 +84,20 @@ enumtypes = gnome.mkenums( ) vips_verbose_config = [] -vips_verbose_config += 'enable debug: @0@'.format(get_option('debug')) -vips_verbose_config += 'enable deprecated library components: @0@'.format(get_option('deprecated')) -vips_verbose_config += 'enable modules: @0@'.format(modules_enabled) -vips_verbose_config += 'use fftw3 for FFT: @0@'.format(fftw_dep.found()) -vips_verbose_config += 'accelerate loops with orc: @0@'.format(orc_dep.found()) -vips_verbose_config += 'ICC profile support with lcms: @0@'.format(lcms_dep.found()) -vips_verbose_config += 'zlib: @0@'.format(zlib_dep.found()) -vips_verbose_config += 'text rendering with pangocairo: @0@'.format(pangocairo_dep.found()) -vips_verbose_config += 'font file support with fontconfig: @0@'.format(fontconfig_dep.found()) -vips_verbose_config += 'RAD load/save: @0@'.format(get_option('radiance')) -vips_verbose_config += 'Analyze7 load/save: @0@'.format(get_option('analyze')) -vips_verbose_config += 'PPM load/save: @0@'.format(get_option('ppm')) -vips_verbose_config += 'GIF load: @0@'.format(get_option('nsgif')) -vips_verbose_config += 'GIF save with cgif: @0@'.format(cgif_dep.found()) -vips_verbose_config += 'EXIF metadata support with libexif: @0@'.format(libexif_dep.found()) -vips_verbose_config += 'JPEG load/save with libjpeg: @0@'.format(libjpeg_dep.found()) -vips_verbose_config += 'JXL load/save with libjxl: @0@ (dynamic module: @1@)'.format(libjxl_dep.found(), modules_enabled and not get_option('jpeg-xl-module').disabled()) -vips_verbose_config +='JPEG2000 load/save with libopenjp2: @0@'.format(libopenjp2_dep.found()) -vips_verbose_config += 'PNG load with libspng: @0@'.format(spng_dep.found()) -vips_verbose_config += 'PNG load/save with libpng: @0@'.format(png_dep.found()) -vips_verbose_config += 'selected quantisation package: @0@'.format(quantisation_package.found() ? quantisation_package.name() : 'none') -vips_verbose_config += 'TIFF load/save with libtiff: @0@'.format(libtiff_dep.found()) -vips_verbose_config += 'image pyramid save: @0@'.format(gsf_dep.found()) -vips_verbose_config += 'HEIC/AVIF load/save with libheif: @0@ (dynamic module: @1@)'.format(libheif_dep.found(), modules_enabled and not get_option('heif-module').disabled()) -vips_verbose_config += 'WebP load/save with libwebp: @0@'.format(libwebp_dep.found()) -vips_verbose_config += 'PDF load with PDFium: @0@'.format(pdfium_dep.found()) -vips_verbose_config += 'PDF load with poppler-glib: @0@ (dynamic module: @1@)'.format(libpoppler_dep.found(), modules_enabled and not get_option('poppler-module').disabled()) -vips_verbose_config += 'SVG load with librsvg-2.0: @0@'.format(librsvg_dep.found()) -vips_verbose_config += 'EXR load with OpenEXR: @0@'.format(openexr_dep.found()) -vips_verbose_config += 'OpenSlide load: @0@ (dynamic module: @1@)'.format(openslide_dep.found(), modules_enabled and not get_option('openslide-module').disabled()) -vips_verbose_config += 'Matlab load with matio: @0@'.format(matio_dep.found()) -vips_verbose_config += 'NIfTI load/save with niftiio: @0@'.format(libnifti_dep.found()) -vips_verbose_config += 'FITS load/save with cfitsio: @0@'.format(cfitsio_dep.found()) -vips_verbose_config += 'Magick package: @0@ (dynamic module: @1@)'.format(magick_dep.found(), modules_enabled and not get_option('magick-module').disabled()) -if magick_dep.found() - magick_version_str = 'magick' + magick_dep.version().split('.')[0] -else - magick_version_str = 'none' -endif -vips_verbose_config += 'Magick API version: @0@'.format(magick_version_str) -vips_verbose_config += 'load with libMagickCore: @0@'.format(magick_dep.found() and 'load' in get_option('magick-features')) -vips_verbose_config += 'save with libMagickCore: @0@'.format(magick_dep.found() and 'save' in get_option('magick-features')) +foreach _, section : build_summary + foreach key, arr : section + if key.contains('gtk-doc') or \ + key.contains('doxygen') or \ + key.contains('introspection') + continue + endif + + vips_verbose_config += '@0@: @1@@2@@3@@4@'.format(key, arr[0], + arr.length() > 1 ? arr[1] : '', + arr.length() > 2 ? arr[2] : '', + arr.length() > 3 ? arr[3] : '') + endforeach +endforeach version_data = configuration_data() version_data.set('VIPS_VERSION', meson.project_version()) diff --git a/libvips/meson.build b/libvips/meson.build index 2a4d1401..695a5841 100644 --- a/libvips/meson.build +++ b/libvips/meson.build @@ -79,7 +79,7 @@ if ['darwin', 'ios'].contains(host_os) module_suffix = 'so' endif -if magick_dep.found() and not get_option('magick-module').disabled() +if magick_module shared_module('vips-magick', 'module/magick.c', magick_module_sources, @@ -92,7 +92,7 @@ if magick_dep.found() and not get_option('magick-module').disabled() ) endif -if libjxl_dep.found() and not get_option('jpeg-xl-module').disabled() +if libjxl_module shared_module('vips-jxl', 'module/jxl.c', jpeg_xl_module_sources, @@ -104,7 +104,7 @@ if libjxl_dep.found() and not get_option('jpeg-xl-module').disabled() ) endif -if libheif_dep.found() and not get_option('heif-module').disabled() +if libheif_module shared_module('vips-heif', 'module/heif.c', heif_module_sources, @@ -116,7 +116,7 @@ if libheif_dep.found() and not get_option('heif-module').disabled() ) endif -if libpoppler_dep.found() and not get_option('poppler-module').disabled() +if libpoppler_module shared_module('vips-poppler', 'module/poppler.c', poppler_module_sources, @@ -128,7 +128,7 @@ if libpoppler_dep.found() and not get_option('poppler-module').disabled() ) endif -if openslide_dep.found() and not get_option('openslide-module').disabled() +if openslide_module shared_module('vips-openslide', 'module/openslide.c', openslide_module_sources, diff --git a/meson.build b/meson.build index faabd1e7..d5fd4dfe 100644 --- a/meson.build +++ b/meson.build @@ -168,8 +168,11 @@ if not magick_dep.found() # very old versions called it "ImageMagick" magick_dep = dependency('ImageMagick', required: get_option('magick')) endif -if not get_option('magick').disabled() and magick_dep.found() - if modules_enabled and not get_option('magick-module').disabled() +magick_found = not get_option('magick').disabled() and magick_dep.found() +magick_module = false +if magick_found + magick_module = modules_enabled and not get_option('magick-module').disabled() + if magick_module cfg_var.set('MAGICK_MODULE', '1') else libvips_deps += magick_dep @@ -301,14 +304,15 @@ spng_dep = dependency('spng', version: '>=0.7', required: false) if not spng_dep.found() spng_dep = dependency('libspng', version: '>=0.7', required: get_option('spng')) endif -if not get_option('spng').disabled() and spng_dep.found() +spng_found = not get_option('spng').disabled() and spng_dep.found() +if spng_found libvips_deps += spng_dep cfg_var.set('HAVE_SPNG', '1') endif # only if libspng not found png_dep = disabler() -if not spng_dep.found() +if not spng_found png_dep = dependency('libpng', version: '>=1.2.9', required: get_option('png')) if png_dep.found() libvips_deps += png_dep @@ -340,7 +344,8 @@ endif # text rendering with fontconfig requires pangoft2 pangoft2_dep = dependency('pangoft2', version: '>=1.32.6', required: get_option('fontconfig')) fontconfig_dep = dependency('fontconfig', required: get_option('fontconfig')) -if pangoft2_dep.found() and fontconfig_dep.found() and pangocairo_dep.found() +fontconfig_found = pangoft2_dep.found() and fontconfig_dep.found() and pangocairo_dep.found() +if fontconfig_found libvips_deps += pangoft2_dep libvips_deps += fontconfig_dep cfg_var.set('HAVE_FONTCONFIG', '1') @@ -359,15 +364,18 @@ endif # 2.40.3 so we get the UNLIMITED open flag librsvg_dep = dependency('librsvg-2.0', version: '>=2.40.3', required: get_option('rsvg')) cairo_dep = dependency('cairo', version: '>=1.2', required: get_option('rsvg')) -if librsvg_dep.found() and cairo_dep.found() +librsvg_found = librsvg_dep.found() and cairo_dep.found() +if librsvg_found libvips_deps += librsvg_dep libvips_deps += cairo_dep cfg_var.set('HAVE_RSVG', '1') endif openslide_dep = dependency('openslide', version: '>=3.3.0', required: get_option('openslide')) +openslide_module = false if openslide_dep.found() - if modules_enabled and not get_option('openslide-module').disabled() + openslide_module = modules_enabled and not get_option('openslide-module').disabled() + if openslide_module cfg_var.set('OPENSLIDE_MODULE', '1') else libvips_deps += openslide_dep @@ -430,8 +438,10 @@ endif libheif_dep = dependency('libheif', version: '>=0.4.11', required: get_option('heif')) +libheif_module = false if libheif_dep.found() - if modules_enabled and not get_option('heif-module').disabled() + libheif_module = modules_enabled and not get_option('heif-module').disabled() + if libheif_module cfg_var.set('HEIF_MODULE', '1') else libvips_deps += libheif_dep @@ -460,8 +470,11 @@ endif libjxl_dep = dependency('libjxl', version: '>=0.5', required: get_option('jpeg-xl')) libjxl_threads_dep = dependency('libjxl_threads', version: '>=0.5', required: get_option('jpeg-xl')) -if libjxl_dep.found() and libjxl_threads_dep.found() - if modules_enabled and not get_option('jpeg-xl-module').disabled() +libjxl_found = libjxl_dep.found() and libjxl_threads_dep.found() +libjxl_module = false +if libjxl_found + libjxl_module = modules_enabled and not get_option('jpeg-xl-module').disabled() + if libjxl_module cfg_var.set('LIBJXL_MODULE', '1') else libvips_deps += libjxl_dep @@ -474,13 +487,17 @@ if libjxl_dep.found() and libjxl_threads_dep.found() endif libpoppler_dep = dependency('poppler-glib', version: '>=0.16.0', required: get_option('poppler')) +libpoppler_found = false +libpoppler_module = false if not cairo_dep.found() cairo_dep = dependency('cairo', version: '>=1.2', required: get_option('poppler')) endif if libpoppler_dep.found() and cairo_dep.found() and pdfium_dep.found() message('PDFium has been found, ignoring Poppler support') elif libpoppler_dep.found() and cairo_dep.found() - if modules_enabled and not get_option('poppler-module').disabled() + libpoppler_found = true + libpoppler_module = modules_enabled and not get_option('poppler-module').disabled() + if libpoppler_module cfg_var.set('POPPLER_MODULE', '1') else libvips_deps += libpoppler_dep @@ -524,7 +541,8 @@ if nifti_prefix_dir != '' and not libnifti_dep.found() znz_lib = cc.find_library('znz', has_headers: ['znzlib.h'], header_include_directories: nifti_inc, required: get_option('nifti')) libnifti_dep = declare_dependency(dependencies: [nifti_lib, znz_lib], include_directories: nifti_inc) endif -if not get_option('nifti').disabled() and libnifti_dep.found() +libnifti_found = not get_option('nifti').disabled() and libnifti_dep.found() +if libnifti_found libvips_deps += libnifti_dep cfg_var.set('HAVE_NIFTI', '1') endif @@ -607,6 +625,59 @@ config_dep = declare_dependency( libvips_deps += config_dep +build_summary = { + 'Build options': + {'enable debug': [get_option('debug')], + 'enable deprecated': [get_option('deprecated')], + 'enable modules': [modules_enabled], + 'enable gtk-doc': [get_option('gtk_doc')], + 'enable doxygen': [get_option('doxygen')], + 'enable introspection': [get_option('introspection')], + 'enable RAD load/save': [get_option('radiance')], + 'enable Analyze7 load/save': [get_option('analyze')], + 'enable PPM load/save': [get_option('ppm')], + 'enable GIF load': [get_option('nsgif')], + }, + 'Optional external packages': + {'use fftw for FFTs': [fftw_dep.found()], + 'accelerate loops with ORC': [orc_dep.found()], + 'ICC profile support with lcms': [lcms_dep.found()], + 'zlib': [zlib_dep.found()], + 'text rendering with pangocairo': [pangocairo_dep.found()], + 'font file support with fontconfig': [fontconfig_found], + 'EXIF metadata support with libexif': [libexif_dep.found()], + }, + 'External image format libraries': + {'JPEG load/save with libjpeg': [libjpeg_dep.found()], + 'JXL load/save with libjxl': [libjxl_found, ' (dynamic module: ', libjxl_module, ')'], + 'JPEG2000 load/save with OpenJPEG': [libopenjp2_dep.found()], + 'PNG load/save with libspng': [spng_found], + 'PNG load/save with libpng': [png_dep.found()], + 'selected quantisation package': [quantisation_package.found() ? quantisation_package.name() : 'none'], + 'TIFF load/save with libtiff': [libtiff_dep.found()], + 'image pyramid save with libgsf': [gsf_dep.found()], + 'HEIC/AVIF load/save with libheif': [libheif_dep.found(), ' (dynamic module: ', libheif_module, ')'], + 'WebP load/save with libwebp': [libwebp_dep.found()], + 'PDF load with PDFium': [pdfium_dep.found()], + 'PDF load with poppler-glib': [libpoppler_found, ' (dynamic module: ', libpoppler_module, ')'], + 'SVG load with librsvg': [librsvg_found], + 'EXR load with OpenEXR': [openexr_dep.found()], + 'OpenSlide load': [openslide_dep.found(), ' (dynamic module: ', openslide_module, ')'], + 'Matlab load with libmatio': [matio_dep.found()], + 'NIfTI load/save with niftiio': [libnifti_found], + 'FITS load/save with cfitsio': [cfitsio_dep.found()], + 'GIF save with cgif': [cgif_dep.found()], + 'selected Magick package': [magick_found ? magick_dep.name() : 'none', ' (dynamic module: ', magick_module, ')'], + 'Magick API version': [magick_found ? 'magick' + magick_dep.version().split('.')[0] : 'none'], + 'Magick load': [magick_found and 'load' in get_option('magick-features')], + 'Magick save': [magick_found and 'save' in get_option('magick-features')], + }, +} + +foreach section_title, section : build_summary + summary(section, bool_yn: true, list_sep: '', section: section_title) +endforeach + subdir('libvips') if get_option('gtk_doc') subdir('doc') From 2c4c0390564da4acf4186663b6bcd1c4ccbe96d8 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 2 Aug 2022 13:50:09 +0100 Subject: [PATCH 3/3] add "unlimited" to jpegload To disable DoS limits for JPEG loading. Adding API on a stable branch is bad, but this fixes a regression, so I think it's necessary, unfortunately. See https://github.com/libvips/libvips/issues/2973 --- .gitignore | 1 + ChangeLog | 1 + libvips/deprecated/im_jpeg2vips.c | 2 +- libvips/foreign/jpeg2vips.c | 37 ++++++++++++++++++++++--------- libvips/foreign/jpegload.c | 15 +++++++++++-- libvips/foreign/pforeign.h | 2 +- libvips/foreign/vips2jpeg.c | 6 ----- test/test_formats.sh | 2 +- 8 files changed, 44 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index c25e08b5..0924987b 100644 --- a/.gitignore +++ b/.gitignore @@ -154,6 +154,7 @@ tmp-* # Auto-generated tag files tags +TAGS ### End of VIM ### Distribution diff --git a/ChangeLog b/ChangeLog index 54af4ecc..7ac5dcb7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,7 @@ - fix im7 feature detection in meson - add a summary table at the end of configure in meson - fix libpng fallback when spng is disabled in meson +- add "unlimited" to jpegload 21/11/21 started 8.13 - configure fails for requested but unmet dependencies [remicollet] diff --git a/libvips/deprecated/im_jpeg2vips.c b/libvips/deprecated/im_jpeg2vips.c index a2cac637..bd26401c 100644 --- a/libvips/deprecated/im_jpeg2vips.c +++ b/libvips/deprecated/im_jpeg2vips.c @@ -117,7 +117,7 @@ jpeg2vips( const char *name, IMAGE *out, gboolean header_only ) if( !(source = vips_source_new_from_file( filename )) ) return( -1 ); if( vips__jpeg_read_source( source, out, - header_only, shrink, fail_on_warn, FALSE ) ) { + header_only, shrink, fail_on_warn, FALSE, FALSE ) ) { VIPS_UNREF( source ); return( -1 ); } diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index 0ee9af69..4f996ec2 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -112,6 +112,8 @@ * - set resolution unit from JFIF * 24/7/21 * - add fail_on support + * 2/8/22 + * - add "unlimited" */ /* @@ -169,6 +171,8 @@ /* Stuff we track during a read. */ typedef struct _ReadJpeg { + VipsImage *out; + /* Shrink by this much during load. 1, 2, 4, 8. */ int shrink; @@ -190,6 +194,10 @@ typedef struct _ReadJpeg { */ gboolean autorotate; + /* Remove DoS limits. + */ + gboolean unlimited; + /* cinfo->output_width and height can be larger than we want since * libjpeg rounds up on shrink-on-load. This is the real size we will * output, as opposed to the size we decompress to. @@ -251,8 +259,12 @@ source_fill_input_buffer( j_decompress_ptr cinfo ) src->pub.bytes_in_buffer = bytes_read; } else { - if( src->jpeg->fail_on >= VIPS_FAIL_ON_TRUNCATED ) + if( src->jpeg->fail_on >= VIPS_FAIL_ON_TRUNCATED ) { + /* Knock the output out of cache. + */ + vips_foreign_load_invalidate( src->jpeg->out ); ERREXIT( cinfo, JERR_INPUT_EOF ); + } else WARNMS( cinfo, JWRN_JPEG_EOF ); @@ -317,6 +329,8 @@ readjpeg_open_input( ReadJpeg *jpeg ) static void readjpeg_emit_message( j_common_ptr cinfo, int msg_level ) { + ReadJpeg *jpeg = (ReadJpeg *) cinfo->client_data; + long num_warnings; if( msg_level < 0 ) { @@ -325,11 +339,13 @@ readjpeg_emit_message( j_common_ptr cinfo, int msg_level ) num_warnings = ++cinfo->err->num_warnings; /* Corrupt files may give many warnings, the policy here is to - * show only the first warning and treat many warnings as fatal. + * show only the first warning and treat many warnings as fatal, + * unless unlimited is set. */ if( num_warnings == 1 ) (*cinfo->err->output_message)( cinfo ); - else if( num_warnings >= 100 ) + else if( !jpeg || + (!jpeg->unlimited && num_warnings >= 100) ) cinfo->err->error_exit( cinfo ); } else if( cinfo->err->trace_level >= msg_level ) @@ -381,13 +397,15 @@ readjpeg_minimise_cb( VipsImage *image, ReadJpeg *jpeg ) static ReadJpeg * readjpeg_new( VipsSource *source, VipsImage *out, - int shrink, VipsFailOn fail_on, gboolean autorotate ) + int shrink, VipsFailOn fail_on, gboolean autorotate, + gboolean unlimited ) { ReadJpeg *jpeg; if( !(jpeg = VIPS_NEW( out, ReadJpeg )) ) return( NULL ); + jpeg->out = out; jpeg->source = source; g_object_ref( source ); jpeg->shrink = shrink; @@ -399,11 +417,8 @@ readjpeg_new( VipsSource *source, VipsImage *out, jpeg->eman.fp = NULL; jpeg->y_pos = 0; jpeg->autorotate = autorotate; - - /* This is used by the error handlers to signal invalidate on the - * output image. - */ - jpeg->cinfo.client_data = out; + jpeg->unlimited = unlimited; + jpeg->cinfo.client_data = jpeg; /* jpeg_create_decompress() can fail on some sanity checks. Don't * readjpeg_free() since we don't want to jpeg_destroy_decompress(). @@ -982,12 +997,12 @@ vips__jpeg_read( ReadJpeg *jpeg, VipsImage *out, gboolean header_only ) int vips__jpeg_read_source( VipsSource *source, VipsImage *out, gboolean header_only, int shrink, VipsFailOn fail_on, - gboolean autorotate ) + gboolean autorotate, gboolean unlimited ) { ReadJpeg *jpeg; if( !(jpeg = readjpeg_new( source, out, shrink, fail_on, - autorotate )) ) + autorotate, unlimited )) ) return( -1 ); /* Here for longjmp() from vips__new_error_exit() during diff --git a/libvips/foreign/jpegload.c b/libvips/foreign/jpegload.c index 386f6942..04190587 100644 --- a/libvips/foreign/jpegload.c +++ b/libvips/foreign/jpegload.c @@ -74,6 +74,10 @@ typedef struct _VipsForeignLoadJpeg { */ VipsSource *source; + /* Remove DoS limits. + */ + gboolean unlimited; + /* Shrink by this much during load. */ int shrink; @@ -140,7 +144,7 @@ vips_foreign_load_jpeg_header( VipsForeignLoad *load ) if( vips__jpeg_read_source( jpeg->source, load->out, TRUE, jpeg->shrink, load->fail_on, - jpeg->autorotate ) ) + jpeg->autorotate, jpeg->unlimited ) ) return( -1 ); return( 0 ); @@ -153,7 +157,7 @@ vips_foreign_load_jpeg_load( VipsForeignLoad *load ) if( vips__jpeg_read_source( jpeg->source, load->real, FALSE, jpeg->shrink, load->fail_on, - jpeg->autorotate ) ) + jpeg->autorotate, jpeg->unlimited ) ) return( -1 ); return( 0 ); @@ -199,6 +203,13 @@ vips_foreign_load_jpeg_class_init( VipsForeignLoadJpegClass *class ) G_STRUCT_OFFSET( VipsForeignLoadJpeg, autorotate ), FALSE ); + VIPS_ARG_BOOL( class, "unlimited", 22, + _( "Unlimited" ), + _( "Remove all denial of service limits" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignLoadJpeg, unlimited ), + FALSE ); + } static void diff --git a/libvips/foreign/pforeign.h b/libvips/foreign/pforeign.h index e2c18ddb..e8cec087 100644 --- a/libvips/foreign/pforeign.h +++ b/libvips/foreign/pforeign.h @@ -153,7 +153,7 @@ int vips__jpeg_write_target( VipsImage *in, VipsTarget *target, int vips__jpeg_read_source( VipsSource *source, VipsImage *out, gboolean header_only, int shrink, VipsFailOn fail_on, - gboolean autorotate ); + gboolean autorotate, gboolean unlimited ); int vips__isjpeg_source( VipsSource *source ); int vips__png_ispng_source( VipsSource *source ); diff --git a/libvips/foreign/vips2jpeg.c b/libvips/foreign/vips2jpeg.c index 6fe1366f..01078f44 100644 --- a/libvips/foreign/vips2jpeg.c +++ b/libvips/foreign/vips2jpeg.c @@ -173,12 +173,6 @@ vips__new_output_message( j_common_ptr cinfo ) #ifdef DEBUG printf( "vips__new_output_message: \"%s\"\n", buffer ); #endif /*DEBUG*/ - - /* This is run for things like file truncated. Signal invalidate to - * force this op out of cache. - */ - if( cinfo->client_data ) - vips_foreign_load_invalidate( VIPS_IMAGE( cinfo->client_data ) ); } /* New error_exit handler. diff --git a/test/test_formats.sh b/test/test_formats.sh index 0f4c60d6..d3983f7f 100755 --- a/test/test_formats.sh +++ b/test/test_formats.sh @@ -204,7 +204,7 @@ if test_supported matload; then # test blocked and untrusted printf "testing VIPS_BLOCK_UNTRUSTED with matio ... " export VIPS_BLOCK_UNTRUSTED=1 - if vips matload $matlab $tmp/block.png; then + if $vips matload $matlab $tmp/block.png; then echo "failed to block matload" exit 1 fi