[ulib][zxcrypt] Fix memory alignment/VLA problem in volume.cpp

volume.cpp currently uses a variable length array of type char
allocated on the stack to pass to block_impl_queue. This is not guaranteed
to be aligned to the required ABI requirements, and is also unsafe.

This patch moves the dynamic memory allocation to the heap
and ensures the allocation is at least aligned to alignof(block_op_t)

Test: Ensure that all automated tests pass on ARM64 and x86_64.
Change-Id: I5ccab789b02d9411b84bcd2b05c44d722852429d
diff --git a/system/ulib/zxcrypt/volume.cpp b/system/ulib/zxcrypt/volume.cpp
index 8bf1144..6c86ca1 100644
--- a/system/ulib/zxcrypt/volume.cpp
+++ b/system/ulib/zxcrypt/volume.cpp
@@ -24,6 +24,7 @@
 #include <fbl/string_buffer.h>
 #include <fbl/unique_fd.h>
 #include <fbl/unique_ptr.h>
+#include <memory>
 #include <fs-management/mount.h>
 #include <fs-management/ramdisk.h>
 #include <lib/fdio/debug.h>
@@ -113,9 +114,19 @@
     size_t bsz = info.block_size;
     ZX_DEBUG_ASSERT(off / bsz <= UINT32_MAX);
     ZX_DEBUG_ASSERT(len / bsz <= UINT32_MAX);
-
-    char raw[op_size];
-    block_op_t* block = reinterpret_cast<block_op_t*>(raw);
+    fbl::AllocChecker ac;
+    std::unique_ptr<char[]> raw;
+    if constexpr (alignof(block_op_t) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
+        raw = std::unique_ptr<char[]>(
+            new (static_cast<std::align_val_t>(alignof(block_op_t)), &ac) char[op_size]);
+    } else {
+        raw = std::unique_ptr<char[]>(
+            new (&ac) char[op_size]);
+    }
+    if (!ac.check()) {
+        return ZX_ERR_NO_MEMORY;
+    }
+    block_op_t* block = reinterpret_cast<block_op_t*>(raw.get());
 
     sync_completion_t completion;
     sync_completion_reset(&completion);