CVE-2019-16346 (published 2019-09-16T13:15Z)

ngiflib 0.4 has a heap-based buffer overflow in WritePixel() in ngiflib.c when called from DecodeGifImg, because deinterlacing for small pictures is mishandled.

Severity: MEDIUM
CVSS v2 base score: 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 8.8, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-787
cwe_name: Out-of-bounds Write
description: The product writes data past the end, or before the beginning, of the intended buffer.
extended_description: 
            
            
             
			 
         
         
cwe_id: CWE-682
cwe_name: Incorrect Calculation
description: The product performs a calculation that generates incorrect or unintended results that are later used in security-critical decisions or resource management.
extended_description: When product performs a security-critical calculation incorrectly, it might lead to incorrect resource allocations, incorrect privilege assignments, or failed comparisons among other things. Many of the direct results of an incorrect calculation can lead to even larger problems such as failed protection mechanisms or even arbitrary code execution.
         

Fix information:
repo_url: https://github.com/miniupnp/ngiflib
commit_details: repo_url: https://github.com/miniupnp/ngiflib
author: Thomas Bernard
author_date: 2019-04-16 02:05:15+02:00
msg: fix deinterlacing for small pictures

fixes #12
repository: repo_url: https://github.com/miniupnp/ngiflib
repo_name: miniupnp/ngiflib
description: GIF picture format decoding library written in C
repo_language: C
owner: miniupnp
file_changes: filename: ngiflib.c
change_type: ModificationType.MODIFY
diff: @@ -6,7 +6,7 @@
 
 /* decodeur GIF en C portable (pas de pb big/little endian)
  * Thomas BERNARD. janvier 2004.
- * (c) 2004-2017 Thomas Bernard. All rights reserved
+ * (c) 2004-2019 Thomas Bernard. All rights reserved
  */
 
 /* Fonction de debug */
@@ -135,29 +135,31 @@ static void WritePixel(struct ngiflib_img * i, struct ngiflib_decode_context * c
 			break;
 		case 1:	/* 1st pass : every eighth row starting from 0 */
 			context->curY += 8;
-			if(context->curY >= p->height) {
-				context->pass++;
-				context->curY = i->posY + 4;
-			}
 			break;
 		case 2:	/* 2nd pass : every eighth row starting from 4 */
 			context->curY += 8;
-			if(context->curY >= p->height) {
-				context->pass++;
-				context->curY = i->posY + 2;
-			}
 			break;
 		case 3:	/* 3rd pass : every fourth row starting from 2 */
 			context->curY += 4;
-			if(context->curY >= p->height) {
-				context->pass++;
-				context->curY = i->posY + 1;
-			}
 			break;
 		case 4:	/* 4th pass : every odd row */
 			context->curY += 2;
 			break;
 		}
+		while(context->pass > 0 && context->pass < 4 &&
+		      context->curY >= p->height) {
+			switch(++context->pass) {
+			case 2:	/* 2nd pass : every eighth row starting from 4 */
+				context->curY = i->posY + 4;
+				break;
+			case 3:	/* 3rd pass : every fourth row starting from 2 */
+				context->curY = i->posY + 2;
+				break;
+			case 4:	/* 4th pass : every odd row */
+				context->curY = i->posY + 1;
+				break;
+			}
+		}
 #ifndef NGIFLIB_INDEXED_ONLY
 		if(p->mode & NGIFLIB_MODE_INDEXED) {
 #endif /* NGIFLIB_INDEXED_ONLY */
@@ -249,29 +251,31 @@ static void WritePixels(struct ngiflib_img * i, struct ngiflib_decode_context *
 				break;
 			case 1:	/* 1st pass : every eighth row starting from 0 */
 				context->curY += 8;
-				if(context->curY >= p->height) {
-					context->pass++;
-					context->curY = i->posY + 4;
-				}
 				break;
 			case 2:	/* 2nd pass : every eighth row starting from 4 */
 				context->curY += 8;
-				if(context->curY >= p->height) {
-					context->pass++;
-					context->curY = i->posY + 2;
-				}
 				break;
 			case 3:	/* 3rd pass : every fourth row starting from 2 */
 				context->curY += 4;
-				if(context->curY >= p->height) {
-					context->pass++;
-					context->curY = i->posY + 1;
-				}
 				break;
 			case 4:	/* 4th pass : every odd row */
 				context->curY += 2;
 				break;
 			}
+			while(context->pass > 0 && context->pass < 4 &&
+			      context->curY >= p->height) {
+				switch(++context->pass) {
+				case 2:	/* 2nd pass : every eighth row starting from 4 */
+					context->curY = i->posY + 4;
+					break;
+				case 3:	/* 3rd pass : every fourth row starting from 2 */
+					context->curY = i->posY + 2;
+					break;
+				case 4:	/* 4th pass : every odd row */
+					context->curY = i->posY + 1;
+					break;
+				}
+			}
 #ifndef NGIFLIB_INDEXED_ONLY
 			if(p->mode & NGIFLIB_MODE_INDEXED) {
 #endif /* NGIFLIB_INDEXED_ONLY */

programming_language: C