File: IMG_pcx-out-of-bounds.patch

package info (click to toggle)
sdl-image1.2 1.2.12-14
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 7,028 kB
  • sloc: sh: 10,194; ansic: 9,697; objc: 248; csh: 219; makefile: 83
file content (101 lines) | stat: -rw-r--r-- 3,259 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
From: Sam Lantinga <slouken@libsdl.org>
Date: Mon, 10 Jun 2019 15:41:09 -0700
Subject: Fixed bug 4628 - SEGV_UNKNOW in function SDL_free_REAL at
 SDL_malloc.c:5372-5

The PCX format specifies pcxh.BytesPerLine, which represents the size of a
single plane's scanline in bytes. Valid PCX images should have
pcxh.BytesPerLine >= surface->pitch.

pcxh.BytesPerLine and surface->pitch can legitimately be different because
pcxh.BytesPerLine is padded to be a multiple of machine word length (where
file was created).

If src_bits == 8 we directly read a whole scanline from src to row. This is
a problem in the case where bpl > surface->pitch because row is too small.

This allows attacker to perform unlimited OOB write on the heap.

+ remove pointless check bpl > surface->pitch, this is a valid situation
+ make sure we always read into buf which is big enough
+ in the case where src_bits == 8: copy these bytes back to row afterwar

Bug: https://security-tracker.debian.org/tracker/CVE-2019-12217
Bug: https://security-tracker.debian.org/tracker/CVE-2019-12219
Bug: https://security-tracker.debian.org/tracker/CVE-2019-12220
Bug: https://security-tracker.debian.org/tracker/CVE-2019-12221
Bug: https://security-tracker.debian.org/tracker/CVE-2019-12222
Origin: upstream, 2.0.5, commit:e7e9786a1a34, commit:https://github.com/libsdl-org/SDL_image/commit/1559b5ce67e25c8de65f0d4af020c1ec50cb7b85
Co-authored-by: Hugo Lefeuvre
---
 IMG_pcx.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/IMG_pcx.c b/IMG_pcx.c
index 0116f17..99af3f5 100644
--- a/IMG_pcx.c
+++ b/IMG_pcx.c
@@ -148,18 +148,17 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
 		goto done;
 
 	bpl = pcxh.NPlanes * pcxh.BytesPerLine;
-	if (bpl < 0 || bpl > surface->pitch) {
-		error = "bytes per line is too large (corrupt?)";
+	buf = (Uint8 *)SDL_calloc(bpl, 1);
+	if ( !buf ) {
+		error = "Out of memory";
 		goto done;
 	}
-	buf = (Uint8 *)SDL_calloc(surface->pitch, 1);
 	row = surface->pixels;
 	for ( y=0; y<surface->h; ++y ) {
 		/* decode a scan line to a temporary buffer first */
 		int i;
-		Uint8 *dst = buf;
 		if ( pcxh.Encoding == 0 ) {
-			if(!SDL_RWread(src, dst, bpl, 1)) {
+			if(!SDL_RWread(src, buf, bpl, 1)) {
 				error = "file truncated";
 				goto done;
 			}
@@ -180,7 +179,7 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
 						}
 					}
 				}
-				dst[i] = ch;
+				buf[i] = ch;
 				count--;
 			}
 		}
@@ -202,13 +201,21 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
 					}
 				}
 			}
+		} else if ( src_bits == 8 ) {
+			/* directly copy buf content to row */
+			Uint8 *innerSrc = buf;
+			int x;
+			Uint8 *dst = row;
+			for ( x = 0; x < width; x++ ) {
+				*dst++ = *innerSrc++;
+			}
  		} else if(src_bits == 24) {
 			/* de-interlace planes */
 			Uint8 *src = buf;
 			int plane;
 			for(plane = 0; plane < pcxh.NPlanes; plane++) {
 				int x;
-				dst = row + plane;
+				Uint8 *dst = row + plane;
 				for(x = 0; x < width; x++) {
 					if ( dst >= row+surface->pitch ) {
 						error = "decoding out of bounds (corrupt?)";
@@ -218,8 +225,6 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
 					dst += pcxh.NPlanes;
 				}
 			}
-		} else {
-			SDL_memcpy(row, buf, bpl);
 		}
 
 		row += surface->pitch;