Fix parsing single section CPER error

Single section CPER logs do not contain a Record Header. The check for
a valid header is now performed only if the content includes a Record
Header. Additionally, this update fixes an issue with the size
calculation for single-section logs.

Tested :
  $> ./cper-generate --out single-cper.file --single-section firmware
  $> ./cper-convert to-json-section single-cper.file

Change-Id: Id7efec20df3e5b53c6f90330e0770c1f682a8d87
Signed-off-by: John Chung <john.chung@arm.com>
diff --git a/cli-app/cper-convert.c b/cli-app/cper-convert.c
index 84ce618..e011ad3 100644
--- a/cli-app/cper-convert.c
+++ b/cli-app/cper-convert.c
@@ -108,7 +108,7 @@
 		return;
 	}
 
-	if (!header_valid(fbuff, readsize)) {
+	if (!is_single_section && !header_valid(fbuff, readsize)) {
 		// Check if it's base64 encoded
 		int32_t decoded_len = 0;
 		UINT8 *decoded = base64_decode(fbuff, readsize, &decoded_len);
diff --git a/cper-parse.c b/cper-parse.c
index 27cfd72..b91a54e 100644
--- a/cper-parse.c
+++ b/cper-parse.c
@@ -414,6 +414,7 @@
 	json_object *section_ir =
 		definition->ToIR(cper_section_buf, size, &cper_description);
 	if (section_ir == NULL) {
+		free(cper_description);
 		return NULL;
 	}
 	json_object *result = json_object_new_object();
@@ -527,7 +528,7 @@
 	json_object_object_add(ir, "sectionDescriptor", section_descriptor_ir);
 	section_begin = cper_buf + section_descriptor->SectionOffset;
 
-	if (section_begin + section_descriptor->SectionLength >= cper_end) {
+	if (section_begin + section_descriptor->SectionLength > cper_end) {
 		json_object_put(ir);
 		//cper_print_log("Invalid CPER file: Invalid section descriptor (section offset + length > size).\n");
 		return NULL;
diff --git a/tests/ir-tests.c b/tests/ir-tests.c
index f8a6990..ad4ae3b 100644
--- a/tests/ir-tests.c
+++ b/tests/ir-tests.c
@@ -311,6 +311,44 @@
 	}
 }
 
+//Tests a single randomly generated CPER section of the given type to ensure CPER-JSON IR validity.
+void cper_buf_log_section_ir_test(const char *section_name, int single_section,
+				  GEN_VALID_BITS_TEST_TYPE validBitsType)
+{
+	//Generate full CPER record for the given type.
+	char *buf;
+	size_t size;
+	FILE *record = generate_record_memstream(&section_name, 1, &buf, &size,
+						 single_section, validBitsType);
+
+	//Convert.
+	json_object *ir;
+	if (single_section) {
+		ir = cper_buf_single_section_to_ir((UINT8 *)buf, size);
+	} else {
+		ir = cper_buf_to_ir((UINT8 *)buf, size);
+	}
+	fclose(record);
+	free(buf);
+
+	if (!ir) {
+		printf("IR validation test failed (%d) : json object empty \n",
+		       single_section);
+		assert(0);
+	}
+
+	//Validate against schema.
+	int valid = schema_validate_from_file(ir, single_section,
+					      /*all_valid_bits*/ 1);
+	json_object_put(ir);
+
+	if (valid < 0) {
+		printf("IR validation test failed (single section mode = %d)\n",
+		       single_section);
+		assert(0);
+	}
+}
+
 int to_hex(const unsigned char *input, size_t size, char **out)
 {
 	*out = (char *)malloc(size * 2);
@@ -393,8 +431,14 @@
 //Tests randomly generated CPER sections for IR validity of a given type, in both single section mode and full CPER log mode.
 void cper_log_section_dual_ir_test(const char *section_name)
 {
+	// Test with file based APIs
 	cper_log_section_ir_test(section_name, 0, allValidbitsSet);
 	cper_log_section_ir_test(section_name, 1, allValidbitsSet);
+
+	// Test with buffer based APIs
+	cper_buf_log_section_ir_test(section_name, 0, allValidbitsSet);
+	cper_buf_log_section_ir_test(section_name, 1, allValidbitsSet);
+
 	//Validate against examples
 	cper_example_section_ir_test(section_name);
 }