reduce stack use for radsave

fixes a crash on very low stack libcs like musl
This commit is contained in:
John Cupitt 2018-04-04 16:25:35 +01:00
parent 878c77a035
commit 632bce3c78
2 changed files with 21 additions and 4 deletions

View File

@ -1,5 +1,6 @@
12/3/18 started 8.6.4 12/3/18 started 8.6.4
- better fitting of fonts with overhanging edges, thanks Adrià - better fitting of fonts with overhanging edges, thanks Adrià
- lower stack use in radsave to help musl [Jacob Thrane Lund]
12/2/18 started 8.6.3 12/2/18 started 8.6.3
- use pkg-config to find libjpeg, if we can - use pkg-config to find libjpeg, if we can

View File

@ -19,6 +19,8 @@
* - add buffer save functions * - add buffer save functions
* 28/2/17 * 28/2/17
* - use dbuf for buffer output * - use dbuf for buffer output
* 4/4/17
* - reduce stack use to help musl
*/ */
/* /*
@ -885,10 +887,12 @@ rle_scanline_write( COLR *scanline, int width,
} }
} }
/* Write a single scanline. /* Write a single scanline. buffer is at least MAX_LINE bytes and is used to
* construct the RLE scanline. Don't allocate this on the stack so we don't
* die too horribly on small-stack libc.
*/ */
static int static int
scanline_write( COLR *scanline, int width, FILE *fp ) scanline_write( unsigned char *buffer, COLR *scanline, int width, FILE *fp )
{ {
if( width < MINELEN || if( width < MINELEN ||
width > MAXELEN ) width > MAXELEN )
@ -898,11 +902,12 @@ scanline_write( COLR *scanline, int width, FILE *fp )
else { else {
/* An RLE scanline. /* An RLE scanline.
*/ */
unsigned char buffer[MAX_LINE];
int length; int length;
rle_scanline_write( scanline, width, buffer, &length ); rle_scanline_write( scanline, width, buffer, &length );
g_assert( length <= MAX_LINE );
return( fwrite( buffer, 1, length, fp ) - length ); return( fwrite( buffer, 1, length, fp ) - length );
} }
} }
@ -1294,12 +1299,18 @@ static int
vips2rad_put_data_block( VipsRegion *region, VipsRect *area, void *a ) vips2rad_put_data_block( VipsRegion *region, VipsRect *area, void *a )
{ {
Write *write = (Write *) a; Write *write = (Write *) a;
size_t size;
unsigned char *buffer = vips_dbuf_get_write( &write->dbuf, &size );
int i; int i;
g_assert( size >= MAX_LINE );
for( i = 0; i < area->height; i++ ) { for( i = 0; i < area->height; i++ ) {
VipsPel *p = VIPS_REGION_ADDR( region, 0, area->top + i ); VipsPel *p = VIPS_REGION_ADDR( region, 0, area->top + i );
if( scanline_write( (COLR *) p, area->width, write->fout ) ) if( scanline_write( buffer,
(COLR *) p, area->width, write->fout ) )
return( -1 ); return( -1 );
} }
@ -1333,6 +1344,11 @@ vips__rad_save( VipsImage *in, const char *filename )
write->filename = vips_strdup( NULL, filename ); write->filename = vips_strdup( NULL, filename );
write->fout = vips__file_open_write( filename, FALSE ); write->fout = vips__file_open_write( filename, FALSE );
/* scanline_write() needs a buffer to write compressed scanlines to.
* We use the dbuf ... why not.
*/
vips_dbuf_allocate( &write->dbuf, MAX_LINE );
if( !write->filename || if( !write->filename ||
!write->fout || !write->fout ||
vips2rad_put_header( write ) || vips2rad_put_header( write ) ||