]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[png] Remove userptr_t from PNG image parsing
authorMichael Brown <mcb30@ipxe.org>
Fri, 25 Apr 2025 15:43:11 +0000 (16:43 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 25 Apr 2025 15:43:11 +0000 (16:43 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/image/png.c

index 8b432e01af0739a8c7da63fe80da01dfccaa9cc7..b7864f770d39128a160e000a9f09b47d62f4c475 100644 (file)
@@ -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 ( &current, png->raw.data,
-                                        offset, sizeof ( current ) );
-                       current = filter->unfilter ( current, left, above,
-                                                    above_left );
-                       copy_to_user ( png->raw.data, offset++,
-                                      &current, 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 ( &current,
-                                                        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;
        }