Add memory size check in tarball copying methods

Change-Id: Id1190844a39daceaa114e0bfad9e4fe406b86c5e
diff --git a/sw/device/examples/hello_world_multicore/hello_world_multicore_sc_loaders_extflash.c b/sw/device/examples/hello_world_multicore/hello_world_multicore_sc_loaders_extflash.c
index fcc9184..026607f 100644
--- a/sw/device/examples/hello_world_multicore/hello_world_multicore_sc_loaders_extflash.c
+++ b/sw/device/examples/hello_world_multicore/hello_world_multicore_sc_loaders_extflash.c
@@ -6,13 +6,15 @@
 #include "sw/device/lib/testing/test_framework/check.h"
 
 void load_smc(void) {
-  CHECK_DIF_OK(
-      load_file_from_tar("smc.bin", (void*)TOP_MATCHA_RAM_SMC_BASE_ADDR));
+  CHECK_DIF_OK(load_file_from_tar(
+      "smc.bin", (void*)TOP_MATCHA_RAM_SMC_BASE_ADDR,
+      (TOP_MATCHA_RAM_SMC_BASE_ADDR + TOP_MATCHA_RAM_SMC_SIZE_BYTES)));
 }
 
 void load_kelvin(void) {
-  CHECK_DIF_OK(load_file_from_tar("kelvin.bin",
-                                  (void*)TOP_MATCHA_ML_TOP_DMEM_BASE_ADDR));
+  CHECK_DIF_OK(load_file_from_tar(
+      "kelvin.bin", (void*)TOP_MATCHA_ML_TOP_DMEM_BASE_ADDR,
+      (TOP_MATCHA_ML_TOP_DMEM_BASE_ADDR + TOP_MATCHA_RAM_ML_DMEM_SIZE_BYTES)));
 }
 
 void load_init(void) { spi_flash_init(); }
diff --git a/sw/device/lib/spi_flash.c b/sw/device/lib/spi_flash.c
index b418aee..8765118 100644
--- a/sw/device/lib/spi_flash.c
+++ b/sw/device/lib/spi_flash.c
@@ -126,18 +126,25 @@
   return kDifOk;
 }
 
-dif_result_t load_file_from_tar(const char* filename, void* addr) {
+dif_result_t load_file_from_tar(const char* filename, void* addr,
+                                size_t max_mem_addr) {
+  if (!filename) {
+    return kDifBadArg;
+  }
   size_t size = 0;
   size_t bin_offset =
       find_file_in_tar(filename, /*start_cursor=*/0, &size,
                        /*found_filename=*/NULL, /*max_filename_len=*/0);
   if (!bin_offset) return kDifError;
+  if ((size_t)addr + size > max_mem_addr) {
+    return kDifBadArg;
+  }
   return copy_flash_to_mem(bin_offset, size, addr);
 }
 
 dif_result_t load_file_prefix_from_tar(const char* file_prefix, void* addr,
-                                       size_t* tar_offset, char* filename,
-                                       size_t filename_len) {
+                                       size_t max_mem_addr, size_t* tar_offset,
+                                       char* filename, size_t filename_len) {
   if (!tar_offset || !file_prefix || !filename) {
     return kDifBadArg;
   }
@@ -146,7 +153,9 @@
   size_t bin_offset = find_file_in_tar(file_prefix, start_offset, &size,
                                        filename, filename_len);
   if (!bin_offset) return kDifOutOfRange;
-
+  if ((size_t)addr + size > max_mem_addr) {
+    return kDifBadArg;
+  }
   // Update the tar_offset for the future call.
   *tar_offset = bin_offset + ((size + 511) & ~511);
   return copy_flash_to_mem(bin_offset, size, addr);
diff --git a/sw/device/lib/spi_flash.h b/sw/device/lib/spi_flash.h
index b275836..746bc23 100644
--- a/sw/device/lib/spi_flash.h
+++ b/sw/device/lib/spi_flash.h
@@ -18,11 +18,12 @@
 dif_result_t spi_flash_read_page(uint32_t page, uint8_t* buf);
 
 /* Tar filesystem related methods */
-dif_result_t load_file_from_tar(const char* filename, void* addr);
+dif_result_t load_file_from_tar(const char* filename, void* addr,
+                                size_t max_mem_addr);
 
 dif_result_t load_file_prefix_from_tar(const char* file_prefix, void* addr,
-                                       size_t* bin_offset, char* filename,
-                                       size_t filename_len);
+                                       size_t max_mem_addr, size_t* bin_offset,
+                                       char* filename, size_t filename_len);
 
 #if defined(__cplusplus)
 }
diff --git a/sw/device/tests/kelvin/fpga_tests/kelvin_test_sc.c b/sw/device/tests/kelvin/fpga_tests/kelvin_test_sc.c
index b8fcb06..b49225a 100644
--- a/sw/device/tests/kelvin/fpga_tests/kelvin_test_sc.c
+++ b/sw/device/tests/kelvin/fpga_tests/kelvin_test_sc.c
@@ -31,8 +31,9 @@
   spi_flash_init();
 
   // Copy binary to SMC RAM.
-  CHECK_DIF_OK(
-      load_file_from_tar("smc.bin", (void*)TOP_MATCHA_RAM_SMC_BASE_ADDR));
+  CHECK_DIF_OK(load_file_from_tar(
+      "smc.bin", (void*)TOP_MATCHA_RAM_SMC_BASE_ADDR,
+      (TOP_MATCHA_RAM_SMC_BASE_ADDR + TOP_MATCHA_RAM_SMC_SIZE_BYTES)));
 
   mmio_region_t ml_dmem =
       mmio_region_from_addr(TOP_MATCHA_ML_TOP_DMEM_BASE_ADDR);
@@ -61,8 +62,11 @@
   int test_num = 0;
   int failed_test = 0;
   while ((kelvin_load_result = load_file_prefix_from_tar(
-              "kelvin_", (void*)TOP_MATCHA_ML_TOP_DMEM_BASE_ADDR, &bin_offset,
-              kelvin_bin_name, sizeof(kelvin_bin_name))) != kDifOutOfRange) {
+              "kelvin_", (void*)TOP_MATCHA_ML_TOP_DMEM_BASE_ADDR,
+              (TOP_MATCHA_ML_TOP_DMEM_BASE_ADDR +
+               TOP_MATCHA_ML_TOP_DMEM_SIZE_BYTES),
+              &bin_offset, kelvin_bin_name, sizeof(kelvin_bin_name))) !=
+         kDifOutOfRange) {
     CHECK_DIF_OK(kelvin_load_result, "Failed to load %s", kelvin_bin_name);
     test_num++;
     LOG_INFO("Test %d: Run kelvin binary %s", test_num, kelvin_bin_name);