From: Michael Brown Date: Fri, 25 Apr 2025 15:43:11 +0000 (+0100) Subject: [png] Remove userptr_t from PNG image parsing X-Git-Tag: rolling/bin~367 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d29651ddec470c3b13eb6fc819f62eaeda10a0d9;p=thirdparty%2Fipxe.git [png] Remove userptr_t from PNG image parsing Signed-off-by: Michael Brown --- diff --git a/src/image/png.c b/src/image/png.c index 8b432e01a..b7864f770 100644 --- a/src/image/png.c +++ b/src/image/png.c @@ -197,12 +197,12 @@ static size_t png_scanline_len ( struct png_context *png, */ static int png_image_header ( struct image *image, struct png_context *png, size_t len ) { - struct png_image_header ihdr; + const struct png_image_header *ihdr; struct png_interlace interlace; unsigned int pass; /* Sanity check */ - if ( len != sizeof ( ihdr ) ) { + if ( len != sizeof ( *ihdr ) ) { DBGC ( image, "PNG %s invalid IHDR length %zd\n", image->name, len ); return -EINVAL; @@ -213,32 +213,32 @@ static int png_image_header ( struct image *image, struct png_context *png, } /* Extract image header */ - copy_from_user ( &ihdr, image->data, png->offset, len ); + ihdr = ( image->data + png->offset ); DBGC ( image, "PNG %s %dx%d depth %d type %d compression %d filter %d " - "interlace %d\n", image->name, ntohl ( ihdr.width ), - ntohl ( ihdr.height ), ihdr.depth, ihdr.colour_type, - ihdr.compression, ihdr.filter, ihdr.interlace ); + "interlace %d\n", image->name, ntohl ( ihdr->width ), + ntohl ( ihdr->height ), ihdr->depth, ihdr->colour_type, + ihdr->compression, ihdr->filter, ihdr->interlace ); /* Sanity checks */ - if ( ihdr.compression >= PNG_COMPRESSION_UNKNOWN ) { + if ( ihdr->compression >= PNG_COMPRESSION_UNKNOWN ) { DBGC ( image, "PNG %s unknown compression method %d\n", - image->name, ihdr.compression ); + image->name, ihdr->compression ); return -ENOTSUP; } - if ( ihdr.filter >= PNG_FILTER_UNKNOWN ) { + if ( ihdr->filter >= PNG_FILTER_UNKNOWN ) { DBGC ( image, "PNG %s unknown filter method %d\n", - image->name, ihdr.filter ); + image->name, ihdr->filter ); return -ENOTSUP; } - if ( ihdr.interlace >= PNG_INTERLACE_UNKNOWN ) { + if ( ihdr->interlace >= PNG_INTERLACE_UNKNOWN ) { DBGC ( image, "PNG %s unknown interlace method %d\n", - image->name, ihdr.interlace ); + image->name, ihdr->interlace ); return -ENOTSUP; } /* Allocate pixel buffer */ - png->pixbuf = alloc_pixbuf ( ntohl ( ihdr.width ), - ntohl ( ihdr.height ) ); + png->pixbuf = alloc_pixbuf ( ntohl ( ihdr->width ), + ntohl ( ihdr->height ) ); if ( ! png->pixbuf ) { DBGC ( image, "PNG %s could not allocate pixel buffer\n", image->name ); @@ -246,7 +246,7 @@ static int png_image_header ( struct image *image, struct png_context *png, } /* Extract bit depth */ - png->depth = ihdr.depth; + png->depth = ihdr->depth; if ( ( png->depth == 0 ) || ( ( png->depth & ( png->depth - 1 ) ) != 0 ) ) { DBGC ( image, "PNG %s invalid depth %d\n", @@ -255,17 +255,17 @@ static int png_image_header ( struct image *image, struct png_context *png, } /* Calculate number of channels */ - png->colour_type = ihdr.colour_type; + png->colour_type = ihdr->colour_type; png->channels = 1; - if ( ! ( ihdr.colour_type & PNG_COLOUR_TYPE_PALETTE ) ) { - if ( ihdr.colour_type & PNG_COLOUR_TYPE_RGB ) + if ( ! ( ihdr->colour_type & PNG_COLOUR_TYPE_PALETTE ) ) { + if ( ihdr->colour_type & PNG_COLOUR_TYPE_RGB ) png->channels += 2; - if ( ihdr.colour_type & PNG_COLOUR_TYPE_ALPHA ) + if ( ihdr->colour_type & PNG_COLOUR_TYPE_ALPHA ) png->channels += 1; } /* Calculate number of interlace passes */ - png->passes = png_interlace_passes[ihdr.interlace]; + png->passes = png_interlace_passes[ihdr->interlace]; /* Calculate length of raw data buffer */ for ( pass = 0 ; pass < png->passes ; pass++ ) { @@ -297,30 +297,28 @@ static int png_image_header ( struct image *image, struct png_context *png, */ static int png_palette ( struct image *image, struct png_context *png, size_t len ) { - size_t offset = png->offset; - struct png_palette_entry palette; + const struct png_palette_entry *palette; unsigned int i; /* Populate palette */ + palette = ( image->data + png->offset ); for ( i = 0 ; i < ( sizeof ( png->palette ) / sizeof ( png->palette[0] ) ) ; i++ ) { /* Stop when we run out of palette data */ - if ( len < sizeof ( palette ) ) + if ( len < sizeof ( *palette ) ) break; /* Extract palette entry */ - copy_from_user ( &palette, image->data, offset, - sizeof ( palette ) ); - png->palette[i] = ( ( palette.red << 16 ) | - ( palette.green << 8 ) | - ( palette.blue << 0 ) ); + png->palette[i] = ( ( palette->red << 16 ) | + ( palette->green << 8 ) | + ( palette->blue << 0 ) ); DBGC2 ( image, "PNG %s palette entry %d is %#06x\n", image->name, i, png->palette[i] ); /* Move to next entry */ - offset += sizeof ( palette ); - len -= sizeof ( palette ); + palette++; + len -= sizeof ( *palette ); } return 0; @@ -503,17 +501,16 @@ static struct png_filter png_filters[] = { */ static int png_unfilter_pass ( struct image *image, struct png_context *png, struct png_interlace *interlace ) { - size_t offset = png->raw.offset; size_t pixel_len = png_pixel_len ( png ); size_t scanline_len = png_scanline_len ( png, interlace ); + uint8_t *data = ( png->raw.data + png->raw.offset ); struct png_filter *filter; unsigned int scanline; unsigned int byte; - uint8_t filter_type; - uint8_t left; - uint8_t above; - uint8_t above_left; - uint8_t current; + unsigned int filter_type; + unsigned int left; + unsigned int above; + unsigned int above_left; /* On the first scanline of a pass, above bytes are assumed to * be zero. @@ -524,8 +521,7 @@ static int png_unfilter_pass ( struct image *image, struct png_context *png, for ( scanline = 0 ; scanline < interlace->height ; scanline++ ) { /* Extract filter byte and determine filter type */ - copy_from_user ( &filter_type, png->raw.data, offset++, - sizeof ( filter_type ) ); + filter_type = *(data++); if ( filter_type >= ( sizeof ( png_filters ) / sizeof ( png_filters[0] ) ) ) { DBGC ( image, "PNG %s unknown filter type %d\n", @@ -547,35 +543,24 @@ static int png_unfilter_pass ( struct image *image, struct png_context *png, for ( byte = 0 ; byte < ( scanline_len - 1 ) ; byte++ ) { /* Extract predictor bytes, if applicable */ - if ( byte >= pixel_len ) { - copy_from_user ( &left, png->raw.data, - ( offset - pixel_len ), - sizeof ( left ) ); - } - if ( scanline > 0 ) { - copy_from_user ( &above, png->raw.data, - ( offset - scanline_len ), - sizeof ( above ) ); - } + if ( byte >= pixel_len ) + left = *( data - pixel_len ); + if ( scanline > 0 ) + above = *( data - scanline_len ); if ( ( scanline > 0 ) && ( byte >= pixel_len ) ) { - copy_from_user ( &above_left, png->raw.data, - ( offset - scanline_len - - pixel_len ), - sizeof ( above_left ) ); + above_left = *( data - scanline_len - + pixel_len ); } /* Unfilter current byte */ - copy_from_user ( ¤t, png->raw.data, - offset, sizeof ( current ) ); - current = filter->unfilter ( current, left, above, - above_left ); - copy_to_user ( png->raw.data, offset++, - ¤t, sizeof ( current ) ); + *data = filter->unfilter ( *data, left, above, + above_left ); + data++; } } /* Update offset */ - png->raw.offset = offset; + png->raw.offset = ( ( ( void * ) data ) - png->raw.data ); return 0; } @@ -650,16 +635,16 @@ static inline unsigned int png_pixel ( unsigned int raw, unsigned int alpha, static void png_pixels_pass ( struct image *image, struct png_context *png, struct png_interlace *interlace ) { - size_t raw_offset = png->raw.offset; uint8_t channel[png->channels]; int is_indexed = ( png->colour_type & PNG_COLOUR_TYPE_PALETTE ); int is_rgb = ( png->colour_type & PNG_COLOUR_TYPE_RGB ); int has_alpha = ( png->colour_type & PNG_COLOUR_TYPE_ALPHA ); - size_t pixbuf_y_offset; - size_t pixbuf_offset; - size_t pixbuf_x_stride; - size_t pixbuf_y_stride; - size_t raw_stride; + const uint8_t *data = ( png->raw.data + png->raw.offset ); + size_t data_stride; + unsigned int pixbuf_y_index; + unsigned int pixbuf_index; + unsigned int pixbuf_x_stride; + unsigned int pixbuf_y_stride; unsigned int y; unsigned int x; unsigned int c; @@ -676,17 +661,16 @@ static void png_pixels_pass ( struct image *image, * as a bit depth of 8 with a stride of more than one. */ depth = png->depth; - raw_stride = ( ( depth + 7 ) / 8 ); + data_stride = ( ( depth + 7 ) / 8 ); if ( depth > 8 ) depth = 8; max = ( ( 1 << depth ) - 1 ); /* Calculate pixel buffer offset and strides */ - pixbuf_y_offset = ( ( ( interlace->y_indent * png->pixbuf->width ) + - interlace->x_indent ) * sizeof ( pixel ) ); - pixbuf_x_stride = ( interlace->x_stride * sizeof ( pixel ) ); - pixbuf_y_stride = ( interlace->y_stride * png->pixbuf->width * - sizeof ( pixel ) ); + pixbuf_y_index = ( ( ( interlace->y_indent * png->pixbuf->width ) + + interlace->x_indent ) ); + pixbuf_x_stride = interlace->x_stride; + pixbuf_y_stride = ( interlace->y_stride * png->pixbuf->width ); DBGC2 ( image, "PNG %s pass %d %dx%d at (%d,%d) stride (%d,%d)\n", image->name, interlace->pass, interlace->width, interlace->height, interlace->x_indent, interlace->y_indent, @@ -696,11 +680,11 @@ static void png_pixels_pass ( struct image *image, for ( y = 0 ; y < interlace->height ; y++ ) { /* Skip filter byte */ - raw_offset++; + data++; /* Iterate over each pixel in turn */ bits = depth; - pixbuf_offset = pixbuf_y_offset; + pixbuf_index = pixbuf_y_index; for ( x = 0 ; x < interlace->width ; x++ ) { /* Extract sample value */ @@ -710,11 +694,8 @@ static void png_pixels_pass ( struct image *image, current <<= depth; bits -= depth; if ( ! bits ) { - copy_from_user ( ¤t, - png->raw.data, - raw_offset, - sizeof ( current ) ); - raw_offset += raw_stride; + current = *data; + data += data_stride; bits = 8; } @@ -745,17 +726,16 @@ static void png_pixels_pass ( struct image *image, } /* Store pixel */ - copy_to_user ( png->pixbuf->data, pixbuf_offset, - &pixel, sizeof ( pixel ) ); - pixbuf_offset += pixbuf_x_stride; + png->pixbuf->data[pixbuf_index] = pixel; + pixbuf_index += pixbuf_x_stride; } /* Move to next output row */ - pixbuf_y_offset += pixbuf_y_stride; + pixbuf_y_index += pixbuf_y_stride; } /* Update offset */ - png->raw.offset = raw_offset; + png->raw.offset = ( ( ( const void * ) data ) - png->raw.data ); } /** @@ -903,8 +883,8 @@ static int png_chunk ( struct image *image, struct png_context *png, */ static int png_pixbuf ( struct image *image, struct pixel_buffer **pixbuf ) { struct png_context *png; - struct png_chunk_header header; - struct png_chunk_footer footer; + const struct png_chunk_header *header; + const struct png_chunk_footer *footer; size_t remaining; size_t chunk_len; int rc; @@ -923,20 +903,19 @@ static int png_pixbuf ( struct image *image, struct pixel_buffer **pixbuf ) { /* Extract chunk header */ remaining = ( image->len - png->offset ); - if ( remaining < ( sizeof ( header ) + sizeof ( footer ) ) ) { + if ( remaining < ( sizeof ( *header ) + sizeof ( *footer ) ) ){ DBGC ( image, "PNG %s truncated chunk header/footer " "at offset %zd\n", image->name, png->offset ); rc = -EINVAL; goto err_truncated; } - copy_from_user ( &header, image->data, png->offset, - sizeof ( header ) ); - png->offset += sizeof ( header ); + header = ( image->data + png->offset ); + png->offset += sizeof ( *header ); /* Validate chunk length */ - chunk_len = ntohl ( header.len ); - if ( chunk_len > ( remaining - sizeof ( header ) - - sizeof ( footer ) ) ) { + chunk_len = ntohl ( header->len ); + if ( chunk_len > ( remaining - sizeof ( *header ) - + sizeof ( *footer ) ) ) { DBGC ( image, "PNG %s truncated chunk data at offset " "%zd\n", image->name, png->offset ); rc = -EINVAL; @@ -944,17 +923,17 @@ static int png_pixbuf ( struct image *image, struct pixel_buffer **pixbuf ) { } /* Handle chunk */ - if ( ( rc = png_chunk ( image, png, header.type, + if ( ( rc = png_chunk ( image, png, header->type, chunk_len ) ) != 0 ) goto err_chunk; /* Move to next chunk */ - png->offset += ( chunk_len + sizeof ( footer ) ); + png->offset += ( chunk_len + sizeof ( *footer ) ); } while ( png->offset < image->len ); /* Check that we finished with an IEND chunk */ - if ( header.type != htonl ( PNG_TYPE_IEND ) ) { + if ( header->type != htonl ( PNG_TYPE_IEND ) ) { DBGC ( image, "PNG %s did not finish with IEND\n", image->name ); rc = -EINVAL; @@ -984,17 +963,17 @@ static int png_pixbuf ( struct image *image, struct pixel_buffer **pixbuf ) { * @ret rc Return status code */ static int png_probe ( struct image *image ) { - struct png_signature signature; + const struct png_signature *signature; /* Sanity check */ - if ( image->len < sizeof ( signature ) ) { + if ( image->len < sizeof ( *signature ) ) { DBGC ( image, "PNG %s is too short\n", image->name ); return -ENOEXEC; } /* Check signature */ - copy_from_user ( &signature, image->data, 0, sizeof ( signature ) ); - if ( memcmp ( &signature, &png_signature, sizeof ( signature ) ) != 0 ){ + signature = image->data; + if ( memcmp ( signature, &png_signature, sizeof ( *signature ) ) != 0 ){ DBGC ( image, "PNG %s has invalid signature\n", image->name ); return -ENOEXEC; }