Fix range check bugs

This is a patch hunting for fuzzing failures and adding
appropriate range checks.


Change-Id: Ieae02b7e461b9a6c5e25de6c663a768f7a0d5e10
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/cper-parse.c b/cper-parse.c
index 54f4cde..8b62ef6 100644
--- a/cper-parse.c
+++ b/cper-parse.c
@@ -411,14 +411,15 @@
 	return section_descriptor_ir;
 }
 
-json_object *read_section(const unsigned char *cper_section_buf,
-			  CPER_SECTION_DEFINITION *definition,
-			  json_object **section_ir)
+json_object *read_section(const unsigned char *cper_section_buf, size_t size,
+			  CPER_SECTION_DEFINITION *definition)
 {
-	*section_ir = definition->ToIR(cper_section_buf);
-
+	if (definition->ToIR == NULL) {
+		return NULL;
+	}
+	json_object *section_ir = definition->ToIR(cper_section_buf, size);
 	json_object *result = json_object_new_object();
-	json_object_object_add(result, definition->ShortName, *section_ir);
+	json_object_object_add(result, definition->ShortName, section_ir);
 	return result;
 }
 
@@ -435,15 +436,14 @@
 	json_object *result = NULL;
 
 	json_object *section_ir = NULL;
-	int section_converted = 0;
 	for (size_t i = 0; i < section_definitions_len; i++) {
 		if (!guid_equal(section_definitions[i].Guid,
 				&descriptor->SectionType)) {
 			continue;
 		}
-		result = read_section(cper_section_buf, &section_definitions[i],
-				      &section_ir);
-		section_converted = 1;
+		result = read_section(cper_section_buf, size,
+				      &section_definitions[i]);
+
 		break;
 	}
 
@@ -453,23 +453,21 @@
 	// a match, try to force a match so we get some coverage.  Note, we still
 	// want coverage of the section failed to convert code, so treat index ==
 	// size as section failed to convert.
-	if (!section_converted) {
+	if (result == NULL) {
 		unsigned char index = 0;
 		if (index > 0) {
 			index = descriptor->SectionType.Data1 %
 				section_definitions_len;
 		}
 		if (index < section_definitions_len) {
-			result = read_section(cper_section_buf,
-					      &section_definitions[index],
-					      &section_ir);
-			section_converted = 1;
+			result = read_section(cper_section_buf, size,
+					      &section_definitions[index]);
 		}
 	}
 #endif
 
 	//Was it an unknown GUID/failed read?
-	if (!section_converted) {
+	if (result == NULL) {
 		//Output the data as formatted base64.
 		int32_t encoded_len = 0;
 		char *encoded = base64_encode(cper_section_buf,
diff --git a/include/libcper/sections/cper-section-ampere.h b/include/libcper/sections/cper-section-ampere.h
index 013a59f..b03f2da 100644
--- a/include/libcper/sections/cper-section-ampere.h
+++ b/include/libcper/sections/cper-section-ampere.h
@@ -5,7 +5,7 @@
 #include <json.h>
 #include <libcper/Cper.h>
 
-json_object *cper_section_ampere_to_ir(const void *section);
+json_object *cper_section_ampere_to_ir(const UINT8 *section, UINT32 size);
 void ir_section_ampere_to_cper(json_object *section, FILE *out);
 
 #endif
diff --git a/include/libcper/sections/cper-section-arm.h b/include/libcper/sections/cper-section-arm.h
index c1c7f75..5433f80 100644
--- a/include/libcper/sections/cper-section-arm.h
+++ b/include/libcper/sections/cper-section-arm.h
@@ -77,6 +77,8 @@
 			  "Device Memory Access" }
 #define ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_KEYS                         \
 	(int[]){ 0, 1, 2, 3, 4, 5, 6, 7, 8 }
+#define ARM_BUS_ADDRESS_SPACE_TYPES_COUNT 9
+
 #define ARM_PROCESSOR_INFO_REGISTER_CONTEXT_TYPES_VALUES                       \
 	(const char *[]){ "AArch32 General Purpose Registers",                 \
 			  "AArch32 EL1 Context Registers",                     \
@@ -129,7 +131,7 @@
 			  "sctlr_el3", "sp_el3",   "spsr_el3", "tcr_el3",      \
 			  "tpidr_el3", "ttbr0_el3" }
 
-json_object *cper_section_arm_to_ir(const void *section);
+json_object *cper_section_arm_to_ir(const UINT8 *section, UINT32 size);
 void ir_section_arm_to_cper(json_object *section, FILE *out);
 
 #ifdef __cplusplus
diff --git a/include/libcper/sections/cper-section-ccix-per.h b/include/libcper/sections/cper-section-ccix-per.h
index a2b858f..256954c 100644
--- a/include/libcper/sections/cper-section-ccix-per.h
+++ b/include/libcper/sections/cper-section-ccix-per.h
@@ -24,7 +24,7 @@
 	UINT16 Reserved;
 } __attribute__((packed, aligned(1))) EFI_CCIX_PER_LOG_DATA;
 
-json_object *cper_section_ccix_per_to_ir(const void *section);
+json_object *cper_section_ccix_per_to_ir(const UINT8 *section, UINT32 size);
 void ir_section_ccix_per_to_cper(json_object *section, FILE *out);
 
 #ifdef __cplusplus
diff --git a/include/libcper/sections/cper-section-cxl-component.h b/include/libcper/sections/cper-section-cxl-component.h
index 5f1c400..3e3eb5c 100644
--- a/include/libcper/sections/cper-section-cxl-component.h
+++ b/include/libcper/sections/cper-section-cxl-component.h
@@ -35,7 +35,8 @@
 	UINT64 DeviceSerial;
 } __attribute__((packed, aligned(1))) EFI_CXL_COMPONENT_EVENT_HEADER;
 
-json_object *cper_section_cxl_component_to_ir(const void *section);
+json_object *cper_section_cxl_component_to_ir(const UINT8 *section,
+					      UINT32 size);
 void ir_section_cxl_component_to_cper(json_object *section, FILE *out);
 
 #ifdef __cplusplus
diff --git a/include/libcper/sections/cper-section-cxl-protocol.h b/include/libcper/sections/cper-section-cxl-protocol.h
index cdf23a0..f707003 100644
--- a/include/libcper/sections/cper-section-cxl-protocol.h
+++ b/include/libcper/sections/cper-section-cxl-protocol.h
@@ -63,7 +63,7 @@
 	UINT32 Reserved;
 } __attribute__((packed, aligned(1))) EFI_CXL_PROTOCOL_ERROR_DATA;
 
