CVE-2022-1809: Access of Uninitialized Pointer (CWE-824)
value: Access of Uninitialized Pointer in GitHub repository radareorg/radare2 prior to 5.7.0.
CWE description: The product accesses or uses a pointer that has not been initialized.
CVSS v3 base score: 7.8
Published: 2022-05-21T23:16Z
Repository: https://github.com/radareorg/radare2
Language: C
Files changed: libr/anal/vtable.c
Commit date: 2022-05-21 22:47:36 +0200
Commit message: Fix crash in vtable analysis on UB ##crash

* Reported by @greatergoodest via huntrdev
* BountyID 0730a95e-c485-4ff2-9a5d-bb3abfda0b17
* Reproducer: minified_crash

Diff: diff --git a/libr/anal/vtable.c b/libr/anal/vtable.c
index d3be434800df..b819c8d693e3 100644
--- a/libr/anal/vtable.c
+++ b/libr/anal/vtable.c
@@ -56,10 +56,12 @@ R_API bool r_anal_vtable_begin(RAnal *anal, RVTableContext *context) {
 		break;
 	case 8:
 		context->read_addr = be? vtable_read_addr_be64 : vtable_read_addr_le64;
 		break;
 	default:
+		// cant be null. assume 32bit "->read_addr = NULL;
+		context->read_addr = be? vtable_read_addr_be32 : vtable_read_addr_le32;
 		return false;
 	}
 	return true;
 }
 
@@ -70,11 +72,11 @@ static bool vtable_addr_in_text_section(RVTableContext *context, ut64 curAddress
 	return value && strstr (value->name, "text") && (value->perm & 1) != 0;
 }
 
 static bool vtable_is_value_in_text_section(RVTableContext *context, ut64 curAddress, ut64 *value) {
 	//value at the current address
-	ut64 curAddressValue;
+	ut64 curAddressValue = UT64_MAX;
 	if (!context->read_addr (context->anal, curAddress, &curAddressValue)) {
 		return false;
 	}
 	//if the value is in text section
 	bool ret = vtable_addr_in_text_section (context, curAddressValue);
@@ -130,10 +132,11 @@ static bool vtable_is_addr_vtable_start_itanium(RVTableContext *context, RBinSec
 	}
 	return true;
 }
 
 static bool vtable_is_addr_vtable_start_msvc(RVTableContext *context, ut64 curAddress) {
+	ut8 buf[VTABLE_BUFF_SIZE];
 	RAnalRef *xref;
 	RListIter *xrefIter;
 
 	if (!curAddress || curAddress == UT64_MAX) {
 		return false;
@@ -148,23 +151,18 @@ static bool vtable_is_addr_vtable_start_msvc(RVTableContext *context, ut64 curAd
 		return false;
 	}
 	r_list_foreach (xrefs, xrefIter, xref) {
 		// section in which currenct xref lies
 		if (vtable_addr_in_text_section (context, xref->addr)) {
-			ut8 buf[VTABLE_BUFF_SIZE];
-			context->anal->iob.read_at (context->anal->iob.io, xref->addr, buf, sizeof(buf));
-
+			context->anal->iob.read_at (context->anal->iob.io, xref->addr, buf, sizeof (buf));
 			RAnalOp analop = {0};
-			r_anal_op (context->anal, &analop, xref->addr, buf, sizeof(buf), R_ANAL_OP_MASK_BASIC);
-
-			if (analop.type == R_ANAL_OP_TYPE_MOV
-				|| analop.type == R_ANAL_OP_TYPE_LEA) {
+			r_anal_op (context->anal, &analop, xref->addr, buf, sizeof (buf), R_ANAL_OP_MASK_BASIC);
+			if (analop.type == R_ANAL_OP_TYPE_MOV || analop.type == R_ANAL_OP_TYPE_LEA) {
 				r_list_free (xrefs);
 				r_anal_op_fini (&analop);
 				return true;
 			}
-
 			r_anal_op_fini (&analop);
 		}
 	}
 	r_list_free (xrefs);
 	return false;
@@ -284,11 +282,11 @@ R_API RList *r_anal_vtable_search(RVTableContext *context) {
 	}
 	return vtables;
 }
 
 R_API void r_anal_list_vtables(RAnal *anal, int rad) {
-	RVTableContext context;
+	RVTableContext context = {0};
 	r_anal_vtable_begin (anal, &context);
 
 	const char *noMethodName = "No Name found";
 	RVTableMethodInfo *curMethod;
 	RListIter *vtableIter;

Vulnerable code: 	ut64 curAddressValue;
			ut8 buf[VTABLE_BUFF_SIZE];
			context->anal->iob.read_at (context->anal->iob.io, xref->addr, buf, sizeof(buf));

			r_anal_op (context->anal, &analop, xref->addr, buf, sizeof(buf), R_ANAL_OP_MASK_BASIC);

			if (analop.type == R_ANAL_OP_TYPE_MOV
				|| analop.type == R_ANAL_OP_TYPE_LEA) {

	RVTableContext context;
Fixed code: 		// cant be null. assume 32bit "->read_addr = NULL;
		context->read_addr = be? vtable_read_addr_be32 : vtable_read_addr_le32;
	ut64 curAddressValue = UT64_MAX;
	ut8 buf[VTABLE_BUFF_SIZE];
			context->anal->iob.read_at (context->anal->iob.io, xref->addr, buf, sizeof (buf));
			r_anal_op (context->anal, &analop, xref->addr, buf, sizeof (buf), R_ANAL_OP_MASK_BASIC);
			if (analop.type == R_ANAL_OP_TYPE_MOV || analop.type == R_ANAL_OP_TYPE_LEA) {
	RVTableContext context = {0};