CVE-2022-1437: Out-of-bounds Write (CWE-787)
value: Heap-based Buffer Overflow in GitHub repository radareorg/radare2 prior to 5.7.0. The bug causes the program reads data past the end of the intented buffer. Typically, this can allow attackers to read sensitive information from other memory locations or cause a crash.
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.1
Published: 2022-04-22T15:15Z
Repository: https://github.com/radareorg/radare2
Language: C
Files changed: libr/bin/format/mach0/coresymbolication.c, libr/bin/p/bin_symbols.c
Commit date: 2022-04-22 15:55:12 +0200
Commit message: Fix oobread and null deref in symbols file parser ##crash

* Reported by @cnitlrt
* BountyID: af6c3e9e-b7df-4d80-b48f-77fdd17b4038/
* Reproducer: symoob

Diff: diff --git a/libr/bin/format/mach0/coresymbolication.c b/libr/bin/format/mach0/coresymbolication.c
index f554898c9401..949afc42cca1 100644
--- a/libr/bin/format/mach0/coresymbolication.c
+++ b/libr/bin/format/mach0/coresymbolication.c
@@ -267,10 +267,13 @@ RCoreSymCacheElement *r_coresym_cache_element_new(RBinFile *bf, RBuffer *buf, ut
 		size_t i;
 		ut8 *cursor = b + start_of_sections;
 		for (i = 0; i < hdr->n_sections && cursor < end; i++) {
 			ut8 *sect_start = cursor;
 			RCoreSymCacheElementSection *sect = &result->sections[i];
+			if (cursor + (word_size * 4) > end) {
+				goto beach;
+			}
 			sect->vaddr = sect->paddr = r_read_ble (cursor, false, bits);
 			if (sect->vaddr < page_zero_size) {
 				sect->vaddr += page_zero_size;
 			}
 			cursor += word_size;
@@ -357,10 +360,14 @@ RCoreSymCacheElement *r_coresym_cache_element_new(RBinFile *bf, RBuffer *buf, ut
 			if (!lsym->sym.mangled_name) {
 				cursor += R_CS_EL_SIZE_LSYM;
 				continue;
 			}
 			string_origin = relative_to_strings? b + start_of_strings : cursor;
+			if (!string_origin) {
+				cursor += R_CS_EL_SIZE_LSYM;
+				continue;
+			}
 			lsym->flc.file = str_dup_safe (b, string_origin + file_name_off, end);
 			if (!lsym->flc.file) {
 				cursor += R_CS_EL_SIZE_LSYM;
 				continue;
 			}
diff --git a/libr/bin/p/bin_symbols.c b/libr/bin/p/bin_symbols.c
index 779e36940ff1..5177be7886f2 100644
--- a/libr/bin/p/bin_symbols.c
+++ b/libr/bin/p/bin_symbols.c
@@ -351,32 +351,34 @@ static bool check_buffer(RBinFile *bf, RBuffer *b) {
 	r_buf_read_at (b, 0, buf, sizeof (buf));
 	return !memcmp (buf, "\x02\xff\x01\xff", 4);
 }
 
 static RList *symbols(RBinFile *bf) {
-	RList *res = r_list_newf ((RListFree)r_bin_symbol_free);
-	r_return_val_if_fail (res && bf->o && bf->o->bin_obj, res);
+	r_return_val_if_fail (bf && bf->o && bf->o->bin_obj, NULL);
 	RCoreSymCacheElement *element = bf->o->bin_obj;
 	size_t i;
 	HtUU *hash = ht_uu_new0 ();
 	if (!hash) {
-		return res;
+		return NULL;
 	}
+	RList *res = r_list_newf ((RListFree)r_bin_symbol_free);
 	bool found = false;
-	for (i = 0; i < element->hdr->n_lined_symbols; i++) {
-		RCoreSymCacheElementSymbol *sym = (RCoreSymCacheElementSymbol *)&element->lined_symbols[i];
-		if (!sym) {
-			break;
-		}
-		ht_uu_find (hash, sym->paddr, &found);
-		if (found) {
-			continue;
-		}
-		RBinSymbol *s = bin_symbol_from_symbol (element, sym);
-		if (s) {
-			r_list_append (res, s);
-			ht_uu_insert (hash, sym->paddr, 1);
+	if (element->lined_symbols) {
+		for (i = 0; i < element->hdr->n_lined_symbols; i++) {
+			RCoreSymCacheElementSymbol *sym = (RCoreSymCacheElementSymbol *)&element->lined_symbols[i];
+			if (!sym) {
+				break;
+			}
+			ht_uu_find (hash, sym->paddr, &found);
+			if (found) {
+				continue;
+			}
+			RBinSymbol *s = bin_symbol_from_symbol (element, sym);
+			if (s) {
+				r_list_append (res, s);
+				ht_uu_insert (hash, sym->paddr, 1);
+			}
 		}
 	}
 	if (element->symbols) {
 		for (i = 0; i < element->hdr->n_symbols; i++) {
 			RCoreSymCacheElementSymbol *sym = &element->symbols[i];

Vulnerable code: 	RList *res = r_list_newf ((RListFree)r_bin_symbol_free);
	r_return_val_if_fail (res && bf->o && bf->o->bin_obj, res);
		return res;
	for (i = 0; i < element->hdr->n_lined_symbols; i++) {
		RCoreSymCacheElementSymbol *sym = (RCoreSymCacheElementSymbol *)&element->lined_symbols[i];
		if (!sym) {
			break;
		}
		ht_uu_find (hash, sym->paddr, &found);
		if (found) {
			continue;
		}
		RBinSymbol *s = bin_symbol_from_symbol (element, sym);
		if (s) {
			r_list_append (res, s);
			ht_uu_insert (hash, sym->paddr, 1);
Fixed code: 			if (cursor + (word_size * 4) > end) {
				goto beach;
			}
			if (!string_origin) {
				cursor += R_CS_EL_SIZE_LSYM;
				continue;
			}
	r_return_val_if_fail (bf && bf->o && bf->o->bin_obj, NULL);
		return NULL;
	RList *res = r_list_newf ((RListFree)r_bin_symbol_free);
	if (element->lined_symbols) {
		for (i = 0; i < element->hdr->n_lined_symbols; i++) {
			RCoreSymCacheElementSymbol *sym = (RCoreSymCacheElementSymbol *)&element->lined_symbols[i];
			if (!sym) {
				break;
			}
			ht_uu_find (hash, sym->paddr, &found);
			if (found) {
				continue;
			}
			RBinSymbol *s = bin_symbol_from_symbol (element, sym);
			if (s) {
				r_list_append (res, s);
				ht_uu_insert (hash, sym->paddr, 1);
			}