-json_object *cper_section_cxl_protocol_to_ir(const void *section);
+json_object *cper_section_cxl_protocol_to_ir(const UINT8 *section, UINT32 size);
 void ir_section_cxl_protocol_to_cper(json_object *section, FILE *out);
 
 #ifdef __cplusplus
diff --git a/include/libcper/sections/cper-section-dmar-generic.h b/include/libcper/sections/cper-section-dmar-generic.h
index a2eb08e..3376dd5 100644
--- a/include/libcper/sections/cper-section-dmar-generic.h
+++ b/include/libcper/sections/cper-section-dmar-generic.h
@@ -43,7 +43,7 @@
 #define DMAR_GENERIC_ERROR_ARCH_TYPES_KEYS   (int[]){ 0x0, 0x1 }
 #define DMAR_GENERIC_ERROR_ARCH_TYPES_VALUES (const char *[]){ "VT-d", "IOMMU" }
 
-json_object *cper_section_dmar_generic_to_ir(const void *section);
+json_object *cper_section_dmar_generic_to_ir(const UINT8 *section, UINT32 size);
 void ir_section_dmar_generic_to_cper(json_object *section, FILE *out);
 
 #ifdef __cplusplus
diff --git a/include/libcper/sections/cper-section-dmar-iommu.h b/include/libcper/sections/cper-section-dmar-iommu.h
index 9192e38..5bee4d4 100644
--- a/include/libcper/sections/cper-section-dmar-iommu.h
+++ b/include/libcper/sections/cper-section-dmar-iommu.h
@@ -9,7 +9,7 @@
 #include <json.h>
 #include <libcper/Cper.h>
 
-json_object *cper_section_dmar_iommu_to_ir(const void *section);
+json_object *cper_section_dmar_iommu_to_ir(const UINT8 *section, UINT32 size);
 void ir_section_dmar_iommu_to_cper(json_object *section, FILE *out);
 
 #ifdef __cplusplus
diff --git a/include/libcper/sections/cper-section-dmar-vtd.h b/include/libcper/sections/cper-section-dmar-vtd.h
index 68a1d79..3d248d1 100644
--- a/include/libcper/sections/cper-section-dmar-vtd.h
+++ b/include/libcper/sections/cper-section-dmar-vtd.h
@@ -28,7 +28,7 @@
 	UINT64 Resv3 : 1;
 } EFI_VTD_FAULT_RECORD;
 
-json_object *cper_section_dmar_vtd_to_ir(const void *section);
+json_object *cper_section_dmar_vtd_to_ir(const UINT8 *section, UINT32 size);
 void ir_section_dmar_vtd_to_cper(json_object *section, FILE *out);
 
 #ifdef __cplusplus
diff --git a/include/libcper/sections/cper-section-firmware.h b/include/libcper/sections/cper-section-firmware.h
index fb21cfb..87614dc 100644
--- a/include/libcper/sections/cper-section-firmware.h
+++ b/include/libcper/sections/cper-section-firmware.h
@@ -15,7 +15,7 @@
 			  "SOC Firmware Error Record (Type1 Legacy)",          \
 			  "SOC Firmware Error Record (Type2)" }
 
-json_object *cper_section_firmware_to_ir(const void *section);
+json_object *cper_section_firmware_to_ir(const UINT8 *section, UINT32 size);
 void ir_section_firmware_to_cper(json_object *section, FILE *out);
 
 #ifdef __cplusplus
diff --git a/include/libcper/sections/cper-section-generic.h b/include/libcper/sections/cper-section-generic.h
index ac041d4..bc7c112 100644
--- a/include/libcper/sections/cper-section-generic.h
+++ b/include/libcper/sections/cper-section-generic.h
@@ -39,7 +39,7 @@
 #define GENERIC_FLAGS_BITFIELD_NAMES                                           \
 	(const char *[]){ "restartable", "preciseIP", "overflow", "corrected" }
 
-json_object *cper_section_generic_to_ir(const void *section);
+json_object *cper_section_generic_to_ir(const UINT8 *section, UINT32 size);
 void ir_section_generic_to_cper(json_object *section, FILE *out);
 
 #ifdef __cplusplus
