@@ -98,14 +98,16 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
9898 Uint8 * row , * buf = NULL ;
9999 char * error = NULL ;
100100 int bits , src_bits ;
101+ int count = 0 ;
102+ Uint8 ch ;
101103
102104 if ( !src ) {
103105 /* The error message has been set in SDL_RWFromFile */
104106 return NULL ;
105107 }
106108 start = SDL_RWtell (src );
107109
108- if ( ! SDL_RWread (src , & pcxh , sizeof (pcxh ), 1 ) ) {
110+ if ( !SDL_RWread (src , & pcxh , sizeof (pcxh ), 1 ) ) {
109111 error = "file truncated" ;
110112 goto done ;
111113 }
@@ -115,6 +117,20 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
115117 pcxh .Ymax = SDL_SwapLE16 (pcxh .Ymax );
116118 pcxh .BytesPerLine = SDL_SwapLE16 (pcxh .BytesPerLine );
117119
120+ #if 0
121+ printf ("Manufacturer = %d\n" , pcxh .Manufacturer );
122+ printf ("Version = %d\n" , pcxh .Version );
123+ printf ("Encoding = %d\n" , pcxh .Encoding );
124+ printf ("BitsPerPixel = %d\n" , pcxh .BitsPerPixel );
125+ printf ("Xmin = %d, Ymin = %d, Xmax = %d, Ymax = %d\n" , pcxh .Xmin , pcxh .Ymin , pcxh .Xmax , pcxh .Ymax );
126+ printf ("HDpi = %d, VDpi = %d\n" , pcxh .HDpi , pcxh .VDpi );
127+ printf ("NPlanes = %d\n" , pcxh .NPlanes );
128+ printf ("BytesPerLine = %d\n" , pcxh .BytesPerLine );
129+ printf ("PaletteInfo = %d\n" , pcxh .PaletteInfo );
130+ printf ("HscreenSize = %d\n" , pcxh .HscreenSize );
131+ printf ("VscreenSize = %d\n" , pcxh .VscreenSize );
132+ #endif
133+
118134 /* Create the surface of the appropriate type */
119135 width = (pcxh .Xmax - pcxh .Xmin ) + 1 ;
120136 height = (pcxh .Ymax - pcxh .Ymin ) + 1 ;
@@ -144,51 +160,52 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
144160 goto done ;
145161
146162 bpl = pcxh .NPlanes * pcxh .BytesPerLine ;
147- if (bpl > surface -> pitch ) {
163+ if ( bpl > surface -> pitch ) {
148164 error = "bytes per line is too large (corrupt?)" ;
165+ goto done ;
149166 }
150- buf = (Uint8 * )SDL_calloc (SDL_max ( bpl , surface -> pitch ) , 1 );
167+ buf = (Uint8 * )SDL_calloc (surface -> pitch , 1 );
151168 row = (Uint8 * )surface -> pixels ;
152169 for ( y = 0 ; y < surface -> h ; ++ y ) {
153170 /* decode a scan line to a temporary buffer first */
154- int i , count = 0 ;
155- Uint8 ch ;
156- Uint8 * dst = (src_bits == 8 ) ? row : buf ;
171+ int i ;
172+ Uint8 * dst = buf ;
157173 if ( pcxh .Encoding == 0 ) {
158- if ( !SDL_RWread (src , dst , bpl , 1 )) {
174+ if ( !SDL_RWread (src , dst , bpl , 1 ) ) {
159175 error = "file truncated" ;
160176 goto done ;
161177 }
162178 } else {
163- for ( i = 0 ; i < bpl ; i ++ ) {
164- if ( !count ) {
165- if ( !SDL_RWread (src , & ch , 1 , 1 )) {
179+ for ( i = 0 ; i < bpl ; i ++ ) {
180+ if ( !count ) {
181+ if ( !SDL_RWread (src , & ch , 1 , 1 ) ) {
166182 error = "file truncated" ;
167183 goto done ;
168184 }
169- if ( (ch & 0xc0 ) == 0xc0 ) {
170- count = ch & 0x3f ;
171- if (!SDL_RWread (src , & ch , 1 , 1 )) {
185+ if ( ch < 0xc0 ) {
186+ count = 1 ;
187+ } else {
188+ count = ch - 0xc0 ;
189+ if ( !SDL_RWread (src , & ch , 1 , 1 ) ) {
172190 error = "file truncated" ;
173191 goto done ;
174192 }
175- } else
176- count = 1 ;
193+ }
177194 }
178195 dst [i ] = ch ;
179196 count -- ;
180197 }
181198 }
182199
183- if ( src_bits <= 4 ) {
200+ if ( src_bits <= 4 ) {
184201 /* expand planes to 1 byte/pixel */
185202 Uint8 * innerSrc = buf ;
186203 int plane ;
187- for ( plane = 0 ; plane < pcxh .NPlanes ; plane ++ ) {
204+ for ( plane = 0 ; plane < pcxh .NPlanes ; plane ++ ) {
188205 int j , k , x = 0 ;
189- for (j = 0 ; j < pcxh .BytesPerLine ; j ++ ) {
206+ for ( j = 0 ; j < pcxh .BytesPerLine ; j ++ ) {
190207 Uint8 byte = * innerSrc ++ ;
191- for (k = 7 ; k >= 0 ; k -- ) {
208+ for ( k = 7 ; k >= 0 ; k -- ) {
192209 unsigned bit = (byte >> k ) & 1 ;
193210 /* skip padding bits */
194211 if (j * 8 + k >= width )
@@ -197,46 +214,53 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
197214 }
198215 }
199216 }
200- } else if ( src_bits == 24 ) {
217+ } else if ( src_bits == 24 ) {
201218 /* de-interlace planes */
202219 Uint8 * innerSrc = buf ;
203220 int plane ;
204- for ( plane = 0 ; plane < pcxh .NPlanes ; plane ++ ) {
221+ for ( plane = 0 ; plane < pcxh .NPlanes ; plane ++ ) {
205222 int x ;
206223 dst = row + plane ;
207- for (x = 0 ; x < width ; x ++ ) {
224+ for ( x = 0 ; x < width ; x ++ ) {
225+ if ( dst >= row + surface -> pitch ) {
226+ error = "decoding out of bounds (corrupt?)" ;
227+ goto done ;
228+ }
208229 * dst = * innerSrc ++ ;
209230 dst += pcxh .NPlanes ;
210231 }
211232 }
233+ } else {
234+ SDL_memcpy (row , buf , bpl );
212235 }
213236
214237 row += surface -> pitch ;
215238 }
216239
217- if ( bits == 8 ) {
240+ if ( bits == 8 ) {
218241 SDL_Color * colors = surface -> format -> palette -> colors ;
219242 int nc = 1 << src_bits ;
220243 int i ;
221244
222245 surface -> format -> palette -> ncolors = nc ;
223- if ( src_bits == 8 ) {
246+ if ( src_bits == 8 ) {
224247 Uint8 ch ;
225248 /* look for a 256-colour palette */
226249 do {
227- if ( !SDL_RWread (src , & ch , 1 , 1 )) {
228- error = "file truncated" ;
229- goto done ;
250+ if ( !SDL_RWread (src , & ch , 1 , 1 ) ) {
251+ /* Couldn't find the palette, try the end of the file */
252+ SDL_RWseek (src , -768 , RW_SEEK_END );
253+ break ;
230254 }
231255 } while ( ch != 12 );
232256
233- for ( i = 0 ; i < 256 ; i ++ ) {
257+ for ( i = 0 ; i < 256 ; i ++ ) {
234258 SDL_RWread (src , & colors [i ].r , 1 , 1 );
235259 SDL_RWread (src , & colors [i ].g , 1 , 1 );
236260 SDL_RWread (src , & colors [i ].b , 1 , 1 );
237261 }
238262 } else {
239- for ( i = 0 ; i < nc ; i ++ ) {
263+ for ( i = 0 ; i < nc ; i ++ ) {
240264 colors [i ].r = pcxh .Colormap [i * 3 ];
241265 colors [i ].g = pcxh .Colormap [i * 3 + 1 ];
242266 colors [i ].b = pcxh .Colormap [i * 3 + 2 ];
0 commit comments