CVE-2017-9520: Use After Free (CWE-416)
value: The r_config_set function in libr/config/config.c in radare2 1.5.0 allows remote attackers to cause a denial of service (use-after-free and application crash) via a crafted DEX file.
CWE description: The product reuses or references memory after it has been freed. At some point afterward, the memory may be allocated again and saved in another pointer, while the original pointer references a location somewhere within the new allocation. Any operations using the original pointer are no longer valid because the memory "belongs" to the code that operates on the new pointer.
CVSS v3 base score: 5.5
Published: 2017-06-08T14:29Z
Repository: https://github.com/radare/radare2
Language: C
Files changed: libr/config/config.c, libr/core/cbin.c
Commit date: 2017-06-07 23:51:13 +0200
Commit message: Fix #7698 - UAF in r_config_set when loading a dex

Diff: diff --git a/libr/config/config.c b/libr/config/config.c
index 4eaa7b876c6..c2b3662b294 100644
--- a/libr/config/config.c
+++ b/libr/config/config.c
@@ -386,12 +386,13 @@ R_API RConfigNode* r_config_set(RConfig *cfg, const char *name, const char *valu
 				node->i_value = 0;
 			} else {
 				if (node->value == value) {
 					goto beach;
 				}
-				free (node->value);
+				char *tmp = node->value;
 				node->value = strdup (value);
+				free (tmp);
 				if (IS_DIGIT (*value)) {
 					if (strchr (value, '/')) {
 						node->i_value = r_num_get (cfg->num, value);
 					} else {
 						node->i_value = r_num_math (cfg->num, value);
diff --git a/libr/core/cbin.c b/libr/core/cbin.c
index 65e088aee22..add791c1c7a 100644
--- a/libr/core/cbin.c
+++ b/libr/core/cbin.c
@@ -94,28 +94,31 @@ R_API int r_core_bin_set_by_name(RCore *core, const char * name) {
 R_API int r_core_bin_set_env(RCore *r, RBinFile *binfile) {
 	RBinObject *binobj = binfile ? binfile->o: NULL;
 	RBinInfo *info = binobj ? binobj->info: NULL;
 	if (info) {
 		int va = info->has_va;
-		const char * arch = info->arch;
+		char * arch = strdup(info->arch);
+		char * cpu = info->cpu? strdup(info->cpu): NULL;
 		ut16 bits = info->bits;
 		ut64 baseaddr = r_bin_get_baddr (r->bin);
 		/* Hack to make baddr work on some corner */
 		r_config_set_i (r->config, "io.va",
 			(binobj->info)? binobj->info->has_va: 0);
 		r_config_set_i (r->config, "bin.baddr", baseaddr);
 		r_config_set (r->config, "asm.arch", arch);
 		r_config_set_i (r->config, "asm.bits", bits);
 		r_config_set (r->config, "anal.arch", arch);
-		if (info->cpu && *info->cpu) {
-			r_config_set (r->config, "anal.cpu", info->cpu);
+		if (cpu && *cpu) {
+			r_config_set (r->config, "anal.cpu", cpu);
 		} else {
 			r_config_set (r->config, "anal.cpu", arch);
 		}
 		r_asm_use (r->assembler, arch);
 		r_core_bin_info (r, R_CORE_BIN_ACC_ALL, R_CORE_BIN_SET, va, NULL, NULL);
 		r_core_bin_set_cur (r, binfile);
+		free (cpu);
+		free (arch);
 		return true;
 	}
 	return false;
 }
 

Vulnerable code: 				free (node->value);
		const char * arch = info->arch;
		if (info->cpu && *info->cpu) {
			r_config_set (r->config, "anal.cpu", info->cpu);
Fixed code: 				char *tmp = node->value;
				free (tmp);
		char * arch = strdup(info->arch);
		char * cpu = info->cpu? strdup(info->cpu): NULL;
		if (cpu && *cpu) {
			r_config_set (r->config, "anal.cpu", cpu);
		free (cpu);
		free (arch);