[ORC][macOS] DylibSubstitutor::configure("") leaves @executable_path empty due to use-after-move
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
### Describe the bug
Affected revision: b5cf3c706
On macOS, `llvm::orc::DylibSubstitutor::configure` mishandles the empty `loaderPath` case in `llvm/lib/ExecutionEngine/Orc/TargetProcess/LibraryScanner.cpp`. When `loaderPath.empty()` is true, the function move-assigns `ExecPath` into `LoaderDir`, then still uses `ExecPath` to populate `@executable_path`:
https://github.com/llvm/llvm-project/blob/4dc415f94df981067e613b04642204a533792977/llvm/lib/ExecutionEngine/Orc/TargetProcess/LibraryScanner.cpp#L276-L289
Because `ExecPath` is a `SmallString`, the move leaves it empty in practice. As a result, `@executable_path/libfoo.dylib` becomes `/libfoo.dylib` instead of `/libfoo.dylib`.
### Expected behavior
With `configure("")`, both placeholders should use the main executable directory:
```text
@loader_path/librepro.dylib -> /librepro.dylib
@executable_path/librepro.dylib -> /librepro.dylib
```
### Actual behavior
`@executable_path` is empty after the move from `ExecPath`, so:
```text
@executable_path/librepro.dylib -> /librepro.dylib
```
The leading slash comes from the suffix `"/librepro.dylib"` being appended to an empty placeholder value.
### Root cause
The bug is internal to `DylibSubstitutor::configure`:
1. `ExecPath` is initialized to the main executable directory.
2. In the empty-loader case, `LoaderDir = std::move(ExecPath)` moves from it.
3. `ExecPath` is then used again to populate `@executable_path`.
4. `SmallString` move assignment leaves the source empty in practice.
https://github.com/llvm/llvm-project/blob/4dc415f94df981067e613b04642204a533792977/llvm/include/llvm/ADT/SmallVector.h#L1105-L1106
Contributor guide
Assessment
This issue has not been assessed yet.