]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[deflate] Remove userptr_t from decompression code
authorMichael Brown <mcb30@ipxe.org>
Tue, 22 Apr 2025 11:13:22 +0000 (12:13 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 22 Apr 2025 11:32:12 +0000 (12:32 +0100)
Simplify the deflate, zlib, and gzip decompression code by assuming
that all content is fully accessible via pointer dereferences.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/crypto/deflate.c
src/image/gzip.c
src/image/png.c
src/image/zlib.c
src/include/ipxe/deflate.h
src/include/ipxe/zlib.h
src/tests/deflate_test.c
src/tests/gzip_test.c
src/tests/zlib_test.c

index c6cce75166e2ad39c99c199ace8866c69aca648a..5d01011846aff61f0766961c340590f6991682f9 100644 (file)
@@ -28,7 +28,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <errno.h>
 #include <assert.h>
 #include <ctype.h>
-#include <ipxe/uaccess.h>
 #include <ipxe/deflate.h>
 
 /** @file
@@ -300,24 +299,21 @@ static int deflate_alphabet ( struct deflate *deflate,
  * Attempt to accumulate bits from input stream
  *
  * @v deflate          Decompressor
- * @v in               Compressed input data
  * @v target           Number of bits to accumulate
  * @ret excess         Number of excess bits accumulated (may be negative)
  */
 static int deflate_accumulate ( struct deflate *deflate,
-                               struct deflate_chunk *in,
                                unsigned int target ) {
        uint8_t byte;
 
        while ( deflate->bits < target ) {
 
                /* Check for end of input */
-               if ( in->offset >= in->len )
+               if ( deflate->in == deflate->end )
                        break;
 
                /* Acquire byte from input */
-               copy_from_user ( &byte, in->data, in->offset++,
-                                sizeof ( byte ) );
+               byte = *(deflate->in++);
                deflate->accumulator = ( deflate->accumulator |
                                         ( byte << deflate->bits ) );
                deflate->rotalumucca = ( deflate->rotalumucca |
@@ -359,12 +355,10 @@ static int deflate_consume ( struct deflate *deflate, unsigned int count ) {
  * Attempt to extract a fixed number of bits from input stream
  *
  * @v deflate          Decompressor
- * @v in               Compressed input data
  * @v target           Number of bits to extract
  * @ret data           Extracted bits (or negative if not yet accumulated)
  */
-static int deflate_extract ( struct deflate *deflate, struct deflate_chunk *in,
-                            unsigned int target ) {
+static int deflate_extract ( struct deflate *deflate, unsigned int target ) {
        int excess;
        int data;
 
@@ -373,7 +367,7 @@ static int deflate_extract ( struct deflate *deflate, struct deflate_chunk *in,
                return 0;
 
        /* Attempt to accumulate bits */
-       excess = deflate_accumulate ( deflate, in, target );
+       excess = deflate_accumulate ( deflate, target );
        if ( excess < 0 )
                return excess;
 
@@ -389,12 +383,10 @@ static int deflate_extract ( struct deflate *deflate, struct deflate_chunk *in,
  * Attempt to decode a Huffman-coded symbol from input stream
  *
  * @v deflate          Decompressor
- * @v in               Compressed input data
  * @v alphabet         Huffman alphabet
  * @ret code           Raw code (or negative if not yet accumulated)
  */
 static int deflate_decode ( struct deflate *deflate,
-                           struct deflate_chunk *in,
                            struct deflate_alphabet *alphabet ) {
        struct deflate_huf_symbols *huf_sym;
        uint16_t huf;
@@ -407,7 +399,7 @@ static int deflate_decode ( struct deflate *deflate,
         * even if the stream still contains some complete
         * Huffman-coded symbols.
         */
-       deflate_accumulate ( deflate, in, DEFLATE_HUFFMAN_BITS );
+       deflate_accumulate ( deflate, DEFLATE_HUFFMAN_BITS );
 
        /* Normalise the bit-reversed accumulated value to 16 bits */
        huf = ( deflate->rotalumucca >> 16 );
@@ -449,24 +441,22 @@ static void deflate_discard_to_byte ( struct deflate *deflate ) {
  * Copy data to output buffer (if available)
  *
  * @v out              Output data buffer
- * @v start            Source data
- * @v offset           Starting offset within source data
+ * @v in               Input data
  * @v len              Length to copy
  */
-static void deflate_copy ( struct deflate_chunk *out,
-                          userptr_t start, size_t offset, size_t len ) {
-       size_t out_offset = out->offset;
+static void deflate_copy ( struct deflate_chunk *out, const void *in,
+                          size_t len ) {
+       const uint8_t *in_byte = in;
+       uint8_t *out_byte = ( out->data + out->offset );
        size_t copy_len;
 
        /* Copy data one byte at a time, to allow for overlap */
-       if ( out_offset < out->len ) {
-               copy_len = ( out->len - out_offset );
+       if ( out->offset < out->len ) {
+               copy_len = ( out->len - out->offset );
                if ( copy_len > len )
                        copy_len = len;
-               while ( copy_len-- ) {
-                       memcpy ( ( out->data + out_offset++ ),
-                                ( start + offset++ ), 1 );
-               }
+               while ( copy_len-- )
+                       *(out_byte++) = *(in_byte++);
        }
        out->offset += len;
 }
@@ -475,7 +465,8 @@ static void deflate_copy ( struct deflate_chunk *out,
  * Inflate compressed data
  *
  * @v deflate          Decompressor
- * @v in               Compressed input data
+ * @v data             Compressed input data
+ * @v len              Length of compressed input data
  * @v out              Output data buffer
  * @ret rc             Return status code
  *
@@ -489,10 +480,13 @@ static void deflate_copy ( struct deflate_chunk *out,
  * caller can use this to find the length of the decompressed data
  * before allocating the output data buffer.
  */
-int deflate_inflate ( struct deflate *deflate,
-                     struct deflate_chunk *in,
+int deflate_inflate ( struct deflate *deflate, const void *data, size_t len,
                      struct deflate_chunk *out ) {
 
+       /* Store input data pointers */
+       deflate->in = data;
+       deflate->end = ( data + len );
+
        /* This could be implemented more neatly if gcc offered a
         * means for enforcing tail recursion.
         */
@@ -509,7 +503,7 @@ int deflate_inflate ( struct deflate *deflate,
                int cm;
 
                /* Extract header */
-               header = deflate_extract ( deflate, in, ZLIB_HEADER_BITS );
+               header = deflate_extract ( deflate, ZLIB_HEADER_BITS );
                if ( header < 0 ) {
                        deflate->resume = &&zlib_header;
                        return 0;
@@ -538,7 +532,7 @@ int deflate_inflate ( struct deflate *deflate,
                int btype;
 
                /* Extract block header */
-               header = deflate_extract ( deflate, in, DEFLATE_HEADER_BITS );
+               header = deflate_extract ( deflate, DEFLATE_HEADER_BITS );
                if ( header < 0 ) {
                        deflate->resume = &&block_header;
                        return 0;
@@ -571,17 +565,17 @@ int deflate_inflate ( struct deflate *deflate,
        }
 
  literal_len: {
-               int len;
+               int llen;
 
                /* Extract LEN field */
-               len = deflate_extract ( deflate, in, DEFLATE_LITERAL_LEN_BITS );
-               if ( len < 0 ) {
+               llen = deflate_extract ( deflate, DEFLATE_LITERAL_LEN_BITS );
+               if ( llen < 0 ) {
                        deflate->resume = &&literal_len;
                        return 0;
                }
 
                /* Record length of literal data */
-               deflate->remaining = len;
+               deflate->remaining = llen;
                DBGC2 ( deflate, "DEFLATE %p literal block length %#04zx\n",
                        deflate, deflate->remaining );
        }
@@ -590,7 +584,7 @@ int deflate_inflate ( struct deflate *deflate,
                int nlen;
 
                /* Extract NLEN field */
-               nlen = deflate_extract ( deflate, in, DEFLATE_LITERAL_LEN_BITS);
+               nlen = deflate_extract ( deflate, DEFLATE_LITERAL_LEN_BITS );
                if ( nlen < 0 ) {
                        deflate->resume = &&literal_nlen;
                        return 0;
@@ -608,20 +602,20 @@ int deflate_inflate ( struct deflate *deflate,
 
  literal_data: {
                size_t in_remaining;
-               size_t len;
+               size_t dlen;
 
                /* Calculate available amount of literal data */
-               in_remaining = ( in->len - in->offset );
-               len = deflate->remaining;
-               if ( len > in_remaining )
-                       len = in_remaining;
+               in_remaining = ( deflate->end - deflate->in );
+               dlen = deflate->remaining;
+               if ( dlen > in_remaining )
+                       dlen = in_remaining;
 
                /* Copy data to output buffer */
-               deflate_copy ( out, in->data, in->offset, len );
+               deflate_copy ( out, deflate->in, dlen );
 
                /* Consume data from input buffer */
-               in->offset += len;
-               deflate->remaining -= len;
+               deflate->in += dlen;
+               deflate->remaining -= dlen;
 
                /* Finish processing if we are blocked */
                if ( deflate->remaining ) {
@@ -657,7 +651,7 @@ int deflate_inflate ( struct deflate *deflate,
                unsigned int hclen;
 
                /* Extract block header */
-               header = deflate_extract ( deflate, in, DEFLATE_DYNAMIC_BITS );
+               header = deflate_extract ( deflate, DEFLATE_DYNAMIC_BITS );
                if ( header < 0 ) {
                        deflate->resume = &&dynamic_header;
                        return 0;
@@ -684,7 +678,7 @@ int deflate_inflate ( struct deflate *deflate,
        }
 
  dynamic_codelen: {
-               int len;
+               int clen;
                unsigned int index;
                int rc;
 
@@ -692,18 +686,18 @@ int deflate_inflate ( struct deflate *deflate,
                while ( deflate->length_index < deflate->length_target ) {
 
                        /* Extract code length length */
-                       len = deflate_extract ( deflate, in,
-                                               DEFLATE_CODELEN_BITS );
-                       if ( len < 0 ) {
+                       clen = deflate_extract ( deflate,
+                                                DEFLATE_CODELEN_BITS );
+                       if ( clen < 0 ) {
                                deflate->resume = &&dynamic_codelen;
                                return 0;
                        }
 
                        /* Store code length */
                        index = deflate_codelen_map[deflate->length_index++];
-                       deflate_set_length ( deflate, index, len );
+                       deflate_set_length ( deflate, index, clen );
                        DBGCP ( deflate, "DEFLATE %p codelen for %d is %d\n",
-                               deflate, index, len );
+                               deflate, index, clen );
                }
 
                /* Generate code length alphabet */
@@ -722,25 +716,25 @@ int deflate_inflate ( struct deflate *deflate,
        }
 
  dynamic_litlen_distance: {
-               int len;
+               int clen;
                int index;
 
                /* Decode literal/length/distance code length */
-               len = deflate_decode ( deflate, in, &deflate->distance_codelen);
-               if ( len < 0 ) {
+               clen = deflate_decode ( deflate, &deflate->distance_codelen );
+               if ( clen < 0 ) {
                        deflate->resume = &&dynamic_litlen_distance;
                        return 0;
                }
 
                /* Prepare for extra bits */
-               if ( len < 16 ) {
-                       deflate->length = len;
+               if ( clen < 16 ) {
+                       deflate->length = clen;
                        deflate->extra_bits = 0;
                        deflate->dup_len = 1;
                } else {
                        static const uint8_t dup_len[3] = { 3, 3, 11 };
                        static const uint8_t extra_bits[3] = { 2, 3, 7 };
-                       index = ( len - 16 );
+                       index = ( clen - 16 );
                        deflate->dup_len = dup_len[index];
                        deflate->extra_bits = extra_bits[index];
                        if ( index )
@@ -753,7 +747,7 @@ int deflate_inflate ( struct deflate *deflate,
                unsigned int dup_len;
 
                /* Extract extra bits */
-               extra = deflate_extract ( deflate, in, deflate->extra_bits );
+               extra = deflate_extract ( deflate, deflate->extra_bits );
                if ( extra < 0 ) {
                        deflate->resume = &&dynamic_litlen_distance_extra;
                        return 0;
@@ -830,7 +824,7 @@ int deflate_inflate ( struct deflate *deflate,
                while ( 1 ) {
 
                        /* Decode Huffman code */
-                       code = deflate_decode ( deflate, in, &deflate->litlen );
+                       code = deflate_decode ( deflate, &deflate->litlen );
                        if ( code < 0 ) {
                                deflate->resume = &&lzhuf_litlen;
                                return 0;
@@ -844,8 +838,7 @@ int deflate_inflate ( struct deflate *deflate,
                                DBGCP ( deflate, "DEFLATE %p literal %#02x "
                                        "('%c')\n", deflate, byte,
                                        ( isprint ( byte ) ? byte : '.' ) );
-                               deflate_copy ( out, virt_to_user ( &byte ), 0,
-                                              sizeof ( byte ) );
+                               deflate_copy ( out, &byte, sizeof ( byte ) );
 
                        } else if ( code == DEFLATE_LITLEN_END ) {
 
@@ -876,7 +869,7 @@ int deflate_inflate ( struct deflate *deflate,
                int extra;
 
                /* Extract extra bits */
-               extra = deflate_extract ( deflate, in, deflate->extra_bits );
+               extra = deflate_extract ( deflate, deflate->extra_bits );
                if ( extra < 0 ) {
                        deflate->resume = &&lzhuf_litlen_extra;
                        return 0;
@@ -892,8 +885,7 @@ int deflate_inflate ( struct deflate *deflate,
                unsigned int bits;
 
                /* Decode Huffman code */
-               code = deflate_decode ( deflate, in,
-                                       &deflate->distance_codelen );
+               code = deflate_decode ( deflate, &deflate->distance_codelen );
                if ( code < 0 ) {
                        deflate->resume = &&lzhuf_distance;
                        return 0;
@@ -914,7 +906,7 @@ int deflate_inflate ( struct deflate *deflate,
                size_t dup_distance;
 
                /* Extract extra bits */
-               extra = deflate_extract ( deflate, in, deflate->extra_bits );
+               extra = deflate_extract ( deflate, deflate->extra_bits );
                if ( extra < 0 ) {
                        deflate->resume = &&lzhuf_distance_extra;
                        return 0;
@@ -934,7 +926,7 @@ int deflate_inflate ( struct deflate *deflate,
                }
 
                /* Copy data, allowing for overlap */
-               deflate_copy ( out, out->data, ( out->offset - dup_distance ),
+               deflate_copy ( out, ( out->data + out->offset - dup_distance ),
                               dup_len );
 
                /* Process next literal/length symbol */
@@ -972,7 +964,7 @@ int deflate_inflate ( struct deflate *deflate,
                 * cases involved in calling deflate_extract() to
                 * obtain a full 32 bits.
                 */
-               excess = deflate_accumulate ( deflate, in, ZLIB_ADLER32_BITS );
+               excess = deflate_accumulate ( deflate, ZLIB_ADLER32_BITS );
                if ( excess < 0 ) {
                        deflate->resume = &&zlib_adler32;
                        return 0;
index 116d912d795d7f6416d03b3302d0608623d2c2f1..b72c3243e27daac94d8b33c5463e7e823bf04278 100644 (file)
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 
 #include <stdlib.h>
+#include <string.h>
 #include <errno.h>
 #include <assert.h>
 #include <ipxe/deflate.h>
-#include <ipxe/uaccess.h>
 #include <ipxe/image.h>
 #include <ipxe/zlib.h>
 #include <ipxe/gzip.h>
@@ -46,83 +46,92 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  * @ret rc             Return status code
  */
 static int gzip_extract ( struct image *image, struct image *extracted ) {
-       struct gzip_header header;
-       struct gzip_extra_header extra;
-       struct gzip_crc_header crc;
-       struct gzip_footer footer;
-       struct deflate_chunk in;
-       unsigned int strings;
-       size_t offset;
+       const struct gzip_header *header;
+       const struct gzip_extra_header *extra;
+       const struct gzip_crc_header *crc;
+       const struct gzip_footer *footer;
+       const void *data;
+       size_t extra_len;
+       size_t string_len;
        size_t len;
-       off_t nul;
+       unsigned int strings;
        int rc;
 
        /* Sanity check */
-       assert ( image->len >= ( sizeof ( header ) + sizeof ( footer ) ) );
+       assert ( image->len >= ( sizeof ( *header ) + sizeof ( *footer ) ) );
+       data = image->data;
+       len = image->len;
 
        /* Extract footer */
-       len = ( image->len - sizeof ( footer ) );
-       copy_from_user ( &footer, image->data, len, sizeof ( footer ) );
+       assert ( len >= sizeof ( *footer ) );
+       len -= sizeof ( *footer );
+       footer = ( data + len );
 
        /* Extract fixed header */
-       copy_from_user ( &header, image->data, 0, sizeof ( header ) );
-       offset = sizeof ( header );
-       assert ( offset <= ( image->len - sizeof ( footer ) ) );
+       assert ( len >= sizeof ( *header ) );
+       header = data;
+       data += sizeof ( *header );
+       len -= sizeof ( *header );
 
        /* Skip extra header, if present */
-       if ( header.flags & GZIP_FL_EXTRA ) {
-               copy_from_user ( &extra, image->data, offset,
-                                sizeof ( extra ) );
-               offset += sizeof ( extra );
-               offset += le16_to_cpu ( extra.len );
-               if ( offset > len ) {
+       if ( header->flags & GZIP_FL_EXTRA ) {
+               if ( len < sizeof ( *extra ) ) {
                        DBGC ( image, "GZIP %p overlength extra header\n",
                               image );
                        return -EINVAL;
                }
+               extra = data;
+               data += sizeof ( *extra );
+               len -= sizeof ( *extra );
+               extra_len = le16_to_cpu ( extra->len );
+               if ( len < extra_len ) {
+                       DBGC ( image, "GZIP %p overlength extra header\n",
+                              image );
+                       return -EINVAL;
+               }
+               data += extra_len;
+               len -= extra_len;
        }
-       assert ( offset <= ( image->len - sizeof ( footer ) ) );
 
        /* Skip name and/or comment, if present */
        strings = 0;
-       if ( header.flags & GZIP_FL_NAME )
+       if ( header->flags & GZIP_FL_NAME )
                strings++;
-       if ( header.flags & GZIP_FL_COMMENT )
+       if ( header->flags & GZIP_FL_COMMENT )
                strings++;
        while ( strings-- ) {
-               nul = memchr_user ( image->data, offset, 0, ( len - offset ) );
-               if ( nul < 0 ) {
+               string_len = strnlen ( data, len );
+               if ( string_len == len ) {
                        DBGC ( image, "GZIP %p overlength name/comment\n",
                               image );
                        return -EINVAL;
                }
-               offset = ( nul + 1 /* NUL */ );
+               data += ( string_len + 1 /* NUL */ );
+               len -= ( string_len + 1 /* NUL */ );
        }
-       assert ( offset <= ( image->len - sizeof ( footer ) ) );
 
        /* Skip CRC, if present */
-       if ( header.flags & GZIP_FL_HCRC ) {
-               offset += sizeof ( crc );
-               if ( offset > len ) {
+       if ( header->flags & GZIP_FL_HCRC ) {
+               if ( len < sizeof ( *crc ) ) {
                        DBGC ( image, "GZIP %p overlength CRC header\n",
                               image );
                        return -EINVAL;
                }
+               data += sizeof ( *crc );
+               len -= sizeof ( *crc );
        }
 
-       /* Initialise input chunk */
-       deflate_chunk_init ( &in, ( image->data + offset ), 0, len );
-
        /* Presize extracted image */
        if ( ( rc = image_set_len ( extracted,
-                                   le32_to_cpu ( footer.len ) ) ) != 0 ) {
+                                   le32_to_cpu ( footer->len ) ) ) != 0 ) {
                DBGC ( image, "GZIP %p could not presize: %s\n",
                       image, strerror ( rc ) );
                return rc;
        }
 
        /* Decompress image (expanding if necessary) */
-       if ( ( rc = zlib_deflate ( DEFLATE_RAW, &in, extracted ) ) != 0 ) {
+       if ( ( rc = zlib_deflate ( DEFLATE_RAW, data, len,
+                                  extracted ) ) != 0 ) {
                DBGC ( image, "GZIP %p could not decompress: %s\n",
                       image, strerror ( rc ) );
                return rc;
@@ -138,19 +147,18 @@ static int gzip_extract ( struct image *image, struct image *extracted ) {
  * @ret rc             Return status code
  */
 static int gzip_probe ( struct image *image ) {
-       struct gzip_header header;
-       struct gzip_footer footer;
+       const struct gzip_header *header;
+       const struct gzip_footer *footer;
 
        /* Sanity check */
-       if ( image->len < ( sizeof ( header ) + sizeof ( footer ) ) ) {
+       if ( image->len < ( sizeof ( *header ) + sizeof ( *footer ) ) ) {
                DBGC ( image, "GZIP %p image too short\n", image );
                return -ENOEXEC;
        }
+       header = image->data;
 
        /* Check magic header */
-       copy_from_user ( &header.magic, image->data, 0,
-                        sizeof ( header.magic ) );
-       if ( header.magic != cpu_to_be16 ( GZIP_MAGIC ) ) {
+       if ( header->magic != cpu_to_be16 ( GZIP_MAGIC ) ) {
                DBGC ( image, "GZIP %p invalid magic\n", image );
                return -ENOEXEC;
        }
index d5cf7fd8f8874b10c42bde1dd5c3681a1d9f91c6..8b432e01af0739a8c7da63fe80da01dfccaa9cc7 100644 (file)
@@ -336,13 +336,12 @@ static int png_palette ( struct image *image, struct png_context *png,
  */
 static int png_image_data ( struct image *image, struct png_context *png,
                            size_t len ) {
-       struct deflate_chunk in;
        int rc;
 
        /* Deflate this chunk */
-       deflate_chunk_init ( &in, image->data, png->offset,
-                            ( png->offset + len ) );
-       if ( ( rc = deflate_inflate ( &png->deflate, &in, &png->raw ) ) != 0 ) {
+       if ( ( rc = deflate_inflate ( &png->deflate,
+                                     ( image->data + png->offset ),
+                                     len, &png->raw ) ) != 0 ) {
                DBGC ( image, "PNG %s could not decompress: %s\n",
                       image->name, strerror ( rc ) );
                return rc;
index a42c47e1ba809e8adbb7cf03e83c20fa56ac867a..d7deee88b53d11231ffa5e722b32ae8f5eeddbb1 100644 (file)
@@ -27,7 +27,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <errno.h>
 #include <assert.h>
 #include <ipxe/deflate.h>
-#include <ipxe/uaccess.h>
 #include <ipxe/image.h>
 #include <ipxe/zlib.h>
 
@@ -41,11 +40,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  * Extract compressed data to image
  *
  * @v format           Compression format code
- * @v in               Compressed input chunk
+ * @v data             Compressed input data
+ * @v len              Length of compressed input data
  * @v extracted                Extracted image
  * @ret rc             Return status code
  */
-int zlib_deflate ( enum deflate_format format, struct deflate_chunk *in,
+int zlib_deflate ( enum deflate_format format, const void *data, size_t len,
                   struct image *extracted ) {
        struct deflate *deflate;
        struct deflate_chunk out;
@@ -64,14 +64,12 @@ int zlib_deflate ( enum deflate_format format, struct deflate_chunk *in,
                /* (Re)initialise decompressor */
                deflate_init ( deflate, format );
 
-               /* (Re)initialise input chunk */
-               in->offset = 0;
-
                /* Initialise output chunk */
                deflate_chunk_init ( &out, extracted->data, 0, extracted->len );
 
                /* Decompress data */
-               if ( ( rc = deflate_inflate ( deflate, in, &out ) ) != 0 ) {
+               if ( ( rc = deflate_inflate ( deflate, data, len,
+                                             &out ) ) != 0 ) {
                        DBGC ( extracted, "ZLIB %p could not decompress: %s\n",
                               extracted, strerror ( rc ) );
                        goto err_inflate;
@@ -116,14 +114,11 @@ int zlib_deflate ( enum deflate_format format, struct deflate_chunk *in,
  * @ret rc             Return status code
  */
 static int zlib_extract ( struct image *image, struct image *extracted ) {
-       struct deflate_chunk in;
        int rc;
 
-       /* Initialise input chunk */
-       deflate_chunk_init ( &in, image->data, 0, image->len );
-
        /* Decompress image */
-       if ( ( rc = zlib_deflate ( DEFLATE_ZLIB, &in, extracted ) ) != 0 )
+       if ( ( rc = zlib_deflate ( DEFLATE_ZLIB, image->data, image->len,
+                                  extracted ) ) != 0 )
                return rc;
 
        return 0;
@@ -136,17 +131,17 @@ static int zlib_extract ( struct image *image, struct image *extracted ) {
  * @ret rc             Return status code
  */
 static int zlib_probe ( struct image *image ) {
-       union zlib_magic magic;
+       const union zlib_magic *magic;
 
        /* Sanity check */
-       if ( image->len < sizeof ( magic ) ) {
+       if ( image->len < sizeof ( *magic ) ) {
                DBGC ( image, "ZLIB %p image too short\n", image );
                return -ENOEXEC;
        }
+       magic = image->data;
 
        /* Check magic header */
-       copy_from_user ( &magic, image->data, 0, sizeof ( magic ) );
-       if ( ! zlib_magic_is_valid ( &magic ) ) {
+       if ( ! zlib_magic_is_valid ( magic ) ) {
                DBGC ( image, "ZLIB %p invalid magic data\n", image );
                return -ENOEXEC;
        }
index b751aa9a3709eaa834e5df0f12d400b96f8be96f..67292d77ecedc8f8f90dd6a7432b699969b79519 100644 (file)
@@ -11,7 +11,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 
 #include <stdint.h>
 #include <string.h>
-#include <ipxe/uaccess.h>
 
 /** Compression formats */
 enum deflate_format {
@@ -163,6 +162,11 @@ struct deflate {
        /** Format */
        enum deflate_format format;
 
+       /** Current input data pointer */
+       const uint8_t *in;
+       /** End of input data pointer */
+       const uint8_t *end;
+
        /** Accumulator */
        uint32_t accumulator;
        /** Bit-reversed accumulator
@@ -240,7 +244,7 @@ struct deflate {
 /** A chunk of data */
 struct deflate_chunk {
        /** Data */
-       userptr_t data;
+       void *data;
        /** Current offset */
        size_t offset;
        /** Length of data */
@@ -256,7 +260,7 @@ struct deflate_chunk {
  * @v len              Length
  */
 static inline __attribute__ (( always_inline )) void
-deflate_chunk_init ( struct deflate_chunk *chunk, userptr_t data,
+deflate_chunk_init ( struct deflate_chunk *chunk, void *data,
                     size_t offset, size_t len ) {
 
        chunk->data = data;
@@ -277,7 +281,7 @@ static inline int deflate_finished ( struct deflate *deflate ) {
 extern void deflate_init ( struct deflate *deflate,
                           enum deflate_format format );
 extern int deflate_inflate ( struct deflate *deflate,
-                            struct deflate_chunk *in,
+                            const void *data, size_t len,
                             struct deflate_chunk *out );
 
 #endif /* _IPXE_DEFLATE_H */
index 29016c38e48268e9cc297bedbf318ce1acf10231..3b0866bd1a3c34a7ace562769a0d6d54f91e9d4a 100644 (file)
@@ -28,15 +28,15 @@ union zlib_magic {
  * @v magic            Magic header
  * @ret is_valid       Magic header is valid
  */
-static inline int zlib_magic_is_valid ( union zlib_magic *magic ) {
+static inline int zlib_magic_is_valid ( const union zlib_magic *magic ) {
 
        /* Check magic value as per RFC 6713 */
        return ( ( ( magic->cmf & 0x8f ) == 0x08 ) &&
                 ( ( be16_to_cpu ( magic->check ) % 31 ) == 0 ) );
 }
 
-extern int zlib_deflate ( enum deflate_format format, struct deflate_chunk *in,
-                         struct image *extracted );
+extern int zlib_deflate ( enum deflate_format format, const void *data,
+                         size_t len, struct image *extracted );
 
 extern struct image_type zlib_image_type __image_type ( PROBE_NORMAL );
 
index 20ff5b9a2b9804145ca1971784e90d3fcff9587b..f7086b45d0c755a95add0d3ae5144d6833f8a67f 100644 (file)
@@ -156,19 +156,18 @@ static void deflate_okx ( struct deflate *deflate,
                          struct deflate_test *test,
                          struct deflate_test_fragments *frags,
                          const char *file, unsigned int line ) {
-       uint8_t data[ test->expected_len ];
-       struct deflate_chunk in;
-       struct deflate_chunk out;
-       size_t frag_len = -1UL;
-       size_t offset = 0;
+       uint8_t buf[ test->expected_len ];
+       const void *data = test->compressed;
        size_t remaining = test->compressed_len;
+       size_t frag_len = -1UL;
+       struct deflate_chunk out;
        unsigned int i;
 
        /* Initialise decompressor */
        deflate_init ( deflate, test->format );
 
        /* Initialise output chunk */
-       deflate_chunk_init ( &out, virt_to_user ( data ), 0, sizeof ( data ) );
+       deflate_chunk_init ( &out, buf, 0, sizeof ( buf ) );
 
        /* Process input (in fragments, if applicable) */
        for ( i = 0 ; i < ( sizeof ( frags->len ) /
@@ -179,16 +178,15 @@ static void deflate_okx ( struct deflate *deflate,
                        frag_len = frags->len[i];
                if ( frag_len > remaining )
                        frag_len = remaining;
-               deflate_chunk_init ( &in, virt_to_user ( test->compressed ),
-                                    offset, ( offset + frag_len ) );
 
                /* Decompress this fragment */
-               okx ( deflate_inflate ( deflate, &in, &out ) == 0, file, line );
-               okx ( in.len == ( offset + frag_len ), file, line );
-               okx ( in.offset == in.len, file, line );
+               okx ( deflate_inflate ( deflate, data, frag_len,
+                                       &out ) == 0, file, line );
+               okx ( deflate->in == ( data + frag_len ), file, line );
+               okx ( deflate->end == ( data + frag_len ), file, line );
 
                /* Move to next fragment */
-               offset = in.offset;
+               data += frag_len;
                remaining -= frag_len;
                if ( ! remaining )
                        break;
@@ -199,9 +197,13 @@ static void deflate_okx ( struct deflate *deflate,
 
        /* Check decompression has terminated as expected */
        okx ( deflate_finished ( deflate ), file, line );
-       okx ( offset == test->compressed_len, file, line );
+       okx ( deflate->in == ( test->compressed + test->compressed_len ),
+             file, line );
+       okx ( deflate->end == ( test->compressed + test->compressed_len ),
+             file, line );
        okx ( out.offset == test->expected_len, file, line );
-       okx ( memcmp ( data, test->expected, test->expected_len ) == 0,
+       okx ( out.data == buf, file, line );
+       okx ( memcmp ( out.data, test->expected, test->expected_len ) == 0,
             file, line );
 }
 #define deflate_ok( deflate, test, frags ) \
index 9226b4c26e2ee4aaf06c3ffe8d7e6df2957c62bf..6fd0ec854762f5d10da1bf059db144294bf07ba9 100644 (file)
@@ -33,6 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #undef NDEBUG
 
 #include <stdint.h>
+#include <string.h>
 #include <ipxe/image.h>
 #include <ipxe/gzip.h>
 #include <ipxe/test.h>
@@ -114,8 +115,7 @@ static void gzip_okx ( struct gzip_test *test, const char *file,
        struct image *extracted;
 
        /* Construct compressed image */
-       image = image_memory ( test->compressed_name,
-                              virt_to_user ( test->compressed ),
+       image = image_memory ( test->compressed_name, test->compressed,
                               test->compressed_len );
        okx ( image != NULL, file, line );
        okx ( image->len == test->compressed_len, file, line );
@@ -128,7 +128,7 @@ static void gzip_okx ( struct gzip_test *test, const char *file,
 
        /* Verify extracted image content */
        okx ( extracted->len == test->expected_len, file, line );
-       okx ( memcmp ( extracted->data, virt_to_user ( test->expected ),
+       okx ( memcmp ( extracted->data, test->expected,
                       test->expected_len ) == 0, file, line );
 
        /* Verify extracted image name */
index 2efdcbad8a3aa9c647a1d4253e3c3b5c4d959bb5..807c5e429d0c41c5c07634e194778d33d8fae38e 100644 (file)
@@ -89,8 +89,7 @@ static void zlib_okx ( struct zlib_test *test, const char *file,
        struct image *extracted;
 
        /* Construct compressed image */
-       image = image_memory ( test->compressed_name,
-                              virt_to_user ( test->compressed ),
+       image = image_memory ( test->compressed_name, test->compressed,
                               test->compressed_len );
        okx ( image != NULL, file, line );
        okx ( image->len == test->compressed_len, file, line );
@@ -103,7 +102,7 @@ static void zlib_okx ( struct zlib_test *test, const char *file,
 
        /* Verify extracted image content */
        okx ( extracted->len == test->expected_len, file, line );
-       okx ( memcmp ( extracted->data, virt_to_user ( test->expected ),
+       okx ( memcmp ( extracted->data, test->expected,
                       test->expected_len ) == 0, file, line );
 
        /* Verify extracted image name */