CVE-2017-16805 (published 2017-11-13T21:29Z)

In radare2 2.0.1, libr/bin/dwarf.c allows remote attackers to cause a denial of service (invalid read and application crash) via a crafted ELF file, related to r_bin_dwarf_parse_comp_unit in dwarf.c and sdb_set_internal in shlr/sdb/src/sdb.c.

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

Weakness information:
cwe_id: CWE-125
cwe_name: Out-of-bounds Read
description: The product reads data past the end, or before the beginning, of the intended buffer.
extended_description: 
            
            
             
			 
         
         

Fix information:
repo_url: https://github.com/radare/radare2
commit_details: repo_url: https://github.com/radare/radare2
author: pancake
author_date: 2017-11-14 04:15:54+09:00
msg: Fix #8813 - segfault in dwarf parser
repository: repo_url: https://github.com/radare/radare2
repo_name: radareorg/radare2
description: UNIX-like reverse engineering framework and command-line toolset
repo_language: C
owner: radare
file_changes: filename: dwarf.c
change_type: ModificationType.MODIFY
diff: @@ -1,4 +1,4 @@
-/* radare - LGPL - Copyright 2012-2016 - pancake, Fedor Sakharov */
+/* radare - LGPL - Copyright 2012-2017 - pancake, Fedor Sakharov */
 
 #define D0 if(1)
 #define D1 if(1)
@@ -1144,8 +1144,9 @@ static void r_bin_dwarf_dump_debug_info(FILE *f, const RBinDwarfDebugInfo *inf)
 			values = dies[j].attr_values;
 
 			for (k = 0; k < dies[j].length; k++) {
-				if (!values[k].name)
+				if (!values[k].name) {
 					continue;
+				}
 
 				if (values[k].name < DW_AT_vtable_elem_location &&
 						dwarf_attr_encodings[values[k].name]) {
@@ -1168,7 +1169,7 @@ static const ut8 *r_bin_dwarf_parse_attr_value(const ut8 *obuf, int obuf_len,
 	const ut8 *buf_end = obuf + obuf_len;
 	size_t j;
 
-	if (!spec || !value || !hdr || !obuf || obuf_len < 0) {
+	if (!spec || !value || !hdr || !obuf || obuf_len < 1) {
 		return NULL;
 	}
 
@@ -1194,7 +1195,7 @@ static const ut8 *r_bin_dwarf_parse_attr_value(const ut8 *obuf, int obuf_len,
 			value->encoding.address = READ (buf, ut64);
 			break;
 		default:
-			eprintf("DWARF: Unexpected pointer size: %u\n", (unsigned)hdr->pointer_size);
+			eprintf ("DWARF: Unexpected pointer size: %u\n", (unsigned)hdr->pointer_size);
 			return NULL;
 		}
 		break;
@@ -1219,6 +1220,8 @@ static const ut8 *r_bin_dwarf_parse_attr_value(const ut8 *obuf, int obuf_len,
 			value->encoding.block.data = data;
 		}
 		break;
+#if 0
+// This causes segfaults to happen
 	case DW_FORM_data2:
 		value->encoding.data = READ (buf, ut16);
 		break;
@@ -1228,6 +1231,7 @@ static const ut8 *r_bin_dwarf_parse_attr_value(const ut8 *obuf, int obuf_len,
 	case DW_FORM_data8:
 		value->encoding.data = READ (buf, ut64);
 		break;
+#endif
 	case DW_FORM_string:
 		value->encoding.str_struct.string = *buf? strdup ((const char*)buf) : NULL;
 		buf += (strlen ((const char*)buf) + 1);
@@ -1237,16 +1241,20 @@ static const ut8 *r_bin_dwarf_parse_attr_value(const ut8 *obuf, int obuf_len,
 		if (!buf) {
 			return NULL;
 		}
-		value->encoding.block.data = calloc (sizeof(ut8), value->encoding.block.length);
-		for (j = 0; j < value->encoding.block.length; j++) {
-			value->encoding.block.data[j] = READ (buf, ut8);
+		value->encoding.block.data = calloc (sizeof (ut8), value->encoding.block.length);
+		if (value->encoding.block.data) {
+			for (j = 0; j < value->encoding.block.length; j++) {
+				value->encoding.block.data[j] = READ (buf, ut8);
+			}
 		}
 		break;
 	case DW_FORM_block1:
 		value->encoding.block.length = READ (buf, ut8);
 		value->encoding.block.data = calloc (sizeof (ut8), value->encoding.block.length + 1);
-		for (j = 0; j < value->encoding.block.length; j++) {
-			value->encoding.block.data[j] = READ (buf, ut8);
+		if (value->encoding.block.data) {
+			for (j = 0; j < value->encoding.block.length; j++) {
+				value->encoding.block.data[j] = READ (buf, ut8);
+			}
 		}
 		break;
 	case DW_FORM_flag:
@@ -1344,8 +1352,7 @@ static const ut8 *r_bin_dwarf_parse_comp_unit(Sdb *s, const ut8 *obuf,
 				eprintf ("Warning: malformed dwarf attribute capacity doesn't match length\n");
 				break;
 			}
-			memset (&cu->dies[cu->length].attr_values[i], 0, sizeof
-					(cu->dies[cu->length].attr_values[i]));
+			memset (&cu->dies[cu->length].attr_values[i], 0, sizeof (cu->dies[cu->length].attr_values[i]));
 			buf = r_bin_dwarf_parse_attr_value (buf, buf_end - buf,
 					&da->decls[abbr_code - 1].specs[i],
 					&cu->dies[cu->length].attr_values[i],

programming_language: Lua
filename: r_bin_dwarf.h
change_type: ModificationType.MODIFY
diff: @@ -622,7 +622,7 @@ typedef union {
 	ut64	data;
 	st64	sdata;
 	ut64	reference;
-	struct str_structt {
+	struct {
 		char	*string;
 		ut64	offset;
 	} str_struct;

programming_language: C