CVE-2021-20304 (published 2022-08-23T16:15Z)

A flaw was found in OpenEXR's hufDecode functionality. This flaw allows an attacker who can pass a crafted file to be processed by OpenEXR, to trigger an undefined right shift error. The highest threat from this vulnerability is to system availability.

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-190
cwe_name: Integer Overflow or Wraparound
description: The product performs a calculation that can
         produce an integer overflow or wraparound when the logic
         assumes that the resulting value will always be larger than
         the original value. This occurs when an integer value is
         incremented to a value that is too large to store in the
         associated representation. When this occurs, the value may
         become a very small or negative number.
extended_description: 
            
            
            
            
         
         

Fix information:
repo_url: https://github.com/AcademySoftwareFoundation/openexr
commit_details: repo_url: https://github.com/AcademySoftwareFoundation/openexr
author: peterhillman
author_date: 2020-10-13 08:03:57+13:00
msg: check for valid Huf code lengths (#849)

* check for valid Huf code lengths
* test non-fast huf decoder in testHuf

Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
repository: repo_url: https://github.com/AcademySoftwareFoundation/openexr
repo_name: AcademySoftwareFoundation/openexr
description: The OpenEXR project provides the specification and reference implementation of the EXR file format, the professional-grade image storage format of the motion picture industry.
repo_language: C
owner: AcademySoftwareFoundation
file_changes: filename: ImfHuf.cpp
change_type: ModificationType.MODIFY
diff: @@ -910,6 +910,11 @@ hufDecode
 		//
 
 		lc -= pl.len;
+
+		if ( lc < 0 )
+		{
+			invalidCode(); // code length too long
+		}
 		getCode (pl.lit, rlc, c, lc, in, out, outb, oe);
 	    }
 	    else
@@ -967,6 +972,10 @@ hufDecode
 	if (pl.len)
 	{
 	    lc -= pl.len;
+            if ( lc < 0 )
+            {
+   	        invalidCode(); // code length too long
+            }
 	    getCode (pl.lit, rlc, c, lc, in, out, outb, oe);
 	}
 	else

programming_language: C++
filename: testHuf.cpp
change_type: ModificationType.MODIFY
diff: @@ -245,70 +245,86 @@ testHuf (const std::string&)
 
 	IMATH_NAMESPACE::Rand48 rand48 (0);
 
