[Spice-devel] [PATCH] fix 16 bpp LZ image decompression

Frediano Ziglio fziglio at redhat.com
Mon Apr 18 16:12:58 UTC 2016


> 
> On Čt, 2016-04-14 at 17:56 +0100, Frediano Ziglio wrote:
> > LZ image decompression was broken for 16 bpp:
> > - stride was computed not computed correctly (as width*4). This caused
> 
> IMO one extra 'computed' here.
> 

Yes, Jonathon reported the same issue but unfortunately
patch was already merged

Frediano

> >   also a buffer underflow;
> > - stride in pixman is always multiple of 4 bytes (so for 16 bpp is
> >   ALIGN(width*2, 4)) so image decompressed by lz_decode as some missing
> >   bytes to be fixed.
> > 
> > The alignment code is reused from LZ4 function.
> > 
> > This fix also https://bugzilla.redhat.com/show_bug.cgi?id=1285469.
> > 
> > Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
> > ---
> >  common/canvas_base.c | 54
> >  +++++++++++++++++++++++++++++++---------------------
> >  1 file changed, 32 insertions(+), 22 deletions(-)
> > 
> > diff --git a/common/canvas_base.c b/common/canvas_base.c
> > index fa4d373..45dd75f 100644
> > --- a/common/canvas_base.c
> > +++ b/common/canvas_base.c
> > @@ -515,13 +515,30 @@ static pixman_image_t *canvas_get_jpeg(CanvasBase
> > *canvas, SpiceImage *image)
> >      return surface;
> >  }
> >  
> > +static void canvas_fix_alignment(uint8_t *bits,
> > +                                 int stride_encoded, int stride_pixman,
> > +                                 int height)
> > +{
> > +    if (stride_pixman > stride_encoded) {
> > +        // Fix the row alignment
> > +        int row;
> > +        uint8_t *dest = bits;
> > +        for (row = height - 1; row > 0; --row) {
> > +            uint32_t *dest_aligned, *dest_misaligned;
> > +            dest_aligned = (uint32_t *)(dest + stride_pixman*row);
> > +            dest_misaligned = (uint32_t*)(dest + stride_encoded*row);
> > +            memmove(dest_aligned, dest_misaligned, stride_encoded);
> > +        }
> > +    }
> > +}
> > +
> >  #ifdef USE_LZ4
> >  static pixman_image_t *canvas_get_lz4(CanvasBase *canvas, SpiceImage
> >  *image)
> >  {
> >      pixman_image_t *surface = NULL;
> >      int dec_size, enc_size, available;
> >      int stride, stride_abs, stride_encoded;
> > -    uint8_t *dest, *data, *data_end;
> > +    uint8_t *dest, *data, *data_end, *bits;
> >      int width, height, top_down;
> >      LZ4_streamDecode_t *stream;
> >      uint8_t spice_format;
> > @@ -576,6 +593,7 @@ static pixman_image_t *canvas_get_lz4(CanvasBase
> > *canvas, SpiceImage *image)
> >      if (!top_down) {
> >          dest -= (stride_abs * (height - 1));
> >      }
> > +    bits = dest;
> >  
> >      do {
> >          // Read next compressed block
> > @@ -594,20 +612,7 @@ static pixman_image_t *canvas_get_lz4(CanvasBase
> > *canvas, SpiceImage *image)
> >          data += enc_size;
> >      } while (data < data_end);
> >  
> > -    if (stride_abs > stride_encoded) {
> > -        // Fix the row alignment
> > -        int row;
> > -        dest = (uint8_t *)pixman_image_get_data(surface);
> > -        if (!top_down) {
> > -            dest -= (stride_abs * (height - 1));
> > -        }
> > -        for (row = height - 1; row > 0; --row) {
> > -            uint32_t *dest_aligned, *dest_misaligned;
> > -            dest_aligned = (uint32_t *)(dest + stride_abs*row);
> > -            dest_misaligned = (uint32_t*)(dest + stride_encoded*row);
> > -            memmove(dest_aligned, dest_misaligned, stride_encoded);
> > -        }
> > -    }
> > +    canvas_fix_alignment(bits, stride_encoded, stride_abs, height);
> >  
> >      LZ4_freeStreamDecode(stream);
> >      return surface;
> > @@ -782,7 +787,6 @@ static pixman_image_t *canvas_get_lz(CanvasBase
> > *canvas, SpiceImage *image,
> >      uint8_t *comp_buf = NULL;
> >      int comp_size;
> >      uint8_t    *decomp_buf = NULL;
> > -    uint8_t    *src;
> >      pixman_format_code_t pixman_format;
> >      LzImageType type, as_type;
> >      SpicePalette *palette;
> > @@ -790,6 +794,7 @@ static pixman_image_t *canvas_get_lz(CanvasBase
> > *canvas, SpiceImage *image,
> >      int width;
> >      int height;
> >      int top_down;
> > +    int stride_encoded;
> >      int stride;
> >      int free_palette;
> >  
> > @@ -818,10 +823,12 @@ static pixman_image_t *canvas_get_lz(CanvasBase
> > *canvas, SpiceImage *image,
> >      lz_decode_begin(lz_data->lz, comp_buf, comp_size, &type,
> >                      &width, &height, &n_comp_pixels, &top_down, palette);
> >  
> > +    stride_encoded = width;
> >      switch (type) {
> >      case LZ_IMAGE_TYPE_RGBA:
> >          as_type = LZ_IMAGE_TYPE_RGBA;
> >          pixman_format = PIXMAN_LE_a8r8g8b8;
> > +        stride_encoded *= 4;
> >          break;
> >      case LZ_IMAGE_TYPE_RGB32:
> >      case LZ_IMAGE_TYPE_RGB24:
> > @@ -832,6 +839,7 @@ static pixman_image_t *canvas_get_lz(CanvasBase
> > *canvas, SpiceImage *image,
> >      case LZ_IMAGE_TYPE_PLT8:
> >          as_type = LZ_IMAGE_TYPE_RGB32;
> >          pixman_format = PIXMAN_LE_x8r8g8b8;
> > +        stride_encoded *= 4;
> >          break;
> >      case LZ_IMAGE_TYPE_A8:
> >          as_type = LZ_IMAGE_TYPE_A8;
> > @@ -843,9 +851,11 @@ static pixman_image_t *canvas_get_lz(CanvasBase
> > *canvas, SpiceImage *image,
> >               canvas->format == SPICE_SURFACE_FMT_32_ARGB)) {
> >              as_type = LZ_IMAGE_TYPE_RGB32;
> >              pixman_format = PIXMAN_LE_x8r8g8b8;
> > +            stride_encoded *= 4;
> >          } else {
> >              as_type = LZ_IMAGE_TYPE_RGB16;
> >              pixman_format = PIXMAN_x1r5g5b5;
> > +            stride_encoded *= 2;
> >          }
> >          break;
> >      default:
> > @@ -865,18 +875,18 @@ static pixman_image_t *canvas_get_lz(CanvasBase
> > *canvas, SpiceImage *image,
> >      alloc_lz_image_surface(&lz_data->decode_data, pixman_format,
> >                             width, height, n_comp_pixels, top_down);
> >  
> > -    src = (uint8_t
> > *)pixman_image_get_data(lz_data->decode_data.out_surface);
> > +    stride = pixman_image_get_stride(lz_data->decode_data.out_surface);
> > +    stride = abs(stride);
> >  
> > -    stride = (n_comp_pixels / height) * 4;
> > +    decomp_buf = (uint8_t
> > *)pixman_image_get_data(lz_data->decode_data.out_surface);
> >      if (!top_down) {
> > -        stride = -stride;
> > -        decomp_buf = src + stride * (height - 1);
> > -    } else {
> > -        decomp_buf = src;
> > +        decomp_buf -= stride * (height - 1);
> >      }
> >  
> >      lz_decode(lz_data->lz, as_type, decomp_buf);
> >  
> > +    canvas_fix_alignment(decomp_buf, stride_encoded, stride, height);
> > +
> >      if (free_palette)  {
> >          free(palette);
> >      }
> 
> 
> 


More information about the Spice-devel mailing list