diff --git a/include/libcper/sections/cper-section-ia32x64.h b/include/libcper/sections/cper-section-ia32x64.h
index 32f7826..b3a1233 100644
--- a/include/libcper/sections/cper-section-ia32x64.h
+++ b/include/libcper/sections/cper-section-ia32x64.h
@@ -66,6 +66,9 @@
 			  "64-bit Mode Debug Registers",                       \
 			  "Memory Mapper Registers" }
 
+#define IA32X64_REGISTER_CONTEXT_TYPES_SIZE                                    \
+	((sizeof(IA32X64_REGISTER_CONTEXT_TYPES_KEYS) / sizeof(int)))
+
 typedef struct {
 	UINT64 Eax;
 	UINT64 Ebx;
@@ -74,7 +77,7 @@
 	UINT64 Reserved[2];
 } EFI_IA32_X64_CPU_ID;
 
-json_object *cper_section_ia32x64_to_ir(const void *section);
+json_object *cper_section_ia32x64_to_ir(const UINT8 *section, UINT32 size);
 void ir_section_ia32x64_to_cper(json_object *section, FILE *out);
 
 #ifdef __cplusplus
diff --git a/include/libcper/sections/cper-section-ipf.h b/include/libcper/sections/cper-section-ipf.h
index be985b4..0541d65 100644
--- a/include/libcper/sections/cper-section-ipf.h
+++ b/include/libcper/sections/cper-section-ipf.h
@@ -65,7 +65,7 @@
 	UINT64 Frs[256];
 } EFI_IPF_PSI_STATIC;
 
-json_object *cper_section_ipf_to_ir(const void *section);
+json_object *cper_section_ipf_to_ir(const UINT8 *section, UINT32 size);
 
 #ifdef __cplusplus
 }
diff --git a/include/libcper/sections/cper-section-memory.h b/include/libcper/sections/cper-section-memory.h
index f759f1d..e8536dd 100644
--- a/include/libcper/sections/cper-section-memory.h
+++ b/include/libcper/sections/cper-section-memory.h
@@ -75,8 +75,10 @@
 			  "bankGroupValid",                                    \
 			  "bankAddressValid" }
 
-json_object *cper_section_platform_memory_to_ir(const void *section);
-json_object *cper_section_platform_memory2_to_ir(const void *section);
+json_object *cper_section_platform_memory_to_ir(const UINT8 *section,
+						UINT32 size);
+json_object *cper_section_platform_memory2_to_ir(const UINT8 *section,
+						 UINT32 size);
 void ir_section_memory_to_cper(json_object *section, FILE *out);
 void ir_section_memory2_to_cper(json_object *section, FILE *out);
 
diff --git a/include/libcper/sections/cper-section-nvidia.h b/include/libcper/sections/cper-section-nvidia.h
index df85792..cca9097 100644
--- a/include/libcper/sections/cper-section-nvidia.h
+++ b/include/libcper/sections/cper-section-nvidia.h
@@ -9,7 +9,7 @@
 #include <json.h>
 #include <libcper/Cper.h>
 
-json_object *cper_section_nvidia_to_ir(const void *section);
+json_object *cper_section_nvidia_to_ir(const UINT8 *section, UINT32 size);
 void ir_section_nvidia_to_cper(json_object *section, FILE *out);
 
 #ifdef __cplusplus
diff --git a/include/libcper/sections/cper-section-pci-bus.h b/include/libcper/sections/cper-section-pci-bus.h
index c4de3be..906af48 100644
--- a/include/libcper/sections/cper-section-pci-bus.h
+++ b/include/libcper/sections/cper-section-pci-bus.h
@@ -26,7 +26,7 @@
 			  "Address Parity Error",                              \
 			  "Command Parity Error" }
 
-json_object *cper_section_pci_bus_to_ir(const void *section);
+json_object *cper_section_pci_bus_to_ir(const UINT8 *section, UINT32 size);
 void ir_section_pci_bus_to_cper(json_object *section, FILE *out);
 
 #ifdef __cplusplus
diff --git a/include/libcper/sections/cper-section-pci-dev.h b/include/libcper/sections/cper-section-pci-dev.h
index 696a44b..cb6321c 100644
--- a/include/libcper/sections/cper-section-pci-dev.h
+++ b/include/libcper/sections/cper-section-pci-dev.h
@@ -29,14 +29,25 @@
 } EFI_PCI_PCIX_DEVICE_ID_INFO;
 
 typedef struct {
+	UINT64 Address;
+	UINT64 Value;
+} EFI_PCI_PCIX_DEVICE_ERROR_DATA_REGISTER;
+
+typedef struct {
 	UINT64 ValidFields;
 	EFI_GENERIC_ERROR_STATUS ErrorStatus;
 	EFI_PCI_PCIX_DEVICE_ID_INFO IdInfo;
 	UINT32 MemoryNumber;
 	UINT32 IoNumber;
+	// Keep this at the end of this struct
+	// and allocate based on NumberRegs
+#ifndef __cplusplus
+	EFI_PCI_PCIX_DEVICE_ERROR_DATA_REGISTER MemoryRegister[];
+#endif
+
 } __attribute__((packed, aligned(1))) EFI_PCI_PCIX_DEVICE_ERROR_DATA;
 
-json_object *cper_section_pci_dev_to_ir(const void *section);
+json_object *cper_section_pci_dev_to_ir(const UINT8 *section, UINT32 size);
 void ir_section_pci_dev_to_cper(json_object *section, FILE *out);
 
 #ifdef __cplusplus
