Fix uninitialised _outputNames in ETCoreMLModelProfiler causing crash when debug_buffer_size=0#18763
Conversation
The _outputNames property was not initialised in initWithModel:configuration:error:, causing set_model_outputs() to produce an empty array when debug_buffer_size=0. This led to an NSRangeException (index 0 beyond bounds for empty array) in ETCoreMLModelManager when accessing modelOutputs[0].shape for dynamic shape resizing. When debug_buffer_size > 0, the bug was masked because the debugging path (debugModelWithInputs) overwrote the empty profiling output with valid results.
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/18763
Note: Links to docs will display an error until the docs builds have been completed. ❗ 1 Active SEVsThere are 1 currently active SEVs. If your PR is affected, please view them below: ❌ 1 Awaiting Approval, 18 Cancelled Jobs, 2 Unrelated FailuresAs of commit e30a7c1 with merge base 4afd7f9 ( CANCELLED JOBS - The following jobs were cancelled. Please retry:
BROKEN TRUNK - The following jobs failed but were present on the merge base:👉 Rebase onto the `viable/strict` branch to avoid these failures
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
|
Hi @notaJiminLee! Thank you for your pull request and welcome to our community. Action RequiredIn order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you. ProcessIn order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA. Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks! |
|
Didn't find following labels among repository labels: release notes: bug fix |
|
@pytorchbot label "release notes: apple" |
|
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks! |
|
To add the ciflow label This helps ensure we don't trigger CI on this PR until it is actually authorized to do so. Please ping one of the reviewers if you do not have access to approve and run workflows. |
|
@metascroy has imported this pull request. If you are a Meta employee, you can view this in D100369384. |
|
@claude review this PR |
|
Thank you for the fix @notaJiminLee! Let's see what CI says |
|
Claude finished @metascroy's task in 2m 4s —— View job Review of PR #18763
Verdict: This fix is correct and well-targeted. The change adds a single missing initialization on line 279 of _outputNames = model.orderedOutputNames;AnalysisThe @property (readonly, copy, nonatomic) NSOrderedSet<NSString *> *outputNames;Without this initialization, Why the fix is correct
One minor noteThe property is declared No additional changes needed. Clean, minimal fix. |
… when debug_buffer_size=0 (pytorch#18763) ### Summary `ETCoreMLModelProfiler::initWithModel:configuration:error:` does not initialise the `_outputNames` property, leaving it as `nil`. This causes an `NSRangeException` crash when `enable_etdump=True` with `debug_buffer_size=0`. **Root cause:** When `_outputNames` is `nil`, `set_model_outputs()` iterates over `nil.count` (0) and produces an empty `NSMutableArray`. This empty array is returned as `modelOutputs` from `profileModelWithInputs`. Later, `ETCoreMLModelManager` attempts to access `modelOutputs[0].shape` for dynamic shape resizing, triggering: NSRangeException: *** -[__NSArrayM objectAtIndexedSubscript:]: index 0 beyond bounds for empty array This manifests as `RuntimeError: Caught an unknown exception!` at the Python level. **Why this was not caught earlier:** When `debug_buffer_size > 0`, `kIntermediateOutputs` debug level is set, which enables both `log_profiling_info` and `log_intermediate_tensors`. In `ETCoreMLModelAnalyzer::executeModelWithInputs`, the `debugModelWithInputs` path runs after profiling and overwrites the empty array with valid outputs, masking the bug. **Fix:** Add `_outputNames = model.orderedOutputNames;` in the initialiser, consistent with how `outputNames` is used in `profilingInfoForOperationsAtPaths:` at line 319. ### Test plan Tested on macOS 15.6 (arm64) with a CoreML model (input: 1x3x640x640, 3 outputs): ```python from executorch.runtime import Runtime, Verification import torch rt = Runtime.get() prog = rt.load_program("output_coreml.pte", verification=Verification.Minimal, enable_etdump=True, debug_buffer_size=0) method = prog.load_method("forward") out = method.execute(torch.randn(1, 3, 640, 640)) # Previously crashed prog.write_etdump_result_to_file("profile.etdump", "debug.bin") ┌──────────────────────────────────┬────────────────────────┬──────────────────────────────────┐ │ Scenario │ Before │ After │ ├──────────────────────────────────┼────────────────────────┼──────────────────────────────────┤ │ debug_buffer_size=0 │ NSRangeException crash │ Success, ETDump with timing data │ ├──────────────────────────────────┼────────────────────────┼──────────────────────────────────┤ │ debug_buffer_size>0 (sufficient) │ Success (bug masked) │ Success │ ├──────────────────────────────────┼────────────────────────┼──────────────────────────────────┤ │ │ │ │ └──────────────────────────────────┴────────────────────────┴──────────────────────────────────┘ cc @kimishpatel @YifanShenSZ @cymbalrush @metascroy
Summary
ETCoreMLModelProfiler::initWithModel:configuration:error:does not initialise the_outputNamesproperty, leaving it asnil. This causes anNSRangeExceptioncrash whenenable_etdump=Truewithdebug_buffer_size=0.Root cause:
When
_outputNamesisnil,set_model_outputs()iterates overnil.count(0) and produces an emptyNSMutableArray. This empty array is returned asmodelOutputsfromprofileModelWithInputs. Later,ETCoreMLModelManagerattempts to accessmodelOutputs[0].shapefor dynamic shape resizing, triggering:NSRangeException: *** -[__NSArrayM objectAtIndexedSubscript:]: index 0 beyond bounds for empty array
This manifests as
RuntimeError: Caught an unknown exception!at the Python level.Why this was not caught earlier:
When
debug_buffer_size > 0,kIntermediateOutputsdebug level is set, which enables bothlog_profiling_infoandlog_intermediate_tensors. InETCoreMLModelAnalyzer::executeModelWithInputs, thedebugModelWithInputspath runs after profiling and overwrites the empty array with valid outputs, masking the bug.Fix:
Add
_outputNames = model.orderedOutputNames;in the initialiser, consistent with howoutputNamesis used inprofilingInfoForOperationsAtPaths:at line 319.Test plan
Tested on macOS 15.6 (arm64) with a CoreML model (input: 1x3x640x640, 3 outputs):