This commit is contained in:
John Cupitt 2009-03-20 15:23:41 +00:00
parent d2a0d4468f
commit 74b0bf80ad
6 changed files with 41 additions and 54 deletions

View File

@ -360,10 +360,11 @@ typedef struct im__IMAGE {
GSList *preclosefns; /* list of pre-close callbacks */
GSList *invalidatefns; /* list of invalidate callbacks */
/* Set this to indicate a truncated file. We've been able to read the
* header, but don't try reading outside the file size.
/* Record the file length here. We use this to stop ourselves mapping
* things beyond the end of the file in the case that the file has
* been truncated.
*/
int nodata;
size_t file_length;
} IMAGE;
/* Only define if IM_ENABLE_DEPRECATED is set.

View File

@ -83,7 +83,6 @@ IMAGE *
im_binfile( const char *name, int xs, int ys, int bands, int offset )
{
IMAGE *im;
gint64 length;
gint64 psize;
/* Check parameters.
@ -112,14 +111,14 @@ im_binfile( const char *name, int xs, int ys, int bands, int offset )
/* Read the file length and check against what we think
* the size should be.
*/
if( (length = im_file_length( im->fd )) == -1 ) {
if( (im->file_length = im_file_length( im->fd )) == -1 ) {
im_close( im );
return( NULL );
}
/* Very common, so special message.
*/
if( psize > length ) {
if( psize > im->file_length ) {
im_error( "im_binfile", _( "unable to open %s: "
"file has been truncated" ), im->filename );
im_close( im );
@ -129,7 +128,7 @@ im_binfile( const char *name, int xs, int ys, int bands, int offset )
/* Just wierd. Only print a warning for this, since we should
* still be able to process it without coredumps.
*/
if( psize < length )
if( psize < im->file_length )
im_warn( "im_binfile", _( "%s is longer than expected" ),
im->filename );

View File

@ -32,7 +32,7 @@
* 9/8/08
* - lock global image list (thanks lee)
* 19/3/09
* - add nodata
* - add file_length
*/
/*
@ -170,7 +170,7 @@ im_init( const char *filename )
im->preclosefns = NULL;
im->invalidatefns = NULL;
im->nodata = 0;
im->file_length = 0;
if( !(im->filename = im_strdup( NULL, filename )) ) {
im_close( im );

View File

@ -210,7 +210,6 @@ im__munmap( void *start, size_t length )
int
im_mapfile( IMAGE *im )
{
gint64 length;
struct stat st;
mode_t m;
@ -219,15 +218,14 @@ im_mapfile( IMAGE *im )
/* Check the size of the file; if it is less than 64 bytes, then flag
* an error.
*/
if( (length = im_file_length( im->fd )) == -1 )
return( -1 );
g_assert( im->file_length > 0 );
if( fstat( im->fd, &st ) == -1 ) {
im_error( "im_mapfile",
"%s", _( "unable to get file status" ) );
return( -1 );
}
m = (mode_t) st.st_mode;
if( length < 64 ) {
if( im->file_length < 64 ) {
im_error( "im_mapfile",
"%s", _( "file is less than 64 bytes" ) );
return( -1 );
@ -238,13 +236,10 @@ im_mapfile( IMAGE *im )
return( -1 );
}
if( !(im->baseaddr = im__mmap( im->fd, 0, length, 0 )) )
if( !(im->baseaddr = im__mmap( im->fd, 0, im->file_length, 0 )) )
return( -1 );
/* im__mmap() will fail for >2GB, so this is safe even for large
* files.
*/
im->length = length;
im->length = im->file_length;
return( 0 );
}
@ -254,7 +249,6 @@ im_mapfile( IMAGE *im )
int
im_mapfilerw( IMAGE *im )
{
gint64 length;
struct stat st;
mode_t m;
@ -263,27 +257,23 @@ im_mapfilerw( IMAGE *im )
/* Check the size of the file if it is less than 64 bytes return
* make also sure that it is a regular file
*/
if( (length = im_file_length( im->fd )) == -1 )
return( -1 );
g_assert( im->file_length > 0 );
if( fstat( im->fd, &st ) == -1 ) {
im_error( "im_mapfilerw",
"%s", _( "unable to get file status" ) );
return( -1 );
}
m = (mode_t) st.st_mode;
if( length < 64 || !S_ISREG( m ) ) {
if( im->file_length < 64 || !S_ISREG( m ) ) {
im_error( "im_mapfile",
"%s", _( "unable to read data" ) );
return( -1 );
}
if( !(im->baseaddr = im__mmap( im->fd, 1, length, 0 )) )
if( !(im->baseaddr = im__mmap( im->fd, 1, im->file_length, 0 )) )
return( -1 );
/* im__mmap() will fail for >2GB, so this is safe even for large
* files.
*/
im->length = length;
im->length = im->file_length;
return( 0 );
}

View File

@ -325,14 +325,12 @@ read_chunk( int fd, gint64 offset, size_t length )
int
im__has_extension_block( IMAGE *im )
{
gint64 length;
gint64 psize;
psize = im__image_pixel_length( im );
if( (length = im_file_length( im->fd )) == -1 )
return( 0 );
g_assert( im->file_length > 0 );
return( length - psize > 0 );
return( im->file_length - psize > 0 );
}
/* Read everything after the pixels into memory.
@ -340,29 +338,27 @@ im__has_extension_block( IMAGE *im )
void *
im__read_extension_block( IMAGE *im, int *size )
{
gint64 length;
gint64 psize;
void *buf;
psize = im__image_pixel_length( im );
if( (length = im_file_length( im->fd )) == -1 )
return( NULL );
if( length - psize > 10 * 1024 * 1024 ) {
g_assert( im->file_length > 0 );
if( im->file_length - psize > 10 * 1024 * 1024 ) {
im_error( "im_readhist",
"%s", _( "more than a 10 megabytes of XML? "
"sufferin' succotash!" ) );
return( NULL );
}
if( length - psize == 0 )
if( im->file_length - psize == 0 )
return( NULL );
if( !(buf = read_chunk( im->fd, psize, length - psize )) )
if( !(buf = read_chunk( im->fd, psize, im->file_length - psize )) )
return( NULL );
if( size )
*size = length - psize;
*size = im->file_length - psize;
#ifdef DEBUG
printf( "im__read_extension_block: read %d bytes from %s\n",
(int) (length - psize), im->filename );
(int) (im->file_length - psize), im->filename );
printf( "data: \"%s\"\n", (char *) buf );
#endif /*DEBUG*/
@ -896,7 +892,6 @@ im__read_header( IMAGE *image )
*/
unsigned char header[IM_SIZEOF_HEADER];
gint64 length;
gint64 psize;
image->dtype = IM_OPENIN;
@ -913,13 +908,11 @@ im__read_header( IMAGE *image )
/* Predict and check the file size.
*/
psize = im__image_pixel_length( image );
if( (length = im_file_length( image->fd )) == -1 )
if( (image->file_length = im_file_length( image->fd )) == -1 )
return( -1 );
if( psize > length ) {
if( psize > image->file_length )
im_warn( "im_openin", _( "unable to read data for \"%s\", %s" ),
image->filename, _( "file has been truncated" ) );
image->nodata = 1;
}
/* Set demand style. Allow the most permissive sort.
*/
@ -960,9 +953,13 @@ im_openin( IMAGE *image )
if( im__read_header( image ) )
return( -1 );
/* Make sure we can map the whole thing without running over the VM
* limit or running out of file.
*/
size = (gint64) IM_IMAGE_SIZEOF_LINE( image ) * image->Ysize +
image->sizeof_header;
if( size < im__mmap_limit && !image->nodata ) {
if( size < im__mmap_limit &&
image->file_length >= size ) {
if( im_mapfile( image ) )
return( -1 );
image->data = image->baseaddr + image->sizeof_header;

View File

@ -219,15 +219,6 @@ im_window_set( im_window_t *window, int top, int height )
gint64 start, end, pagestart;
size_t length, pagelength;
/* Make sure this image has data.
*/
if( window->im->nodata ) {
im_error( "im_window_set",
_( "unable to read data for \"%s\", %s" ),
window->im->filename, _( "file has been truncated" ) );
return( -1 );
}
/* Calculate start and length for our window.
*/
start = window->im->sizeof_header +
@ -238,6 +229,15 @@ im_window_set( im_window_t *window, int top, int height )
end = start + length;
pagelength = end - pagestart;
/* Make sure we have enough file.
*/
if( end > window->im->file_length ) {
im_error( "im_window_set",
_( "unable to read data for \"%s\", %s" ),
window->im->filename, _( "file has been truncated" ) );
return( -1 );
}
if( !(baseaddr = im__mmap( window->im->fd, 0, pagelength, pagestart )) )
return( -1 );