CVE-2017-8326: Incorrect Calculation (CWE-682)
value: libimageworsener.a in ImageWorsener before 1.3.1 has "left shift cannot be represented in type int" undefined behavior issues, which might allow remote attackers to cause a denial of service (application crash) or possibly have unspecified other impact via a crafted image, related to imagew-bmp.c and imagew-util.c.
CWE description: The product performs a calculation that generates incorrect or unintended results that are later used in security-critical decisions or resource management.
CVSS v3 base score: 8.8
Published: 2017-04-29T20:59Z
Repository: https://github.com/jsummers/imageworsener
Language: C
Files changed: src/imagew-bmp.c, src/imagew-util.c
Commit date: 2017-04-22 08:51:22 -0400
Commit message: Trying to fix some invalid left shift operations

Fixes issue #16

Diff: diff --git a/src/imagew-bmp.c b/src/imagew-bmp.c
index 94619c5..9e51106 100644
--- a/src/imagew-bmp.c
+++ b/src/imagew-bmp.c
@@ -423,19 +423,19 @@ done:
 // Find the highest/lowest bit that is set.
 static int find_high_bit(unsigned int x)
 {
 	int i;
 	for(i=31;i>=0;i--) {
-		if(x&(1<<i)) return i;
+		if(x&(1U<<(unsigned int)i)) return i;
 	}
 	return 0;
 }
 static int find_low_bit(unsigned int x)
 {
 	int i;
 	for(i=0;i<=31;i++) {
-		if(x&(1<<i)) return i;
+		if(x&(1U<<(unsigned int)i)) return i;
 	}
 	return 0;
 }
 
 // Given .bf_mask[k], set high_bit[k], low_bit[k], etc.
diff --git a/src/imagew-util.c b/src/imagew-util.c
index 72410c2..77f19a8 100644
--- a/src/imagew-util.c
+++ b/src/imagew-util.c
@@ -400,31 +400,34 @@ IW_IMPL(void) iw_set_ui32be(iw_byte *b, unsigned int n)
 	b[3] = n&0xff;
 }
 
 IW_IMPL(unsigned int) iw_get_ui16le(const iw_byte *b)
 {
-	return b[0] | (b[1]<<8);
+	return (unsigned int)b[0] | ((unsigned int)b[1]<<8);
 }
 
 IW_IMPL(unsigned int) iw_get_ui32le(const iw_byte *b)
 {
-	return b[0] | (b[1]<<8) | (b[2]<<16) | (b[3]<<24);
+	return (unsigned int)b[0] | ((unsigned int)b[1]<<8) |
+		((unsigned int)b[2]<<16) | ((unsigned int)b[3]<<24);
 }
 
 IW_IMPL(int) iw_get_i32le(const iw_byte *b)
 {
-	return (iw_int32)(iw_uint32)(b[0] | (b[1]<<8) | (b[2]<<16) | (b[3]<<24));
+	return (iw_int32)(iw_uint32)((unsigned int)b[0] | ((unsigned int)b[1]<<8) |
+		((unsigned int)b[2]<<16) | ((unsigned int)b[3]<<24));
 }
 
 IW_IMPL(unsigned int) iw_get_ui16be(const iw_byte *b)
 {
-	return (b[0]<<8) | b[1];
+	return ((unsigned int)b[0]<<8) | (unsigned int)b[1];
 }
 
 IW_IMPL(unsigned int) iw_get_ui32be(const iw_byte *b)
 {
-	return (b[0]<<24) | (b[1]<<16) | (b[2]<<8) | b[3];
+	return ((unsigned int)b[0]<<24) | ((unsigned int)b[1]<<16) |
+		((unsigned int)b[2]<<8) | (unsigned int)b[3];
 }
 
 // Accepts a flag indicating the endianness.
 IW_IMPL(unsigned int) iw_get_ui16_e(const iw_byte *b, int endian)
 {

Vulnerable code: 		if(x&(1<<i)) return i;
		if(x&(1<<i)) return i;
	return b[0] | (b[1]<<8);
	return b[0] | (b[1]<<8) | (b[2]<<16) | (b[3]<<24);
	return (iw_int32)(iw_uint32)(b[0] | (b[1]<<8) | (b[2]<<16) | (b[3]<<24));
	return (b[0]<<8) | b[1];
	return (b[0]<<24) | (b[1]<<16) | (b[2]<<8) | b[3];
Fixed code: 		if(x&(1U<<(unsigned int)i)) return i;
		if(x&(1U<<(unsigned int)i)) return i;
	return (unsigned int)b[0] | ((unsigned int)b[1]<<8);
	return (unsigned int)b[0] | ((unsigned int)b[1]<<8) |
		((unsigned int)b[2]<<16) | ((unsigned int)b[3]<<24);
	return (iw_int32)(iw_uint32)((unsigned int)b[0] | ((unsigned int)b[1]<<8) |
		((unsigned int)b[2]<<16) | ((unsigned int)b[3]<<24));
	return ((unsigned int)b[0]<<8) | (unsigned int)b[1];
	return ((unsigned int)b[0]<<24) | ((unsigned int)b[1]<<16) |
		((unsigned int)b[2]<<8) | (unsigned int)b[3];