@@ -100,6 +100,8 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
100100 Uint8 * row , * buf = NULL ;
101101 char * error = NULL ;
102102 int bits , src_bits ;
103+ int count = 0 ;
104+ Uint8 ch ;
103105
104106 if ( !src ) {
105107 /* The error message has been set in SDL_RWFromFile */
@@ -117,6 +119,20 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
117119 pcxh .Ymax = SDL_SwapLE16 (pcxh .Ymax );
118120 pcxh .BytesPerLine = SDL_SwapLE16 (pcxh .BytesPerLine );
119121
122+ #if 0
123+ printf ("Manufacturer = %d\n" , pcxh .Manufacturer );
124+ printf ("Version = %d\n" , pcxh .Version );
125+ printf ("Encoding = %d\n" , pcxh .Encoding );
126+ printf ("BitsPerPixel = %d\n" , pcxh .BitsPerPixel );
127+ printf ("Xmin = %d, Ymin = %d, Xmax = %d, Ymax = %d\n" , pcxh .Xmin , pcxh .Ymin , pcxh .Xmax , pcxh .Ymax );
128+ printf ("HDpi = %d, VDpi = %d\n" , pcxh .HDpi , pcxh .VDpi );
129+ printf ("NPlanes = %d\n" , pcxh .NPlanes );
130+ printf ("BytesPerLine = %d\n" , pcxh .BytesPerLine );
131+ printf ("PaletteInfo = %d\n" , pcxh .PaletteInfo );
132+ printf ("HscreenSize = %d\n" , pcxh .HscreenSize );
133+ printf ("VscreenSize = %d\n" , pcxh .VscreenSize );
134+ #endif
135+
120136 /* Create the surface of the appropriate type */
121137 width = (pcxh .Xmax - pcxh .Xmin ) + 1 ;
122138 height = (pcxh .Ymax - pcxh .Ymin ) + 1 ;
@@ -142,22 +158,22 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
142158 }
143159 surface = SDL_AllocSurface (SDL_SWSURFACE , width , height ,
144160 bits , Rmask , Gmask , Bmask , Amask );
145- if ( surface == NULL )
161+ if ( surface == NULL ) {
146162 goto done ;
163+ }
147164
148165 bpl = pcxh .NPlanes * pcxh .BytesPerLine ;
149- if (bpl > surface -> pitch ) {
150- error = "bytes per line is too large (corrupt?)" ;
166+ buf = (Uint8 * )calloc (bpl , 1 );
167+ if (!buf ) {
168+ error = "Out of memory" ;
169+ goto done ;
151170 }
152- buf = (Uint8 * )calloc (SDL_max (bpl , surface -> pitch ), 1 );
153171 row = (Uint8 * )surface -> pixels ;
154172 for ( y = 0 ; y < surface -> h ; ++ y ) {
155173 /* decode a scan line to a temporary buffer first */
156- int i , count = 0 ;
157- Uint8 ch ;
158- Uint8 * dst = (src_bits == 8 ) ? row : buf ;
174+ int i ;
159175 if ( pcxh .Encoding == 0 ) {
160- if (!SDL_RWread (src , dst , bpl , 1 )) {
176+ if (!SDL_RWread (src , buf , bpl , 1 )) {
161177 error = "file truncated" ;
162178 goto done ;
163179 }
@@ -168,16 +184,17 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
168184 error = "file truncated" ;
169185 goto done ;
170186 }
171- if ( (ch & 0xc0 ) == 0xc0 ) {
172- count = ch & 0x3f ;
187+ if (ch < 0xc0 ) {
188+ count = 1 ;
189+ } else {
190+ count = ch - 0xc0 ;
173191 if (!SDL_RWread (src , & ch , 1 , 1 )) {
174192 error = "file truncated" ;
175193 goto done ;
176194 }
177- } else
178- count = 1 ;
195+ }
179196 }
180- dst [i ] = ch ;
197+ buf [i ] = ch ;
181198 count -- ;
182199 }
183200 }
@@ -199,14 +216,21 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
199216 }
200217 }
201218 }
219+ } else if (src_bits == 8 ) {
220+ /* Copy the row directly */
221+ memcpy (row , buf , SDL_min (width , bpl ));
202222 } else if (src_bits == 24 ) {
203223 /* de-interlace planes */
204224 Uint8 * innerSrc = buf ;
205225 int plane ;
206226 for (plane = 0 ; plane < pcxh .NPlanes ; plane ++ ) {
207227 int x ;
208- dst = row + plane ;
228+ Uint8 * dst = row + plane ;
209229 for (x = 0 ; x < width ; x ++ ) {
230+ if (dst >= row + surface -> pitch ) {
231+ error = "decoding out of bounds (corrupt?)" ;
232+ goto done ;
233+ }
210234 * dst = * innerSrc ++ ;
211235 dst += pcxh .NPlanes ;
212236 }
@@ -227,8 +251,9 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
227251 /* look for a 256-colour palette */
228252 do {
229253 if ( !SDL_RWread (src , & ch , 1 , 1 )) {
230- error = "file truncated" ;
231- goto done ;
254+ /* Couldn't find the palette, try the end of the file */
255+ SDL_RWseek (src , -768 , RW_SEEK_END );
256+ break ;
232257 }
233258 } while ( ch != 12 );
234259
0 commit comments