php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #79220 Allow setting FFI_LIB search path at runtime
Submitted: 2020-02-04 11:47 UTC Modified: -
From: ojrask at gmail dot com Assigned:
Status: Open Package: Dynamic loading
PHP Version: 7.4.2 OS: -
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2020-02-04 11:47 UTC] ojrask at gmail dot com
Description:
------------
Currently, when using the new FFI core extension, and loading dynamic libraries using the `FFI_LIB` header definition, the path is passed as is to `dlopen(3)`.

What this means is:

1. Absolute paths work as expected
2. Relative paths work from the current working directory (not changeable with PHP's `chdir`)
3. `LD_LIBRARY_PATH` works, but only if the PHP interpreter itself if invoked after adjusting the env var
4. `/lib` and `/usr/lib` work as expected.

The problem this poses is as follows:

Assume I want to create a new distributable PHP package, using Composer for instance. I want to bundle an FFI compatible dynamic library into the package itself.

Now, when someone installs the package, the files will be installed under the `vendor` directory of the project root they are working in. Hence the library path becomes something similar to `/home/user/projects/a/vendor/myvendor/mypkg/libs/lib.so`.

Now, when I want to use `FFI::load`, I am required to use the `FFI_LIB` define in my header file.

If the `lib.h` lives inside the package's `lib` directory, next to the `lib.so` library binary, I must take the following into consideration:

1. Cannot use `./lib.so`, as quite literally no one will run PHP from that directory
2. Cannot use absolute path, as there is no way of knowing it in advance
3. Cannot use `LD_LIBRARY_PATH` as that would require everyone to write their own wrappers for the PHP interpreter that sets the variable
4. Cannot use `/lib`, as I do not wish to pollute systems globally when installing a PHP package (Python has this problem by default, requiring juggling venvs 99% of the time)

So the only "builtin" option is to use `FFI::cdef`.

Is there any way to instruct the FFI extension to use additional search paths at runtime when loading libraries using the `FFI_LIB` definition?

My current hack to fix this goes as follows:

1. Load the raw text contents of the `lib.h` file
2. Replace the `FFI_LIB` path with an absolutized path using preg_replace or similar
3. Put the altered contents into a temporary `templib.h` file somewhere accessible (e.g. `/tmp`)
4. Use that file instead of the real `lib.h` file when doing `FFI::load(...)`.

This works and allows setting an absolute path to a library file at runtime. But this is a little hacky and I would like to see an official and supported method to do this.

Maybe something like

```
\FFI::setLibraryPaths(['/path/to/libs']); // maybe some `::resetLibraryPaths` could exist as well

// now dlopen should receive an absolute path to an `/path/to/libs/lib.so` file that was found, otherwise error out if not found, or maybe defer to regular `dlopen` logic

$ffi = \FFI::load(__DIR__ . '/lib/lib.h'); // lib.h has `FFI_LIB "lib.so" defined
```

Things I don't know about:

- Is my suggestion safe, as in do people understand what happens and what holes they might be opening up? Then again who knows how often malware and such can inject files into `/lib` in the first place.
- Would it make a dent in loading performance, if we need to glob `*.so` files in X number of user supplied directories?
- Or is this just an edge case and most of the time people will not be installing FFI Composer packages and hack together loading shims just like I did now?


Patches

Add a Patch

Pull Requests

Add a Pull Request

 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Fri Oct 30 05:02:34 2020 UTC