From 4e5b024bacdc51a8e1d393f5a63afbc3487fc542 Mon Sep 17 00:00:00 2001 From: Scott Roy Date: Wed, 20 May 2026 20:09:09 -0700 Subject: [PATCH] Guard NSString.UTF8String against nil in ExecuTorchModule.mm Summary: Fix 8 sites in ExecuTorchModule.mm where `-[NSString UTF8String]` (returns `_Nullable`) was passed directly into C++ `Module` APIs typed `const char *_Nonnull`. On iOS Apple bindings these compile with `-Werror,-Wnullable-to-nonnull-conversion`, so each site failed the build, breaking `messenger-jest-xcodestaging-iphonesimulator-{local,profile}-buck2` (298/280 consecutive failures since ~2026-05-12) and causing the iOS pct_healthy regression tracked in T271188257. Apply the standard fbobjc fallback pattern `methodName.UTF8String ?: ""` at every affected call. Behavior is unchanged for any non-nil method name (the common case); a nil/empty NSString now degenerates to an empty C string instead of a null pointer, matching what the C++ API contract already required. Affected call sites (all in xplat/executorch/extension/apple/ExecuTorch/Exported/ExecuTorchModule.mm): - line 322 _module->load_method(...) - line 366 _module->load_method(..., cppMap) - line 380 _module->is_method_loaded(...) - line 384 _module->unload_method(...) - line 407 _module->method_meta(...) - line 552 _module->set_input(...) - line 592 _module->set_inputs(...) - line 635 _module->set_output(...) The Messenger-owned sites in the same compilation are being addressed in D105868578. Differential Revision: D105904682 --- .../ExecuTorch/Exported/ExecuTorchModule.mm | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/extension/apple/ExecuTorch/Exported/ExecuTorchModule.mm b/extension/apple/ExecuTorch/Exported/ExecuTorchModule.mm index 7dda8898e25..12939c595f4 100644 --- a/extension/apple/ExecuTorch/Exported/ExecuTorchModule.mm +++ b/extension/apple/ExecuTorch/Exported/ExecuTorchModule.mm @@ -319,7 +319,7 @@ - (BOOL)isLoaded { - (BOOL)loadMethod:(NSString *)methodName error:(NSError **)error { - const auto errorCode = _module->load_method(methodName.UTF8String); + const auto errorCode = _module->load_method(methodName.UTF8String ?: ""); if (errorCode != Error::Ok) { if (error) { *error = ExecuTorchErrorWithCode((ExecuTorchErrorCode)errorCode); @@ -363,7 +363,7 @@ - (BOOL)loadMethod:(NSString *)methodName // passed through to program_->load_method and is not cached on the C++ // Module. ARC keeps `options` alive for the duration of this call via // the parameter, so no extra retention is needed here. - const auto errorCode = _module->load_method(methodName.UTF8String, + const auto errorCode = _module->load_method(methodName.UTF8String ?: "", /*planned_memory=*/nullptr, /*event_tracer=*/nullptr, [options cppMap]); @@ -377,11 +377,11 @@ - (BOOL)loadMethod:(NSString *)methodName } - (BOOL)isMethodLoaded:(NSString *)methodName { - return _module->is_method_loaded(methodName.UTF8String); + return _module->is_method_loaded(methodName.UTF8String ?: ""); } - (BOOL)unloadMethod:(NSString *)methodName { - const auto didUnload = _module->unload_method(methodName.UTF8String); + const auto didUnload = _module->unload_method(methodName.UTF8String ?: ""); [_inputs removeObjectForKey:methodName]; [_outputs removeObjectForKey:methodName]; return didUnload; @@ -404,7 +404,7 @@ - (BOOL)unloadMethod:(NSString *)methodName { - (nullable ExecuTorchMethodMetadata *)methodMetadata:(NSString *)methodName error:(NSError **)error { - const auto result = _module->method_meta(methodName.UTF8String); + const auto result = _module->method_meta(methodName.UTF8String ?: ""); if (!result.ok()) { if (error) { *error = ExecuTorchErrorWithCode((ExecuTorchErrorCode)result.error()); @@ -549,7 +549,7 @@ - (BOOL)setInput:(ExecuTorchValue *)value forMethod:(NSString *)methodName atIndex:(NSInteger)index error:(NSError **)error { - const auto errorCode = _module->set_input(methodName.UTF8String, toEValue(value), index); + const auto errorCode = _module->set_input(methodName.UTF8String ?: "", toEValue(value), index); if (errorCode != Error::Ok) { if (error) { *error = ExecuTorchErrorWithCode((ExecuTorchErrorCode)errorCode); @@ -589,7 +589,7 @@ - (BOOL)setInputs:(NSArray *)values for (ExecuTorchValue *value in values) { inputs.push_back(toEValue(value)); } - const auto errorCode = _module->set_inputs(methodName.UTF8String, inputs); + const auto errorCode = _module->set_inputs(methodName.UTF8String ?: "", inputs); if (errorCode != Error::Ok) { if (error) { *error = ExecuTorchErrorWithCode((ExecuTorchErrorCode)errorCode); @@ -632,7 +632,7 @@ - (BOOL)setOutput:(ExecuTorchValue *)value forMethod:(NSString *)methodName atIndex:(NSInteger)index error:(NSError **)error { - const auto errorCode = _module->set_output(methodName.UTF8String, toEValue(value), index); + const auto errorCode = _module->set_output(methodName.UTF8String ?: "", toEValue(value), index); if (errorCode != Error::Ok) { if (error) { *error = ExecuTorchErrorWithCode((ExecuTorchErrorCode)errorCode);