Move from memset to memset_s.

This adds the extra bounds checks and panics if there is a violation.

Change-Id: I9db3ca44be4f9c39964d912b57fe7b68e2792bc1
diff --git a/inc/hf/arch/std.h b/inc/hf/arch/std.h
index 173571d..3f69ccc 100644
--- a/inc/hf/arch/std.h
+++ b/inc/hf/arch/std.h
@@ -21,7 +21,6 @@
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
-void *memset(void *s, int c, size_t n);
 void *memcpy(void *dst, const void *src, size_t n);
 void *memmove(void *dst, const void *src, size_t n);
 int memcmp(const void *a, const void *b, size_t n);
diff --git a/inc/hf/std.h b/inc/hf/std.h
index bb71a9d..73c7d1c 100644
--- a/inc/hf/std.h
+++ b/inc/hf/std.h
@@ -17,3 +17,16 @@
 #pragma once
 
 #include "hf/arch/std.h"
+
+typedef size_t rsize_t;
+
+#define RSIZE_MAX SIZE_MAX
+
+/*
+ * Only the safer versions of these functions are exposed to reduce the chance
+ * of misusing the versions without bounds checking or null pointer checks.
+ *
+ * These functions don't return errno_t as per the specification and implicity
+ * have a constraint handler that panics.
+ */
+void memset_s(void *dest, rsize_t destsz, int ch, rsize_t count);
diff --git a/src/BUILD.gn b/src/BUILD.gn
index 8ec1f92..8e1b7e2 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -70,6 +70,10 @@
 
 # Standard library functions.
 source_set("std") {
+  sources = [
+    "std.c",
+  ]
+
   deps = [
     "//src/arch/${plat_arch}:std",
   ]
diff --git a/src/api.c b/src/api.c
index cd46073..ec98c22 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1185,7 +1185,7 @@
 		return false;
 	}
 
-	memset(ptr, 0, size);
+	memset_s(ptr, size, 0, size);
 	arch_mm_write_back_dcache(ptr, size);
 	mm_unmap(begin, end, ppool);
 
diff --git a/src/arch/aarch64/cpu.c b/src/arch/aarch64/cpu.c
index b1280a6..a1a2c87 100644
--- a/src/arch/aarch64/cpu.c
+++ b/src/arch/aarch64/cpu.c
@@ -42,7 +42,7 @@
 	uintreg_t cptr;
 	uintreg_t cnthctl;
 
-	memset(r, 0, sizeof(*r));
+	memset_s(r, sizeof(*r), 0, sizeof(*r));
 
 	r->pc = pc;
 	r->r[0] = arg;
