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
This commit is contained in:
parent
a6fa62605c
commit
2c4c039056
1
.gitignore
vendored
1
.gitignore
vendored
@ -154,6 +154,7 @@ tmp-*
|
|||||||
|
|
||||||
# Auto-generated tag files
|
# Auto-generated tag files
|
||||||
tags
|
tags
|
||||||
|
TAGS
|
||||||
### End of VIM
|
### End of VIM
|
||||||
|
|
||||||
### Distribution
|
### Distribution
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
- fix im7 feature detection in meson
|
- fix im7 feature detection in meson
|
||||||
- add a summary table at the end of configure in meson
|
- add a summary table at the end of configure in meson
|
||||||
- fix libpng fallback when spng is disabled in meson
|
- fix libpng fallback when spng is disabled in meson
|
||||||
|
- add "unlimited" to jpegload
|
||||||
|
|
||||||
21/11/21 started 8.13
|
21/11/21 started 8.13
|
||||||
- configure fails for requested but unmet dependencies [remicollet]
|
- configure fails for requested but unmet dependencies [remicollet]
|
||||||
|
@ -117,7 +117,7 @@ jpeg2vips( const char *name, IMAGE *out, gboolean header_only )
|
|||||||
if( !(source = vips_source_new_from_file( filename )) )
|
if( !(source = vips_source_new_from_file( filename )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
if( vips__jpeg_read_source( source, out,
|
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 );
|
VIPS_UNREF( source );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,8 @@
|
|||||||
* - set resolution unit from JFIF
|
* - set resolution unit from JFIF
|
||||||
* 24/7/21
|
* 24/7/21
|
||||||
* - add fail_on support
|
* - add fail_on support
|
||||||
|
* 2/8/22
|
||||||
|
* - add "unlimited"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -169,6 +171,8 @@
|
|||||||
/* Stuff we track during a read.
|
/* Stuff we track during a read.
|
||||||
*/
|
*/
|
||||||
typedef struct _ReadJpeg {
|
typedef struct _ReadJpeg {
|
||||||
|
VipsImage *out;
|
||||||
|
|
||||||
/* Shrink by this much during load. 1, 2, 4, 8.
|
/* Shrink by this much during load. 1, 2, 4, 8.
|
||||||
*/
|
*/
|
||||||
int shrink;
|
int shrink;
|
||||||
@ -190,6 +194,10 @@ typedef struct _ReadJpeg {
|
|||||||
*/
|
*/
|
||||||
gboolean autorotate;
|
gboolean autorotate;
|
||||||
|
|
||||||
|
/* Remove DoS limits.
|
||||||
|
*/
|
||||||
|
gboolean unlimited;
|
||||||
|
|
||||||
/* cinfo->output_width and height can be larger than we want since
|
/* 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
|
* libjpeg rounds up on shrink-on-load. This is the real size we will
|
||||||
* output, as opposed to the size we decompress to.
|
* 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;
|
src->pub.bytes_in_buffer = bytes_read;
|
||||||
}
|
}
|
||||||
else {
|
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 );
|
ERREXIT( cinfo, JERR_INPUT_EOF );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
WARNMS( cinfo, JWRN_JPEG_EOF );
|
WARNMS( cinfo, JWRN_JPEG_EOF );
|
||||||
|
|
||||||
@ -317,6 +329,8 @@ readjpeg_open_input( ReadJpeg *jpeg )
|
|||||||
static void
|
static void
|
||||||
readjpeg_emit_message( j_common_ptr cinfo, int msg_level )
|
readjpeg_emit_message( j_common_ptr cinfo, int msg_level )
|
||||||
{
|
{
|
||||||
|
ReadJpeg *jpeg = (ReadJpeg *) cinfo->client_data;
|
||||||
|
|
||||||
long num_warnings;
|
long num_warnings;
|
||||||
|
|
||||||
if( msg_level < 0 ) {
|
if( msg_level < 0 ) {
|
||||||
@ -325,11 +339,13 @@ readjpeg_emit_message( j_common_ptr cinfo, int msg_level )
|
|||||||
num_warnings = ++cinfo->err->num_warnings;
|
num_warnings = ++cinfo->err->num_warnings;
|
||||||
|
|
||||||
/* Corrupt files may give many warnings, the policy here is to
|
/* 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 )
|
if( num_warnings == 1 )
|
||||||
(*cinfo->err->output_message)( cinfo );
|
(*cinfo->err->output_message)( cinfo );
|
||||||
else if( num_warnings >= 100 )
|
else if( !jpeg ||
|
||||||
|
(!jpeg->unlimited && num_warnings >= 100) )
|
||||||
cinfo->err->error_exit( cinfo );
|
cinfo->err->error_exit( cinfo );
|
||||||
}
|
}
|
||||||
else if( cinfo->err->trace_level >= msg_level )
|
else if( cinfo->err->trace_level >= msg_level )
|
||||||
@ -381,13 +397,15 @@ readjpeg_minimise_cb( VipsImage *image, ReadJpeg *jpeg )
|
|||||||
|
|
||||||
static ReadJpeg *
|
static ReadJpeg *
|
||||||
readjpeg_new( VipsSource *source, VipsImage *out,
|
readjpeg_new( VipsSource *source, VipsImage *out,
|
||||||
int shrink, VipsFailOn fail_on, gboolean autorotate )
|
int shrink, VipsFailOn fail_on, gboolean autorotate,
|
||||||
|
gboolean unlimited )
|
||||||
{
|
{
|
||||||
ReadJpeg *jpeg;
|
ReadJpeg *jpeg;
|
||||||
|
|
||||||
if( !(jpeg = VIPS_NEW( out, ReadJpeg )) )
|
if( !(jpeg = VIPS_NEW( out, ReadJpeg )) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
|
|
||||||
|
jpeg->out = out;
|
||||||
jpeg->source = source;
|
jpeg->source = source;
|
||||||
g_object_ref( source );
|
g_object_ref( source );
|
||||||
jpeg->shrink = shrink;
|
jpeg->shrink = shrink;
|
||||||
@ -399,11 +417,8 @@ readjpeg_new( VipsSource *source, VipsImage *out,
|
|||||||
jpeg->eman.fp = NULL;
|
jpeg->eman.fp = NULL;
|
||||||
jpeg->y_pos = 0;
|
jpeg->y_pos = 0;
|
||||||
jpeg->autorotate = autorotate;
|
jpeg->autorotate = autorotate;
|
||||||
|
jpeg->unlimited = unlimited;
|
||||||
/* This is used by the error handlers to signal invalidate on the
|
jpeg->cinfo.client_data = jpeg;
|
||||||
* output image.
|
|
||||||
*/
|
|
||||||
jpeg->cinfo.client_data = out;
|
|
||||||
|
|
||||||
/* jpeg_create_decompress() can fail on some sanity checks. Don't
|
/* jpeg_create_decompress() can fail on some sanity checks. Don't
|
||||||
* readjpeg_free() since we don't want to jpeg_destroy_decompress().
|
* 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
|
int
|
||||||
vips__jpeg_read_source( VipsSource *source, VipsImage *out,
|
vips__jpeg_read_source( VipsSource *source, VipsImage *out,
|
||||||
gboolean header_only, int shrink, VipsFailOn fail_on,
|
gboolean header_only, int shrink, VipsFailOn fail_on,
|
||||||
gboolean autorotate )
|
gboolean autorotate, gboolean unlimited )
|
||||||
{
|
{
|
||||||
ReadJpeg *jpeg;
|
ReadJpeg *jpeg;
|
||||||
|
|
||||||
if( !(jpeg = readjpeg_new( source, out, shrink, fail_on,
|
if( !(jpeg = readjpeg_new( source, out, shrink, fail_on,
|
||||||
autorotate )) )
|
autorotate, unlimited )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
/* Here for longjmp() from vips__new_error_exit() during
|
/* Here for longjmp() from vips__new_error_exit() during
|
||||||
|
@ -74,6 +74,10 @@ typedef struct _VipsForeignLoadJpeg {
|
|||||||
*/
|
*/
|
||||||
VipsSource *source;
|
VipsSource *source;
|
||||||
|
|
||||||
|
/* Remove DoS limits.
|
||||||
|
*/
|
||||||
|
gboolean unlimited;
|
||||||
|
|
||||||
/* Shrink by this much during load.
|
/* Shrink by this much during load.
|
||||||
*/
|
*/
|
||||||
int shrink;
|
int shrink;
|
||||||
@ -140,7 +144,7 @@ vips_foreign_load_jpeg_header( VipsForeignLoad *load )
|
|||||||
|
|
||||||
if( vips__jpeg_read_source( jpeg->source,
|
if( vips__jpeg_read_source( jpeg->source,
|
||||||
load->out, TRUE, jpeg->shrink, load->fail_on,
|
load->out, TRUE, jpeg->shrink, load->fail_on,
|
||||||
jpeg->autorotate ) )
|
jpeg->autorotate, jpeg->unlimited ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -153,7 +157,7 @@ vips_foreign_load_jpeg_load( VipsForeignLoad *load )
|
|||||||
|
|
||||||
if( vips__jpeg_read_source( jpeg->source,
|
if( vips__jpeg_read_source( jpeg->source,
|
||||||
load->real, FALSE, jpeg->shrink, load->fail_on,
|
load->real, FALSE, jpeg->shrink, load->fail_on,
|
||||||
jpeg->autorotate ) )
|
jpeg->autorotate, jpeg->unlimited ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -199,6 +203,13 @@ vips_foreign_load_jpeg_class_init( VipsForeignLoadJpegClass *class )
|
|||||||
G_STRUCT_OFFSET( VipsForeignLoadJpeg, autorotate ),
|
G_STRUCT_OFFSET( VipsForeignLoadJpeg, autorotate ),
|
||||||
FALSE );
|
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
|
static void
|
||||||
|
@ -153,7 +153,7 @@ int vips__jpeg_write_target( VipsImage *in, VipsTarget *target,
|
|||||||
|
|
||||||
int vips__jpeg_read_source( VipsSource *source, VipsImage *out,
|
int vips__jpeg_read_source( VipsSource *source, VipsImage *out,
|
||||||
gboolean header_only, int shrink, VipsFailOn fail_on,
|
gboolean header_only, int shrink, VipsFailOn fail_on,
|
||||||
gboolean autorotate );
|
gboolean autorotate, gboolean unlimited );
|
||||||
int vips__isjpeg_source( VipsSource *source );
|
int vips__isjpeg_source( VipsSource *source );
|
||||||
|
|
||||||
int vips__png_ispng_source( VipsSource *source );
|
int vips__png_ispng_source( VipsSource *source );
|
||||||
|
@ -173,12 +173,6 @@ vips__new_output_message( j_common_ptr cinfo )
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf( "vips__new_output_message: \"%s\"\n", buffer );
|
printf( "vips__new_output_message: \"%s\"\n", buffer );
|
||||||
#endif /*DEBUG*/
|
#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.
|
/* New error_exit handler.
|
||||||
|
@ -204,7 +204,7 @@ if test_supported matload; then
|
|||||||
# test blocked and untrusted
|
# test blocked and untrusted
|
||||||
printf "testing VIPS_BLOCK_UNTRUSTED with matio ... "
|
printf "testing VIPS_BLOCK_UNTRUSTED with matio ... "
|
||||||
export VIPS_BLOCK_UNTRUSTED=1
|
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"
|
echo "failed to block matload"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user