diff --git a/include/libcper/sections/cper-section-pcie.h b/include/libcper/sections/cper-section-pcie.h
index 05307aa..93206b7 100644
--- a/include/libcper/sections/cper-section-pcie.h
+++ b/include/libcper/sections/cper-section-pcie.h
@@ -30,7 +30,7 @@
 			  "Root Complex Integrated Endpoint Device",           \
 			  "Root Complex Event Collector" }
 
-json_object *cper_section_pcie_to_ir(const void *section);
+json_object *cper_section_pcie_to_ir(const UINT8 *section, UINT32 size);
 void ir_section_pcie_to_cper(json_object *section, FILE *out);
 
 #ifdef __cplusplus
diff --git a/include/libcper/sections/cper-section.h b/include/libcper/sections/cper-section.h
index 5874edf..1945b1b 100644
--- a/include/libcper/sections/cper-section.h
+++ b/include/libcper/sections/cper-section.h
@@ -15,7 +15,7 @@
 	EFI_GUID *Guid;
 	const char *ReadableName;
 	const char *ShortName;
-	json_object *(*ToIR)(const void *);
+	json_object *(*ToIR)(const UINT8 *, UINT32);
 	void (*ToCPER)(json_object *, FILE *);
 } CPER_SECTION_DEFINITION;
 
diff --git a/sections/cper-section-ampere.c b/sections/cper-section-ampere.c
index 5002a26..34d0829 100644
--- a/sections/cper-section-ampere.c
+++ b/sections/cper-section-ampere.c
@@ -5,8 +5,12 @@
 #include <libcper/sections/cper-section-ampere.h>
 
 //Converts the given processor-generic CPER section into JSON IR.
-json_object *cper_section_ampere_to_ir(const void *section)
+json_object *cper_section_ampere_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_AMPERE_ERROR_DATA)) {
+		return NULL;
+	}
+
 	EFI_AMPERE_ERROR_DATA *record = (EFI_AMPERE_ERROR_DATA *)section;
 	json_object *section_ir = json_object_new_object();
 
diff --git a/sections/cper-section-arm.c b/sections/cper-section-arm.c
index 31fa9b0..6aa0b87 100644
--- a/sections/cper-section-arm.c
+++ b/sections/cper-section-arm.c
@@ -44,8 +44,11 @@
 void ir_arm_unknown_register_to_cper(json_object *registers, FILE *out);
 
 //Converts the given processor-generic CPER section into JSON IR.
-json_object *cper_section_arm_to_ir(const void *section)
+json_object *cper_section_arm_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_ARM_ERROR_RECORD)) {
+		return NULL;
+	}
 	EFI_ARM_ERROR_RECORD *record = (EFI_ARM_ERROR_RECORD *)section;
 	json_object *section_ir = json_object_new_object();
 
diff --git a/sections/cper-section-ccix-per.c b/sections/cper-section-ccix-per.c
index a4cab0c..d68f422 100644
--- a/sections/cper-section-ccix-per.c
+++ b/sections/cper-section-ccix-per.c
@@ -13,9 +13,18 @@
 #include <libcper/sections/cper-section-ccix-per.h>
 
 //Converts a single CCIX PER log CPER section into JSON IR.
-json_object *cper_section_ccix_per_to_ir(const void *section)
+json_object *cper_section_ccix_per_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_CCIX_PER_LOG_DATA)) {
+		return NULL;
+	}
+
 	EFI_CCIX_PER_LOG_DATA *ccix_error = (EFI_CCIX_PER_LOG_DATA *)section;
+
+	if (size < ccix_error->Length) {
+		return NULL;
+	}
+
 	json_object *section_ir = json_object_new_object();
 	ValidationTypes ui64Type = { UINT_64T,
 				     .value.ui64 = ccix_error->ValidBits };
@@ -39,7 +48,7 @@
 	//CCIX PER Log.
 	if (isvalid_prop_to_ir(&ui64Type, 2)) {
 		//This is formatted as described in Section 7.3.2 of CCIX Base Specification (Rev 1.0).
-		const char *cur_pos = (const char *)(ccix_error + 1);
+		const UINT8 *cur_pos = (const UINT8 *)(ccix_error + 1);
 		int remaining_length =
 			ccix_error->Length - sizeof(EFI_CCIX_PER_LOG_DATA);
 		if (remaining_length > 0) {
diff --git a/sections/cper-section-cxl-component.c b/sections/cper-section-cxl-component.c
index f1db9ad..cae152b 100644
--- a/sections/cper-section-cxl-component.c
+++ b/sections/cper-section-cxl-component.c
@@ -12,10 +12,20 @@
 #include <libcper/sections/cper-section-cxl-component.h>
 
 //Converts a single CXL component error CPER section into JSON IR.
-json_object *cper_section_cxl_component_to_ir(const void *section)
+json_object *cper_section_cxl_component_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_CXL_COMPONENT_EVENT_HEADER)) {
+		return NULL;
+	}
+
 	EFI_CXL_COMPONENT_EVENT_HEADER *cxl_error =
 		(EFI_CXL_COMPONENT_EVENT_HEADER *)section;
+	if (cxl_error->Length < sizeof(EFI_CXL_COMPONENT_EVENT_HEADER)) {
+		return NULL;
+	}
+	if (size < cxl_error->Length) {
+		return NULL;
+	}
 	json_object *section_ir = json_object_new_object();
 
 	//Length (bytes) for the entire structure.
