From 64cb613aa7492ef9d7bb45e55a03e20a74f586fc Mon Sep 17 00:00:00 2001 From: Grant Watson <2866599+grant-arm@users.noreply.github.com> Date: Thu, 11 Feb 2021 20:29:36 +0000 Subject: [PATCH] Replace type punning with memcpy. (#7415) The type punning in the existing code is undefined behaviour in C. In particular, the existing code fails when running on Arm Cortex-M devices. On Cortex-M, accessing a uint64_t that is not 8-byte aligned generates a hard fault. Change-Id: I2aecaa220e581af7c91a8bc7886499d70e2aa6f2 --- src/runtime/crt/common/ndarray.c | 14 +++++++------- src/runtime/crt/graph_runtime/graph_runtime.c | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/runtime/crt/common/ndarray.c b/src/runtime/crt/common/ndarray.c index 33dcaab0e77b..c90a4667903c 100644 --- a/src/runtime/crt/common/ndarray.c +++ b/src/runtime/crt/common/ndarray.c @@ -68,22 +68,22 @@ int TVMNDArray_Empty(int32_t ndim, const tvm_index_t* shape, DLDataType dtype, D int TVMNDArray_Load(TVMNDArray* ret, const char** strm) { int32_t status = 0; uint64_t header, reserved; - header = ((uint64_t*)*strm)[0]; // NOLINT(*) + memcpy(&header, *strm, sizeof(header)); *strm += sizeof(header); if (header != kTVMNDArrayMagic) { fprintf(stderr, "Invalid DLTensor file format\n"); status = -1; } - reserved = ((uint64_t*)*strm)[0]; // NOLINT(*) + memcpy(&reserved, *strm, sizeof(reserved)); *strm += sizeof(reserved); DLContext ctx; int ndim; // sizeof ndim should match dlpack DLDataType dtype; - ctx = ((DLContext*)*strm)[0]; // NOLINT(*) + memcpy(&ctx, *strm, sizeof(ctx)); *strm += sizeof(ctx); - ndim = ((int*)*strm)[0]; // NOLINT(*) + memcpy(&ndim, *strm, sizeof(ndim)); *strm += sizeof(ndim); - dtype = ((DLDataType*)*strm)[0]; // NOLINT(*) + memcpy(&dtype, *strm, sizeof(dtype)); *strm += sizeof(dtype); if ((ndim < 0) || (ndim > TVM_CRT_MAX_NDIM)) { fprintf(stderr, "Invalid ndim=%d: expected to be 0 ~ %d.\n", ndim, TVM_CRT_MAX_NDIM); @@ -97,7 +97,7 @@ int TVMNDArray_Load(TVMNDArray* ret, const char** strm) { int32_t idx; if (ndim != 0) { for (idx = 0; idx < ndim; idx++) { - shape[idx] = ((int64_t*)*strm)[0]; // NOLINT(*) + memcpy(&shape[idx], *strm, sizeof(int64_t)); *strm += sizeof(shape[idx]); } } @@ -111,7 +111,7 @@ int TVMNDArray_Load(TVMNDArray* ret, const char** strm) { num_elems *= ret->dl_tensor.shape[idx]; } int64_t data_byte_size; - data_byte_size = ((int64_t*)*strm)[0]; // NOLINT(*) + memcpy(&data_byte_size, *strm, sizeof(data_byte_size)); *strm += sizeof(data_byte_size); if (!(data_byte_size == num_elems * elem_bytes)) { fprintf(stderr, diff --git a/src/runtime/crt/graph_runtime/graph_runtime.c b/src/runtime/crt/graph_runtime/graph_runtime.c index 9f7b53c997f8..21b72f0e400c 100644 --- a/src/runtime/crt/graph_runtime/graph_runtime.c +++ b/src/runtime/crt/graph_runtime/graph_runtime.c @@ -777,13 +777,13 @@ int TVMGraphRuntime_LoadParams(TVMGraphRuntime* runtime, const char* param_blob, int status = 0; const char* bptr = param_blob; uint64_t header, reserved; - header = ((uint64_t*)bptr)[0]; // NOLINT(*) + memcpy(&header, bptr, sizeof(header)); bptr += sizeof(header); if (header != kTVMNDArrayListMagic) { fprintf(stderr, "Invalid parameters file format"); status = -1; } - reserved = ((uint64_t*)bptr)[0]; // NOLINT(*) + memcpy(&reserved, bptr, sizeof(reserved)); bptr += sizeof(reserved); // read names @@ -799,11 +799,11 @@ int TVMGraphRuntime_LoadParams(TVMGraphRuntime* runtime, const char* param_blob, memset(names, 0, TVM_CRT_STRLEN_NAME * runtime->nodes_count); uint64_t names_count; int idx; - names_count = ((uint64_t*)bptr)[0]; // NOLINT(*) + memcpy(&names_count, bptr, sizeof(names_count)); bptr += sizeof(names_count); for (idx = 0; idx < names_count; idx++) { uint64_t name_length; - name_length = ((uint64_t*)bptr)[0]; // NOLINT(*) + memcpy(&name_length, bptr, sizeof(name_length)); bptr += sizeof(name_length); if (name_length >= TVM_CRT_STRLEN_NAME) { fprintf(stderr, "Error: function name longer than expected.\n"); @@ -815,7 +815,7 @@ int TVMGraphRuntime_LoadParams(TVMGraphRuntime* runtime, const char* param_blob, // read sizes uint64_t sz; - sz = ((uint64_t*)bptr)[0]; // NOLINT(*) + memcpy(&sz, bptr, sizeof(sz)); bptr += sizeof(sz); uint32_t size = sz; if (size != names_count) {