[RESENDv3] winhelp: fix LZ77 decompressor

HolyLich lich at math.spbu.ru
Fri Aug 11 10:28:49 CDT 2006


Hi,

This patch fixes a bug in LZ77 decompressor which affected only large (>0x1000)
compressed embedded files, e.g. images (metafiles). I've never noticed it corrupting
small images, but it may.

Thanks to Dan Kegel and Alexandre Julliard for clarifying things!

ChangeLog:
  Kirill K. Smirnov <lich at math.spbu.ru>
  winhelp: Fix LZ77 decompressor
-------------- next part --------------
===================================================================
RCS file: /home/wine/wine/programs/winhelp/hlpfile.c,v
retrieving revision 1.29
diff -u -p -r1.29 hlpfile.c
--- programs/winhelp/hlpfile.c	23 May 2006 12:49:31 -0000	1.29
+++ programs/winhelp/hlpfile.c	11 Aug 2006 15:21:05 -0000
@@ -1498,8 +1498,25 @@ static BYTE *HLPFILE_UncompressLZ77(BYTE
                 int code   = GET_USHORT(ptr, 0);
                 int len    = 3 + (code >> 12);
                 int offset = code & 0xfff;
-                memcpy(newptr, newptr - offset - 1, len);
-                newptr += len;
+                /*
+                 * We must copy byte-by-byte here. We cannot use memcpy nor
+                 * memmove here. Just example:
+                 * a[]={1,2,3,4,5,6,7,8,9,10}
+                 * newptr=a+2;
+                 * offset=1;
+                 * We expect:
+                 * {1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 11, 12}
+                 * memcpy produce:
+                 * {1, 2, 1, 2, 1, 2, 5, 6, 5, 6, 11, 12}
+                 * memmove produce:
+                 * {1, 2, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12}
+                 *
+                 * The reason is memcpy's behaviour is unpredictable if
+                 * areas overlap.
+                 * And memmove guarantees, that dest area will be the same
+                 * as src area before. It does not suit LZ77.
+                 */
+                for (; len>0; len--, newptr++) *newptr = *(newptr-offset-1);
                 ptr    += 2;
 	    }
             else *newptr++ = *ptr++;


More information about the wine-patches mailing list