@@ -63,20 +73,21 @@
 
 	//The specification for this is defined within the CXL Specification Section 8.2.9.1.
 	if (isvalid_prop_to_ir(&ui64Type, 2)) {
-		const char *cur_pos = (const char *)(cxl_error + 1);
+		const UINT8 *cur_pos = (const UINT8 *)(cxl_error + 1);
 		int remaining_len = cxl_error->Length -
 				    sizeof(EFI_CXL_COMPONENT_EVENT_HEADER);
 		if (remaining_len > 0) {
-			json_object *event_log = json_object_new_object();
-
 			int32_t encoded_len = 0;
 
-			char *encoded = base64_encode(
-				(UINT8 *)cur_pos, remaining_len, &encoded_len);
+			char *encoded = base64_encode(cur_pos, remaining_len,
+						      &encoded_len);
 			if (encoded == NULL) {
 				printf("Failed to allocate encode output buffer. \n");
+				json_object_put(section_ir);
 				return NULL;
 			}
+			json_object *event_log = json_object_new_object();
+
 			json_object_object_add(event_log, "data",
 					       json_object_new_string_len(
 						       encoded, encoded_len));
diff --git a/sections/cper-section-cxl-protocol.c b/sections/cper-section-cxl-protocol.c
index 4b5737b..1a9b33b 100644
--- a/sections/cper-section-cxl-protocol.c
+++ b/sections/cper-section-cxl-protocol.c
@@ -12,10 +12,21 @@
 #include <libcper/sections/cper-section-cxl-protocol.h>
 
 //Converts a single CXL protocol error CPER section into JSON IR.
-json_object *cper_section_cxl_protocol_to_ir(const void *section)
+json_object *cper_section_cxl_protocol_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_CXL_PROTOCOL_ERROR_DATA)) {
+		return NULL;
+	}
+
 	EFI_CXL_PROTOCOL_ERROR_DATA *cxl_protocol_error =
 		(EFI_CXL_PROTOCOL_ERROR_DATA *)section;
+
+	if (size < sizeof(EFI_CXL_PROTOCOL_ERROR_DATA) +
+			   cxl_protocol_error->CxlDvsecLength +
+			   cxl_protocol_error->CxlErrorLogLength) {
+		return NULL;
+	}
+
 	json_object *section_ir = json_object_new_object();
 	ValidationTypes ui64Type = {
 		UINT_64T, .value.ui64 = cxl_protocol_error->ValidBits
@@ -99,10 +110,8 @@
 			device_id, "slotNumber",
 			json_object_new_uint64(
 				cxl_protocol_error->DeviceId.SlotNumber));
-		json_object_object_add(section_ir, "deviceID", device_id);
 	}
-
-	char *encoded;
+	json_object_object_add(section_ir, "deviceID", device_id);
 
 	if (isvalid_prop_to_ir(&ui64Type, 3)) {
 		//Device serial & capability structure (if CXL 1.1 device).
@@ -115,6 +124,7 @@
 		}
 	}
 
+	char *encoded;
 	int32_t encoded_len = 0;
 
 	//The PCIe capability structure provided here could either be PCIe 1.1 Capability Structure
@@ -126,6 +136,8 @@
 			60, &encoded_len);
 		if (encoded == NULL) {
 			printf("Failed to allocate encode output buffer. \n");
+			json_object_put(section_ir);
+
 			return NULL;
 		}
 		json_object_object_add(section_ir, "capabilityStructure",
@@ -134,7 +146,7 @@
 		free(encoded);
 	}
 
-	const char *cur_pos = (const char *)(cxl_protocol_error + 1);
+	const UINT8 *cur_pos = (const UINT8 *)(cxl_protocol_error + 1);
 
 	if (isvalid_prop_to_ir(&ui64Type, 5)) {
 		//CXL DVSEC & error log length.
@@ -147,10 +159,11 @@
 		//For CXL 1.1 host downstream ports, this is the "CXL DVSEC For Flex Bus Port" structure as in CXL 1.1 spec.
 		int32_t encoded_len = 0;
 
-		encoded = base64_encode((UINT8 *)cur_pos,
+		encoded = base64_encode(cur_pos,
 					cxl_protocol_error->CxlDvsecLength,
 					&encoded_len);
 		if (encoded == NULL) {
+			json_object_put(section_ir);
 			return NULL;
 		}
 		json_object_object_add(section_ir, "cxlDVSEC",
@@ -178,6 +191,7 @@
 
 		if (encoded == NULL) {
 			printf("Failed to allocate encode output buffer. \n");
+			json_object_put(section_ir);
 			return NULL;
 		}
 		json_object_object_add(section_ir, "cxlErrorLog",
diff --git a/sections/cper-section-dmar-generic.c b/sections/cper-section-dmar-generic.c
index 7468d30..e745d2b 100644
--- a/sections/cper-section-dmar-generic.c
+++ b/sections/cper-section-dmar-generic.c
@@ -11,8 +11,12 @@
 #include <libcper/sections/cper-section-dmar-generic.h>
 
 //Converts a single generic DMAr CPER section into JSON IR.
-json_object *cper_section_dmar_generic_to_ir(const void *section)
+json_object *cper_section_dmar_generic_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_DMAR_GENERIC_ERROR_DATA)) {
+		return NULL;
+	}
+
 	EFI_DMAR_GENERIC_ERROR_DATA *firmware_error =
 		(EFI_DMAR_GENERIC_ERROR_DATA *)section;
 	json_object *section_ir = json_object_new_object();
diff --git a/sections/cper-section-dmar-iommu.c b/sections/cper-section-dmar-iommu.c
index 99af77c..c411cf2 100644
--- a/sections/cper-section-dmar-iommu.c
+++ b/sections/cper-section-dmar-iommu.c
@@ -13,8 +13,12 @@
 #include <libcper/sections/cper-section-dmar-iommu.h>
 
 //Converts a single IOMMU specific DMAr CPER section into JSON IR.
-json_object *cper_section_dmar_iommu_to_ir(const void *section)
+json_object *cper_section_dmar_iommu_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_IOMMU_DMAR_ERROR_DATA)) {
+		return NULL;
+	}
+
 	EFI_IOMMU_DMAR_ERROR_DATA *iommu_error =
 		(EFI_IOMMU_DMAR_ERROR_DATA *)section;
 	json_object *section_ir = json_object_new_object();
