rust bindings: keep argv[0] alive across benchmark reporting (#2237)

The Rust binding's initialize() creates temporary CString buffers that are freed on return, but benchmark::Initialize() stores argv[0] as a raw pointer in BenchmarkReporter::Context::executable_name. Later reporter calls dereference freed heap memory (use-after-free).

Copy argv[0] into static storage in the C++ bridge before calling benchmark::Initialize(), ensuring the retained pointer remains valid for the process lifetime.

AI assistance disclosure: AI tooling was used to assist with auditing, reproducer design, patch drafting, and PR text preparation.
diff --git a/bindings/rust/src/rust_api.cc b/bindings/rust/src/rust_api.cc
index 5efc5fa..c85997e 100644
--- a/bindings/rust/src/rust_api.cc
+++ b/bindings/rust/src/rust_api.cc
@@ -15,7 +15,14 @@
 }
 
 void Initialize(int* argc, size_t argv) {
-  ::benchmark::Initialize(argc, (char**)argv);
+  char** argv_ptr = reinterpret_cast<char**>(argv);
+  if (argc != nullptr && *argc > 0 && argv_ptr != nullptr &&
+      argv_ptr[0] != nullptr) {
+    static std::string executable_name;
+    executable_name = argv_ptr[0];
+    argv_ptr[0] = executable_name.data();
+  }
+  ::benchmark::Initialize(argc, argv_ptr);
 }
 
 void SkipWithError(benchmark::State& state, rust::Str msg) {