zephyr: Fix possible memory leak in img_mgmt_impl_write_image_data

The commit fixes memory leak that would happen in case when heap
allocation is used, for obtaining buffer for flash_img_context
and an error occurs in code that uses the obtained buffer.

Signed-off-by: Dominik Ermel <dominik.ermel@nordicsemi.no>
diff --git a/cmd/img_mgmt/port/zephyr/src/zephyr_img_mgmt.c b/cmd/img_mgmt/port/zephyr/src/zephyr_img_mgmt.c
index 0cfe637..533c006 100644
--- a/cmd/img_mgmt/port/zephyr/src/zephyr_img_mgmt.c
+++ b/cmd/img_mgmt/port/zephyr/src/zephyr_img_mgmt.c
@@ -337,59 +337,83 @@
     return 0;
 }
 
+/*
+ * The alloc_ctx and free_ctx are specifically provided for
+ * the img_mgmt_impl_write_image_data to allocate/free single flash_img_context
+ * type buffer.
+ * When heap is enabled these functions will operate on heap; when  heap is not
+ * allocated the alloc_ctx just returns pointer to static, global life-time
+ * variable, and free_ctx does nothing.
+ * CONFIG_HEAP_MEM_POOL_SIZE is C preprocessor literal.
+ */
+static inline struct flash_img_context *alloc_ctx(void)
+{
+    struct flash_img_context *ctx = NULL;
+
+    if (CONFIG_HEAP_MEM_POOL_SIZE > 0) {
+        ctx = k_malloc(sizeof(*ctx));
+    } else {
+        static struct flash_img_context stcx;
+        ctx = &stcx;
+    }
+    return ctx;
+}
+
+static inline void free_ctx(struct flash_img_context *ctx)
+{
+    if (CONFIG_HEAP_MEM_POOL_SIZE > 0) {
+        k_free(ctx);
+    }
+}
+
 int
 img_mgmt_impl_write_image_data(unsigned int offset, const void *data,
                                unsigned int num_bytes, bool last)
 {
-	int rc;
-#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
+	int rc = 0;
 	static struct flash_img_context *ctx = NULL;
-#else
-	static struct flash_img_context ctx_data;
-#define ctx (&ctx_data)
-#endif
 
-#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
-	if (offset != 0 && ctx == NULL) {
+	if (CONFIG_HEAP_MEM_POOL_SIZE > 0 && offset != 0 && ctx == NULL) {
 		return MGMT_ERR_EUNKNOWN;
 	}
-#endif
 
 	if (offset == 0) {
-#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
 		if (ctx == NULL) {
-			ctx = k_malloc(sizeof(*ctx));
+			ctx = alloc_ctx();
 
 			if (ctx == NULL) {
-				return MGMT_ERR_ENOMEM;
+				rc = MGMT_ERR_ENOMEM;
+				goto out;
 			}
 		}
-#endif
+
 		rc = flash_img_init_id(ctx, g_img_mgmt_state.area_id);
 
 		if (rc != 0) {
-			return MGMT_ERR_EUNKNOWN;
+			rc = MGMT_ERR_EUNKNOWN;
+			goto out;
 		}
 	}
 
 	if (offset != ctx->stream.bytes_written + ctx->stream.buf_bytes) {
-		return MGMT_ERR_EUNKNOWN;
+		rc = MGMT_ERR_EUNKNOWN;
+		goto out;
 	}
 
 	/* Cast away const. */
 	rc = flash_img_buffered_write(ctx, (void *)data, num_bytes, last);
 	if (rc != 0) {
-		return MGMT_ERR_EUNKNOWN;
+		rc = MGMT_ERR_EUNKNOWN;
+		goto out;
 	}
 
-#if (CONFIG_HEAP_MEM_POOL_SIZE > 0)
-	if (last) {
+out:
+	if (CONFIG_HEAP_MEM_POOL_SIZE > 0 && (last || rc != 0)) {
 		k_free(ctx);
 		ctx = NULL;
 	}
-#endif
 
-	return 0;
+	return rc;
 }
 
 int