diff --git a/sections/cper-section-dmar-vtd.c b/sections/cper-section-dmar-vtd.c
index 16985a9..ad86293 100644
--- a/sections/cper-section-dmar-vtd.c
+++ b/sections/cper-section-dmar-vtd.c
@@ -13,8 +13,12 @@
 #include <libcper/sections/cper-section-dmar-vtd.h>
 
 //Converts a single VT-d specific DMAr CPER section into JSON IR.
-json_object *cper_section_dmar_vtd_to_ir(const void *section)
+json_object *cper_section_dmar_vtd_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_DIRECTED_IO_DMAR_ERROR_DATA)) {
+		return NULL;
+	}
+
 	EFI_DIRECTED_IO_DMAR_ERROR_DATA *vtd_error =
 		(EFI_DIRECTED_IO_DMAR_ERROR_DATA *)section;
 	json_object *section_ir = json_object_new_object();
diff --git a/sections/cper-section-firmware.c b/sections/cper-section-firmware.c
index ebdc11f..78f04d0 100644
--- a/sections/cper-section-firmware.c
+++ b/sections/cper-section-firmware.c
@@ -11,8 +11,12 @@
 #include <libcper/sections/cper-section-firmware.h>
 
 //Converts a single firmware CPER section into JSON IR.
-json_object *cper_section_firmware_to_ir(const void *section)
+json_object *cper_section_firmware_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_FIRMWARE_ERROR_DATA)) {
+		return NULL;
+	}
+
 	EFI_FIRMWARE_ERROR_DATA *firmware_error =
 		(EFI_FIRMWARE_ERROR_DATA *)section;
 	json_object *section_ir = json_object_new_object();
diff --git a/sections/cper-section-generic.c b/sections/cper-section-generic.c
index 7bbf56e..ec70b85 100644
--- a/sections/cper-section-generic.c
+++ b/sections/cper-section-generic.c
@@ -13,8 +13,12 @@
 #include <libcper/sections/cper-section-generic.h>
 
 //Converts the given processor-generic CPER section into JSON IR.
-json_object *cper_section_generic_to_ir(const void *section)
+json_object *cper_section_generic_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_PROCESSOR_GENERIC_ERROR_DATA)) {
+		return NULL;
+	}
+
 	EFI_PROCESSOR_GENERIC_ERROR_DATA *section_generic =
 		(EFI_PROCESSOR_GENERIC_ERROR_DATA *)section;
 	json_object *section_ir = json_object_new_object();
diff --git a/sections/cper-section-ia32x64.c b/sections/cper-section-ia32x64.c
index f217612..bf7f565 100644
--- a/sections/cper-section-ia32x64.c
+++ b/sections/cper-section-ia32x64.c
@@ -21,7 +21,8 @@
 cper_ia32x64_bus_check_to_ir(EFI_IA32_X64_BUS_CHECK_INFO *bus_check);
 json_object *cper_ia32x64_ms_check_to_ir(EFI_IA32_X64_MS_CHECK_INFO *ms_check);
 json_object *cper_ia32x64_processor_context_info_to_ir(
-	EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos);
+	EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos,
+	UINT32 *remaining_size);
 json_object *
 cper_ia32x64_register_32bit_to_ir(EFI_CONTEXT_IA32_REGISTER_STATE *registers);
 json_object *
@@ -43,10 +44,15 @@
 //////////////////
 
 //Converts the IA32/x64 error section described in the given descriptor into intermediate format.
-json_object *cper_section_ia32x64_to_ir(const void *section)
+json_object *cper_section_ia32x64_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD)) {
+		return NULL;
+	}
 	EFI_IA32_X64_PROCESSOR_ERROR_RECORD *record =
 		(EFI_IA32_X64_PROCESSOR_ERROR_RECORD *)section;
+	UINT32 remaining_size =
+		size - sizeof(EFI_IA32_X64_PROCESSOR_ERROR_RECORD);
 	json_object *record_ir = json_object_new_object();
 
 	//Validation bits.
@@ -89,16 +95,34 @@
 	EFI_IA32_X64_PROCESS_ERROR_INFO *current_error_info =
 		(EFI_IA32_X64_PROCESS_ERROR_INFO *)(record + 1);
 	json_object *error_info_array = json_object_new_array();