diff --git a/src/cpu.c b/src/cpu.c
index b2213d1..ca26122 100644
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -159,7 +159,7 @@
 
 void vcpu_init(struct vcpu *vcpu, struct vm *vm)
 {
-	memset(vcpu, 0, sizeof(*vcpu));
+	memset_s(vcpu, sizeof(*vcpu), 0, sizeof(*vcpu));
 	sl_init(&vcpu->lock);
 	vcpu->regs_available = true;
 	vcpu->vm = vm;
diff --git a/src/fdt.c b/src/fdt.c
index b781a72..f02864a 100644
--- a/src/fdt.c
+++ b/src/fdt.c
@@ -136,7 +136,7 @@
 	uint32_t begin = be32toh(hdr->off_dt_struct);
 	uint32_t size = be32toh(hdr->size_dt_struct);
 
-	memset(node, 0, sizeof(*node));
+	memset_s(node, sizeof(*node), 0, sizeof(*node));
 
 	/* Check the magic number before anything else. */
 	if (hdr->magic != be32toh(FDT_MAGIC)) {
diff --git a/src/std.c b/src/std.c
new file mode 100644
index 0000000..00d4704
--- /dev/null
+++ b/src/std.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019 The Hafnium Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hf/std.h"
+
+#include "hf/panic.h"
+
+/* Declare unsafe functions locally so they are not available globally. */
+void *memset(void *s, int c, size_t n);
+
+void memset_s(void *dest, rsize_t destsz, int ch, rsize_t count)
+{
+	if (dest == NULL) {
+		goto fail;
+	}
+
+	if (destsz > RSIZE_MAX || count > RSIZE_MAX) {
+		goto fail;
+	}
+
+	if (count > destsz) {
+		goto fail;
+	}
+
+	memset(dest, ch, count);
+	return;
+
+fail:
+	panic("memset_s failure");
+}
diff --git a/src/vm.c b/src/vm.c
index a58886e..d1fb5bb 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -36,7 +36,7 @@
 
 	vm = &vms[vm_count];
 
-	memset(vm, 0, sizeof(*vm));
+	memset_s(vm, sizeof(*vm), 0, sizeof(*vm));
 
 	list_init(&vm->mailbox.waiter_list);
 	list_init(&vm->mailbox.ready_list);
diff --git a/test/hftest/hftest_common.c b/test/hftest/hftest_common.c
index e1b4602..4a3f0df 100644
--- a/test/hftest/hftest_common.c
+++ b/test/hftest/hftest_common.c
@@ -106,8 +106,7 @@
 			}
 			/*
 			 * It's easier to put the comma at the start of the line
-			 * than the end even
-			 * though the JSON looks a bit funky.
+			 * than the end even though the JSON looks a bit funky.
 			 */
 			HFTEST_LOG("       %c\"%s\"",
 				   tests_in_suite ? ',' : ' ', test->name);
@@ -136,7 +135,7 @@
 {
 	/* Prepare the context. */
 	struct hftest_context *ctx = hftest_get_context();
-	memset(ctx, 0, sizeof(*ctx));
+	memset_s(ctx, sizeof(*ctx), 0, sizeof(*ctx));
 	ctx->abort = abort;
 
 	/* Run any set up functions. */
diff --git a/test/hftest/hftest_service.c b/test/hftest/hftest_service.c
index b110cb5..c728e27 100644
--- a/test/hftest/hftest_service.c
+++ b/test/hftest/hftest_service.c
@@ -107,7 +107,7 @@
 
 	/* Clean the context. */
 	ctx = hftest_get_context();
-	memset(ctx, 0, sizeof(*ctx));
+	memset_s(ctx, sizeof(*ctx), 0, sizeof(*ctx));
 	ctx->abort = abort;
 	ctx->send = (struct spci_message *)send;
 	ctx->recv = (struct spci_message *)recv;
diff --git a/test/vmapi/primary_with_secondaries/memory_sharing.c b/test/vmapi/primary_with_secondaries/memory_sharing.c
index c74d6f3..fc03a32 100644
--- a/test/vmapi/primary_with_secondaries/memory_sharing.c
+++ b/test/vmapi/primary_with_secondaries/memory_sharing.c
@@ -93,7 +93,7 @@
 
 	SERVICE_SELECT(SERVICE_VM0, "memory_increment", mb.send);
 
-	memset(ptr, 'a', PAGE_SIZE);
+	memset_s(ptr, sizeof(page), 'a', PAGE_SIZE);
 	ASSERT_EQ(hf_share_memory(SERVICE_VM0, (hf_ipaddr_t)&page, PAGE_SIZE,
 				  HF_MEMORY_SHARE),
 		  0);
@@ -136,7 +136,7 @@
 	SERVICE_SELECT(SERVICE_VM0, "memory_return", mb.send);
 
 	/* Dirty the memory before sharing it. */
-	memset(ptr, 'b', PAGE_SIZE);
+	memset_s(ptr, sizeof(page), 'b', PAGE_SIZE);
 	ASSERT_EQ(hf_share_memory(SERVICE_VM0, (hf_ipaddr_t)&page, PAGE_SIZE,
 				  HF_MEMORY_SHARE),
 		  0);
@@ -174,7 +174,7 @@
 	SERVICE_SELECT(SERVICE_VM0, "memory_return", mb.send);
 
 	/* Dirty the memory before giving it. */
-	memset(ptr, 'b', PAGE_SIZE);
+	memset_s(ptr, sizeof(page), 'b', PAGE_SIZE);
 	ASSERT_EQ(hf_share_memory(SERVICE_VM0, (hf_ipaddr_t)&page, PAGE_SIZE,
 				  HF_MEMORY_GIVE),
 		  0);
@@ -212,7 +212,7 @@
 	SERVICE_SELECT(SERVICE_VM0, "memory_return", mb.send);
 
 	/* Dirty the memory before lending it. */
-	memset(ptr, 'c', PAGE_SIZE);
+	memset_s(ptr, sizeof(page), 'c', PAGE_SIZE);
 	ASSERT_EQ(hf_share_memory(SERVICE_VM0, (hf_ipaddr_t)&page, PAGE_SIZE,
 				  HF_MEMORY_LEND),
 		  0);