CVE-2019-17178 (published 2019-10-04T17:15Z)

HuffmanTree_makeFromFrequencies in lodepng.c in LodePNG through 2019-09-28, as used in WinPR in FreeRDP and other products, has a memory leak because a supplied realloc pointer (i.e., the first argument to realloc) is also used for a realloc return value.

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

Weakness information:
cwe_id: CWE-252
cwe_name: Unchecked Return Value
description: The product does not check the return value from a method or function, which can prevent it from detecting unexpected states and conditions.
extended_description: Two common programmer assumptions are "this function call can never fail" and "it doesn't matter if this function call fails". If an attacker can force the function to fail or otherwise return a value that is not expected, then the subsequent program logic could lead to a vulnerability, because the product is not in a state that the programmer assumes. For example, if the program calls a function to drop privileges but does not check the return code to ensure that privileges were successfully dropped, then the program will continue to operate with the higher privileges.
         
cwe_id: CWE-401
cwe_name: Missing Release of Memory after Effective Lifetime
description: The product does not sufficiently track and release allocated memory after it has been used, which slowly consumes remaining memory.
extended_description: This is often triggered by improper handling of malformed data or unexpectedly interrupted sessions.  In some languages, developers are responsible for tracking memory allocation and releasing the memory.  If there are no more pointers or references to the memory, then it can no longer be tracked and identified for release.
         