-	const int N = 1000000;
-	Array <unsigned short> raw (N);
-
-	fill1 (raw, N, 1, rand48);	  // test various symbol distributions
-	compressUncompress (raw, N);
-	compressUncompressSubset (raw, N);
-	fill1 (raw, N, 10, rand48);
-	compressUncompress (raw, N);
-	compressUncompressSubset (raw, N);
-	fill1 (raw, N, 100, rand48);
-	compressUncompress (raw, N);
-	compressUncompressSubset (raw, N);
-	fill1 (raw, N, 1000, rand48);
-	compressUncompress (raw, N);
-	compressUncompressSubset (raw, N);
-
-	fill2 (raw, N, 1, rand48);
-	compressUncompress (raw, N);
-	compressUncompressSubset (raw, N);
-	fill2 (raw, N, 10, rand48);
-	compressUncompress (raw, N);
-	compressUncompressSubset (raw, N);
-	fill2 (raw, N, 100, rand48);
-	compressUncompress (raw, N);
-	compressUncompressSubset (raw, N);
-	fill2 (raw, N, 1000, rand48);
-	compressUncompress (raw, N);
-	compressUncompressSubset (raw, N);
-
-	fill3 (raw, N, 0);
-	compressUncompress (raw, N);
-	compressUncompressSubset (raw, N);
-	fill3 (raw, N, 1);
-	compressUncompress (raw, N);
-	compressUncompressSubset (raw, N);
-	fill3 (raw, N, USHRT_MAX - 1);
-	compressUncompress (raw, N);
-	compressUncompressSubset (raw, N);
-	fill3 (raw, N, USHRT_MAX);
-	compressUncompress (raw, N);
-	compressUncompressSubset (raw, N);
-
-	fill4 (raw, USHRT_MAX + 1);
-        compressVerify(raw, USHRT_MAX + 1, HUF_COMPRESS_DEK_HASH_FOR_FILL4_USHRT_MAX_PLUS_ONE);
-	compressUncompress (raw, USHRT_MAX + 1);
-	compressUncompressSubset (raw, USHRT_MAX + 1);
-	fill4 (raw, N);
-        compressVerify(raw, N, HUF_COMPRESS_DEK_HASH_FOR_FILL4_N);
-	compressUncompress (raw, N);
-	compressUncompressSubset (raw, N);
-
-	fill4 (raw, 0);
-	compressUncompress (raw, 0);	// test small input data sets
-	fill4 (raw, 1);
-	compressUncompress (raw, 1);
-	fill4 (raw, 2);
-	compressUncompress (raw, 2);
-	fill4 (raw, 3);
-	compressUncompress (raw, 3);
-
-	fill5 (raw, N);			// test run-length coding of code table
-        compressVerify(raw, N, HUF_COMPRESS_DEK_HASH_FOR_FILL5_N);
-	compressUncompress (raw, N);
-	compressUncompressSubset (raw, N);
+        //
+        // FastHufDecoder is used for more than 128 bits, so first test with fewer than 128 bits,
+        // then test FastHufDecoder
+        //
+        for (int pass = 0 ; pass < 2 ; ++pass)
+        {
+
+            int N = pass==0 ? 12 : 1000000;
+            Array <unsigned short> raw (N);
+
+            fill1 (raw, N, 1, rand48);	  // test various symbol distributions
+            compressUncompress (raw, N);
+            compressUncompressSubset (raw, N);
+            fill1 (raw, N, 10, rand48);
+            compressUncompress (raw, N);
+            compressUncompressSubset (raw, N);
+            fill1 (raw, N, 100, rand48);
+            compressUncompress (raw, N);
+            compressUncompressSubset (raw, N);
+            fill1 (raw, N, 1000, rand48);
+            compressUncompress (raw, N);
+            compressUncompressSubset (raw, N);
+
+            fill2 (raw, N, 1, rand48);
+            compressUncompress (raw, N);
+            compressUncompressSubset (raw, N);
+            fill2 (raw, N, 10, rand48);
+            compressUncompress (raw, N);
+            compressUncompressSubset (raw, N);
+            fill2 (raw, N, 100, rand48);
+            compressUncompress (raw, N);
+            compressUncompressSubset (raw, N);
+            fill2 (raw, N, 1000, rand48);
+            compressUncompress (raw, N);
+            compressUncompressSubset (raw, N);
+
+            fill3 (raw, N, 0);
+            compressUncompress (raw, N);
+            compressUncompressSubset (raw, N);
+            fill3 (raw, N, 1);
+            compressUncompress (raw, N);
+            compressUncompressSubset (raw, N);
+            fill3 (raw, N, USHRT_MAX - 1);
+            compressUncompress (raw, N);
+            compressUncompressSubset (raw, N);
+            fill3 (raw, N, USHRT_MAX);
+            compressUncompress (raw, N);
+            compressUncompressSubset (raw, N);
+
+            if (pass==1)
+            {
+                fill4 (raw, USHRT_MAX + 1);
+                compressVerify(raw, USHRT_MAX + 1, HUF_COMPRESS_DEK_HASH_FOR_FILL4_USHRT_MAX_PLUS_ONE);
+
+                compressUncompress (raw, USHRT_MAX + 1);
+                compressUncompressSubset (raw, USHRT_MAX + 1);
+                fill4 (raw, N);
+                compressVerify(raw, N, HUF_COMPRESS_DEK_HASH_FOR_FILL4_N);
+            }
+            compressUncompress (raw, N);
+            compressUncompressSubset (raw, N);
+
+            fill4 (raw, 0);
+            compressUncompress (raw, 0);	// test small input data sets
+            fill4 (raw, 1);
+            compressUncompress (raw, 1);
+            fill4 (raw, 2);
+            compressUncompress (raw, 2);
+            fill4 (raw, 3);
+            compressUncompress (raw, 3);
+
+            fill5 (raw, N);			// test run-length coding of code table
+            if (pass==1)
+            {
+                compressVerify(raw, N, HUF_COMPRESS_DEK_HASH_FOR_FILL5_N);
+            }
+            compressUncompress (raw, N);
+            compressUncompressSubset (raw, N);
+
+        }
 
 	cout << "ok\n" << endl;
     }

programming_language: C++