CVE-2017-6309: Out-of-bounds Write (CWE-787)
value: An issue was discovered in tnef before 1.4.13. Two type confusions have been identified in the parse_file() function. These might lead to invalid read and write operations, controlled by an attacker.
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.8
Published: 2017-02-24T04:59Z
Repository: https://github.com/verdammelt/tnef
Language: C
Files changed: src/file.c, src/tnef.c
Commit date: 2017-02-22 20:51:43 -0500
Commit message: Check types to avoid invalid reads/writes.

Diff: diff --git a/src/file.c b/src/file.c
index 4dacda4..4b3d81d 100644
--- a/src/file.c
+++ b/src/file.c
@@ -171,28 +171,32 @@ file_add_mapi_attrs (File* file, MAPI_Attr** attrs)
 	{
 
 	    switch (a->name)
 	    {
 	    case MAPI_ATTACH_LONG_FILENAME:
+		assert(a->type == szMAPI_STRING);
 		if (file->name) XFREE(file->name);
 		file->name = strdup( (char*)a->values[0].data.buf );
 		break;
 
 	    case MAPI_ATTACH_DATA_OBJ:
+		assert((a->type == szMAPI_BINARY) || (a->type == szMAPI_OBJECT));
 		file->len = a->values[0].len;
 		if (file->data) XFREE (file->data);
 		file->data = CHECKED_XMALLOC (unsigned char, file->len);
 		memmove (file->data, a->values[0].data.buf, file->len);
 		break;
 
              case MAPI_ATTACH_MIME_TAG:
+		assert(a->type == szMAPI_STRING);
 		if (file->mime_type) XFREE (file->mime_type);
 		file->mime_type = CHECKED_XMALLOC (char, a->values[0].len);
 		memmove (file->mime_type, a->values[0].data.buf, a->values[0].len);
 		break;
 
                 case MAPI_ATTACH_CONTENT_ID:
+                    assert(a->type == szMAPI_STRING);
                     if (file->content_id) XFREE(file->content_id);
                     file->content_id = CHECKED_XMALLOC (char, a->values[0].len);
                     memmove (file->content_id, a->values[0].data.buf, a->values[0].len);
                     break;
 
diff --git a/src/tnef.c b/src/tnef.c
index 0f1d9e4..7f74e88 100644
--- a/src/tnef.c
+++ b/src/tnef.c
@@ -163,14 +163,16 @@ get_html_data (MAPI_Attr *a)
     VarLenData **body = XCALLOC(VarLenData*, a->num_values + 1);
 
     int j;
     for (j = 0; j < a->num_values; j++)
     {
-	body[j] = XMALLOC(VarLenData, 1);
-	body[j]->len = a->values[j].len;
-	body[j]->data = CHECKED_XCALLOC(unsigned char, a->values[j].len);
-	memmove (body[j]->data, a->values[j].data.buf, body[j]->len);
+        if (a->type == szMAPI_BINARY) {
+ 	    body[j] = XMALLOC(VarLenData, 1);
+	    body[j]->len = a->values[j].len;
+	    body[j]->data = CHECKED_XCALLOC(unsigned char, a->values[j].len);
+	    memmove (body[j]->data, a->values[j].data.buf, body[j]->len);
+        }
     }
     return body;
 }
 
 int
@@ -304,17 +306,17 @@ parse_file (FILE* input_file, char* directory,
 		{ 
 		    int i;
 		    for (i = 0; mapi_attrs[i]; i++)
 		    {
 			MAPI_Attr *a = mapi_attrs[i];
-			    
-			if (a->name == MAPI_BODY_HTML)
+		
+			if (a->type == szMAPI_BINARY && a->name == MAPI_BODY_HTML)
 			{
 			    body.html_bodies = get_html_data (a);
                                 html_size = a->num_values;
 			}
-			else if (a->name == MAPI_RTF_COMPRESSED)
+			else if (a->type == szMAPI_BINARY && a->name == MAPI_RTF_COMPRESSED)
 			{
 			    body.rtf_bodies = get_rtf_data (a);
                                 rtf_size = a->num_values;
 			}
 		    }

Vulnerable code: 	body[j] = XMALLOC(VarLenData, 1);
	body[j]->len = a->values[j].len;
	body[j]->data = CHECKED_XCALLOC(unsigned char, a->values[j].len);
	memmove (body[j]->data, a->values[j].data.buf, body[j]->len);
			    
			if (a->name == MAPI_BODY_HTML)
			else if (a->name == MAPI_RTF_COMPRESSED)
Fixed code: 		assert(a->type == szMAPI_STRING);
		assert((a->type == szMAPI_BINARY) || (a->type == szMAPI_OBJECT));
		assert(a->type == szMAPI_STRING);
                    assert(a->type == szMAPI_STRING);
        if (a->type == szMAPI_BINARY) {
 	    body[j] = XMALLOC(VarLenData, 1);
	    body[j]->len = a->values[j].len;
	    body[j]->data = CHECKED_XCALLOC(unsigned char, a->values[j].len);
	    memmove (body[j]->data, a->values[j].data.buf, body[j]->len);
        }
		
			if (a->type == szMAPI_BINARY && a->name == MAPI_BODY_HTML)
			else if (a->type == szMAPI_BINARY && a->name == MAPI_RTF_COMPRESSED)