+	if (remaining_size < (processor_error_info_num *
+			      sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO))) {
+		json_object_put(error_info_array);
+		json_object_put(record_ir);
+		printf("Invalid CPER file: Invalid processor error info num.\n");
+		return NULL;
+	}
+
 	for (int i = 0; i < processor_error_info_num; i++) {
 		json_object_array_add(error_info_array,
 				      cper_ia32x64_processor_error_info_to_ir(
 					      current_error_info));
 		current_error_info++;
 	}
+	remaining_size -= processor_error_info_num *
+			  sizeof(EFI_IA32_X64_PROCESS_ERROR_INFO);
+
 	json_object_object_add(record_ir, "processorErrorInfo",
 			       error_info_array);
 
 	//Processor context information, of the amount described above.
+	if (remaining_size < (processor_context_info_num *
+			      sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO))) {
+		json_object_put(error_info_array);
+		json_object_put(record_ir);
+		printf("Invalid CPER file: Invalid processor context info num.\n");
+		return NULL;
+	}
 	EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *current_context_info =
 		(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)current_error_info;
 	void *cur_pos = (void *)current_context_info;
@@ -106,11 +130,14 @@
 	for (int i = 0; i < processor_context_info_num; i++) {
 		json_object_array_add(context_info_array,
 				      cper_ia32x64_processor_context_info_to_ir(
-					      current_context_info, &cur_pos));
+					      current_context_info, &cur_pos,
+					      &remaining_size));
 		current_context_info =
 			(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *)cur_pos;
+
 		//The context array is a non-fixed size, pointer is shifted within the above function.
 	}
+
 	json_object_object_add(record_ir, "processorContextInfo",
 			       context_info_array);
 
@@ -424,13 +451,18 @@
 
 //Converts a single IA32/x64 processor context info entry into JSON IR format.
 json_object *cper_ia32x64_processor_context_info_to_ir(
-	EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos)
+	EFI_IA32_X64_PROCESSOR_CONTEXT_INFO *context_info, void **cur_pos,
+	UINT32 *remaining_size)
 {
+	if (*remaining_size < sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO)) {
+		return NULL;
+	}
+	*remaining_size -= sizeof(EFI_IA32_X64_PROCESSOR_CONTEXT_INFO);
 	json_object *context_info_ir = json_object_new_object();
 
 	//Register context type.
 	json_object *context_type = integer_to_readable_pair(
-		context_info->RegisterType, 8,
+		context_info->RegisterType, IA32X64_REGISTER_CONTEXT_TYPES_SIZE,
 		IA32X64_REGISTER_CONTEXT_TYPES_KEYS,
 		IA32X64_REGISTER_CONTEXT_TYPES_VALUES, "Unknown (Reserved)");
 	json_object_object_add(context_info_ir, "registerContextType",
@@ -449,21 +481,34 @@
 	//Register array.
 	json_object *register_array = NULL;
 	if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_IA32) {
+		if (*remaining_size < sizeof(EFI_CONTEXT_IA32_REGISTER_STATE)) {
+			json_object_put(context_info_ir);
+			return NULL;
+		}
 		EFI_CONTEXT_IA32_REGISTER_STATE *register_state =
 			(EFI_CONTEXT_IA32_REGISTER_STATE *)(context_info + 1);
 		register_array =
 			cper_ia32x64_register_32bit_to_ir(register_state);
 		*cur_pos = (void *)(register_state + 1);
+		*remaining_size -= sizeof(EFI_CONTEXT_IA32_REGISTER_STATE);
 	} else if (context_info->RegisterType == EFI_REG_CONTEXT_TYPE_X64) {
+		if (*remaining_size < sizeof(EFI_CONTEXT_X64_REGISTER_STATE)) {
+			json_object_put(context_info_ir);
+			return NULL;
+		}
 		EFI_CONTEXT_X64_REGISTER_STATE *register_state =
 			(EFI_CONTEXT_X64_REGISTER_STATE *)(context_info + 1);
 		register_array =
 			cper_ia32x64_register_64bit_to_ir(register_state);
 		*cur_pos = (void *)(register_state + 1);
+		*remaining_size -= sizeof(EFI_CONTEXT_X64_REGISTER_STATE);
 	} else {
 		//No parseable data, just dump as base64 and shift the head to the next item.
 		*cur_pos = (void *)(context_info + 1);
-
+		if (*remaining_size < context_info->ArraySize) {
+			json_object_put(context_info_ir);
+			return NULL;
+		}
 		int32_t encoded_len = 0;
 		char *encoded = base64_encode((UINT8 *)*cur_pos,
 					      context_info->ArraySize,
@@ -480,6 +525,7 @@
 
 		*cur_pos =
 			(void *)(((char *)*cur_pos) + context_info->ArraySize);
+		*remaining_size -= context_info->ArraySize;
 	}
 	json_object_object_add(context_info_ir, "registerArray",
 			       register_array);
diff --git a/sections/cper-section-ipf.c b/sections/cper-section-ipf.c
index a50cfab..2cf6f13 100644
--- a/sections/cper-section-ipf.c
+++ b/sections/cper-section-ipf.c
@@ -15,8 +15,12 @@
 json_object *cper_ipf_mod_error_to_ir(EFI_IPF_MOD_ERROR_INFO *mod_error);
 
 //Converts a single Intel IPF error CPER section into JSON IR.
-json_object *cper_section_ipf_to_ir(const void *section)
+json_object *cper_section_ipf_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_IPF_ERROR_INFO_HEADER)) {
+		return NULL;
+	}
+
 	EFI_IPF_ERROR_INFO_HEADER *ipf_error =
 		(EFI_IPF_ERROR_INFO_HEADER *)section;
 	json_object *section_ir = json_object_new_object();
