|  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
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
Block user comment
Status: Assign to:
Bug Type:
From: ojrask at gmail dot com
New email:
PHP Version: OS:


 [2020-02-04 11:47 UTC] ojrask at gmail dot com
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/`.

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 `` library binary, I must take the following into consideration:

1. Cannot use `./`, 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/` 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 "" 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?


Add a Patch

Pull Requests

Add a Pull Request

PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Sat Jan 16 17:01:23 2021 UTC