Fix information:
repo_url: https://github.com/FreeRDP/FreeRDP
commit_details: repo_url: https://github.com/FreeRDP/FreeRDP
author: Armin Novak
author_date: 2019-10-04 14:49:30+02:00
msg: Fixed #5645: realloc return handling
repository: repo_url: https://github.com/FreeRDP/FreeRDP
repo_name: FreeRDP/FreeRDP
description: FreeRDP is a free remote desktop protocol library and clients
repo_language: C
owner: FreeRDP
file_changes: filename: generate_argument_docbook.c
change_type: ModificationType.MODIFY
diff: @@ -9,6 +9,7 @@
 LPSTR tr_esc_str(LPCSTR arg, bool format)
 {
 	LPSTR tmp = NULL;
+	LPSTR tmp2 = NULL;
 	size_t cs = 0, x, ds, len;
 	size_t s;
 
@@ -25,7 +26,12 @@ LPSTR tr_esc_str(LPCSTR arg, bool format)
 	ds = s + 1;
 
 	if (s)
-		tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+	{
+		tmp2 = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+		if (!tmp2)
+			free(tmp);
+		tmp = tmp2;
+	}
 
 	if (NULL == tmp)
 	{
@@ -43,7 +49,10 @@ LPSTR tr_esc_str(LPCSTR arg, bool format)
 			case '<':
 				len = format ? 13 : 4;
 				ds += len - 1;
-				tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+				tmp2 = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+				if (!tmp2)
+					free(tmp);
+				tmp = tmp2;
 
 				if (NULL == tmp)
 				{
@@ -64,7 +73,10 @@ LPSTR tr_esc_str(LPCSTR arg, bool format)
 			case '>':
 				len = format ? 14 : 4;
 				ds += len - 1;
-				tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+				tmp2 = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+				if (!tmp2)
+					free(tmp);
+				tmp = tmp2;
 
 				if (NULL == tmp)
 				{
@@ -84,7 +96,10 @@ LPSTR tr_esc_str(LPCSTR arg, bool format)
 
 			case '\'':
 				ds += 5;
-				tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+				tmp2 = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+				if (!tmp2)
+					free(tmp);
+				tmp = tmp2;
 
 				if (NULL == tmp)
 				{
@@ -102,7 +117,10 @@ LPSTR tr_esc_str(LPCSTR arg, bool format)
 
 			case '"':
 				ds += 5;
-				tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+				tmp2 = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+				if (!tmp2)
+					free(tmp);
+				tmp = tmp2;
 
 				if (NULL == tmp)
 				{
@@ -120,7 +138,10 @@ LPSTR tr_esc_str(LPCSTR arg, bool format)
 
 			case '&':
 				ds += 4;
-				tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+				tmp2 = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
+				if (!tmp2)
+					free(tmp);
+				tmp = tmp2;
 
 				if (NULL == tmp)
 				{

programming_language: C
filename: region.c
change_type: ModificationType.MODIFY
diff: @@ -467,8 +467,12 @@ static BOOL region16_simplify_bands(REGION16* region)
 
 	if (finalNbRects != nbRects)
 	{
-		int allocSize = sizeof(REGION16_DATA) + (finalNbRects * sizeof(RECTANGLE_16));
-		region->data = realloc(region->data, allocSize);
+		REGION16_DATA* data;
+		size_t allocSize = sizeof(REGION16_DATA) + (finalNbRects * sizeof(RECTANGLE_16));
+		data = realloc(region->data, allocSize);
+		if (!data)
+			free(region->data);
+		region->data = data;
 
 		if (!region->data)
 		{
@@ -485,10 +489,12 @@ static BOOL region16_simplify_bands(REGION16* region)
 
 BOOL region16_union_rect(REGION16* dst, const REGION16* src, const RECTANGLE_16* rect)
 {
+	REGION16_DATA* data;
 	const RECTANGLE_16* srcExtents;
 	RECTANGLE_16* dstExtents;
 	const RECTANGLE_16* currentBand, *endSrcRect, *nextBand;
 	REGION16_DATA* newItems = NULL;
+	REGION16_DATA* tmpItems = NULL;
 	RECTANGLE_16* dstRect = NULL;
 	UINT32 usedRects, srcNbRects;
 	UINT16 topInterBand;
@@ -673,7 +679,11 @@ BOOL region16_union_rect(REGION16* dst, const REGION16* src, const RECTANGLE_16*
 	dstExtents->bottom = MAX(rect->bottom, srcExtents->bottom);
 	dstExtents->right = MAX(rect->right, srcExtents->right);
 	newItems->size = sizeof(REGION16_DATA) + (usedRects * sizeof(RECTANGLE_16));
-	dst->data = realloc(newItems, newItems->size);
+	tmpItems = realloc(newItems, newItems->size);
+	if (!tmpItems)
+		free(newItems);
+	newItems = tmpItems;
+	dst->data = newItems;
 
 	if (!dst->data)
 	{
@@ -717,6 +727,7 @@ BOOL region16_intersects_rect(const REGION16* src, const RECTANGLE_16* arg2)
 
 BOOL region16_intersect_rect(REGION16* dst, const REGION16* src, const RECTANGLE_16* rect)
 {
+	REGION16_DATA* data;
 	REGION16_DATA* newItems;
 	const RECTANGLE_16* srcPtr, *endPtr, *srcExtents;
 	RECTANGLE_16* dstPtr;

programming_language: C
filename: lodepng.c
change_type: ModificationType.MODIFY
diff: @@ -841,11 +841,15 @@ unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequen
 static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies,
                                                 size_t mincodes, size_t numcodes, unsigned maxbitlen)
 {
+	unsigned* lengths;
   unsigned error = 0;
   while(!frequencies[numcodes - 1] && numcodes > mincodes) numcodes--; /*trim zeroes*/
   tree->maxbitlen = maxbitlen;
   tree->numcodes = (unsigned)numcodes; /*number of symbols*/
-  tree->lengths = (unsigned*)realloc(tree->lengths, numcodes * sizeof(unsigned));
+  lengths = (unsigned*)realloc(tree->lengths, numcodes * sizeof(unsigned));
+	if (!lengths)
+		free(tree->lengths);
+	tree->lengths = lengths;
   if(!tree->lengths) return 83; /*alloc fail*/
   /*initialize all lengths to 0*/
   memset(tree->lengths, 0, numcodes * sizeof(unsigned));

programming_language: C++