diff --git a/sections/cper-section-memory.c b/sections/cper-section-memory.c
index c5a2094..b58bf82 100644
--- a/sections/cper-section-memory.c
+++ b/sections/cper-section-memory.c
@@ -11,8 +11,13 @@
 #include <libcper/sections/cper-section-memory.h>
 
 //Converts a single memory error CPER section into JSON IR.
-json_object *cper_section_platform_memory_to_ir(const void *section)
+json_object *cper_section_platform_memory_to_ir(const UINT8 *section,
+						UINT32 size)
 {
+	if (size < sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA)) {
+		return NULL;
+	}
+
 	EFI_PLATFORM_MEMORY_ERROR_DATA *memory_error =
 		(EFI_PLATFORM_MEMORY_ERROR_DATA *)section;
 	json_object *section_ir = json_object_new_object();
@@ -166,8 +171,13 @@
 }
 
 //Converts a single memory error 2 CPER section into JSON IR.
-json_object *cper_section_platform_memory2_to_ir(const void *section)
+json_object *cper_section_platform_memory2_to_ir(const UINT8 *section,
+						 UINT32 size)
 {
+	if (size < sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA)) {
+		return NULL;
+	}
+
 	EFI_PLATFORM_MEMORY2_ERROR_DATA *memory_error =
 		(EFI_PLATFORM_MEMORY2_ERROR_DATA *)section;
 	json_object *section_ir = json_object_new_object();
diff --git a/sections/cper-section-nvidia.c b/sections/cper-section-nvidia.c
index 8b211ea..83c6083 100644
--- a/sections/cper-section-nvidia.c
+++ b/sections/cper-section-nvidia.c
@@ -12,9 +12,19 @@
 #include <libcper/sections/cper-section-nvidia.h>
 
 //Converts a single NVIDIA CPER section into JSON IR.
-json_object *cper_section_nvidia_to_ir(const void *section)
+json_object *cper_section_nvidia_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_NVIDIA_ERROR_DATA)) {
+		return NULL;
+	}
+
 	EFI_NVIDIA_ERROR_DATA *nvidia_error = (EFI_NVIDIA_ERROR_DATA *)section;
+	if (size < sizeof(EFI_NVIDIA_ERROR_DATA) +
+			   nvidia_error->NumberRegs *
+				   sizeof(EFI_NVIDIA_REGISTER_DATA)) {
+		return NULL;
+	}
+
 	json_object *section_ir = json_object_new_object();
 
 	json_object_object_add(section_ir, "signature",
diff --git a/sections/cper-section-pci-bus.c b/sections/cper-section-pci-bus.c
index 5564c21..70b5a2c 100644
--- a/sections/cper-section-pci-bus.c
+++ b/sections/cper-section-pci-bus.c
@@ -12,8 +12,12 @@
 #include <libcper/sections/cper-section-pci-bus.h>
 
 //Converts a single PCI/PCI-X bus CPER section into JSON IR.
-json_object *cper_section_pci_bus_to_ir(const void *section)
+json_object *cper_section_pci_bus_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_PCI_PCIX_BUS_ERROR_DATA)) {
+		return NULL;
+	}
+
 	EFI_PCI_PCIX_BUS_ERROR_DATA *bus_error =
 		(EFI_PCI_PCIX_BUS_ERROR_DATA *)section;
 	json_object *section_ir = json_object_new_object();
diff --git a/sections/cper-section-pci-dev.c b/sections/cper-section-pci-dev.c
index adc54a0..9f89494 100644
--- a/sections/cper-section-pci-dev.c
+++ b/sections/cper-section-pci-dev.c
@@ -11,10 +11,21 @@
 #include <libcper/sections/cper-section-pci-dev.h>
 
 //Converts a single PCI/PCI-X device CPER section into JSON IR.
-json_object *cper_section_pci_dev_to_ir(const void *section)
+json_object *cper_section_pci_dev_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA)) {
+		return NULL;
+	}
+
 	EFI_PCI_PCIX_DEVICE_ERROR_DATA *dev_error =
 		(EFI_PCI_PCIX_DEVICE_ERROR_DATA *)section;
+
+	if (size < sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA) +
+			   ((dev_error->MemoryNumber + dev_error->IoNumber) *
+			    sizeof(EFI_PCI_PCIX_DEVICE_ERROR_DATA_REGISTER))) {
+		return NULL;
+	}
+
 	json_object *section_ir = json_object_new_object();
 
 	//Validation bits.
diff --git a/sections/cper-section-pcie.c b/sections/cper-section-pcie.c
index 5e83f9d..93d6331 100644
--- a/sections/cper-section-pcie.c
+++ b/sections/cper-section-pcie.c
@@ -24,8 +24,12 @@
 };
 
 //Converts a single PCIe CPER section into JSON IR.
-json_object *cper_section_pcie_to_ir(const void *section)
+json_object *cper_section_pcie_to_ir(const UINT8 *section, UINT32 size)
 {
+	if (size < sizeof(EFI_PCIE_ERROR_DATA)) {
+		return NULL;
+	}
+
 	EFI_PCIE_ERROR_DATA *pcie_error = (EFI_PCIE_ERROR_DATA *)section;
 	json_object *section_ir = json_object_new_object();