2

I'm having trouble using a third party .so library in PHP with the new FFI. When I run this little piece of code:

<?php

$ffi = FFI::cdef('typedef int (*NFE_Nome)(const char* sNome, int* esTamanho);', 'libacbrnfe64.so');

PHP outputs me this error:

double free or corruption (out)
Aborted (core dumped)

Is this a problem with the library itself, my PHP configuration or something else? It's confusing to me, because I can use normally this same library with this C++ code:

#include <iostream>
#include <dlfcn.h>

typedef int (*NFE_Nome)(const char* sNome, int* esTamanho);

#define BUFFER_LEN 256

int main() {
    void *lib = dlopen("libacbrnfe64.so", RTLD_LAZY);

    auto libMethod = (NFE_Nome) dlsym(lib, "NFE_Nome");

    const std::string bufferNome(BUFFER_LEN, ' ');
    int bufferNomeLength = BUFFER_LEN;

    libMethod(bufferNome.c_str(), &bufferNomeLength);

    std::cout << bufferNome << std::endl;
    return 0;
}

I'm aware that the PHP code doesn't execute the NFE_Nome function, but I'm getting the error before trying to call the function itself.

miken32
  • 42,008
  • 16
  • 111
  • 154
  • Exactly the same error. The library is originally written in Pascal, compiled with Lazarus. I don't have a lot of experience in C programming, or using shared libraries, but could this be the cause of the problem? – Heverton Coneglian de Freitas Jan 29 '20 at 11:08
  • Are you using the latest `php` and `libffi` versions (php-7.4.2 and libffi-3.3)? – Lorinczy Zsigmond Jan 29 '20 at 11:55
  • Yes, I am, PHP 7.4.2 and libffi 3.3-2.3 – Heverton Coneglian de Freitas Jan 29 '20 at 12:38
  • Well, I compiled those from source; tried your PHP-program on AIX/PowerPC and Linux/x64 but couldn't reproduce the problem. Though I do get _Failed loading_ error, unless I change the filename to `./libacbrnfe64.so` -- Mind you, I'd never use C++ for a plugin. C++ is not compatible with dynamic loading. (Or anything.) – Lorinczy Zsigmond Jan 29 '20 at 12:44
  • Just tried on another computer and now I'm getting this error: Inconsistency detected by ld.so: dl-minimal.c: 126: realloc: Assertion `ptr == alloc_last_block' failed! Here are the binaries of the library that I'm using: https://drive.google.com/drive/folders/1Op6Uu05Bp0vDtq2WR3a61I2qRkzPsM_c?usp=sharing – Heverton Coneglian de Freitas Jan 29 '20 at 13:12

1 Answers1

2

-- Edit --

This problem is result of two bugs in two different programs.

  1. When linking a shared objects, fpc-3.0.0 (or newer) adds this to the dependencies (as the first dependency): /lib64/ld-linux-x86-64.so.2

  2. ld-linux-x86-64.so.2 exports a calloc variant, that doesn't (always) clears the memory it returns (details below)

The workaround OP suggested is linking in a separate pass (using -E (or -Cn) option of fpc), but before running ./ppas.sh fixing link.res file. For that, I hacked this awk-script, but I do feel it a bit clumsy:

#!/usr/bin/awk -f
$0=="INPUT(" { state=1; next; }
$0=="/lib64/ld-linux-x86-64.so.2" { state=2; next; }
$0==")" && state>0 { state=0;next; }
state==1 { print "INPUT("; state=0; }
{ print $0; }

-- Original answer --

Sounds like a linking problem: you might have added /lib64/ld-linux-x86-64.so.2 into the dependent shared libraries, which is neither required or useful.

Actually, it resulted a calloc version that returns non-zeroed memory. The details are described here: https://www.linuxquestions.org/questions/programming-9/debugging-dlopen-4175668676/ and here: Why does calling calloc in gdb not appear to zero out the memory?

Suggested solution: change the linkage according to the example:

- gcc -shared -o demodule.so demodule.o /lib64/ld-linux-x86-64.so.2 -lglib-2.0
+ gcc -shared -o demodule.so demodule.o -lglib-2.0

The difference can be checked with readelf -d. Wrong:

Dynamic section at offset 0x828 contains 26 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libglib-2.0.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

Right output:

Dynamic section at offset 0x7f8 contains 25 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libglib-2.0.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

Also, with command ldd demodule.so the line containing /lib64/ld-linux-x86-64.so.2 should be the last one.

Edit: discussion on sourceware.org regarding this problem: https://sourceware.org/bugzilla/show_bug.cgi?id=25486

Edit: on Freepascal side: https://bugs.freepascal.org/view.php?id=36706

Lorinczy Zsigmond
  • 1,749
  • 1
  • 14
  • 21
  • So, the shared object is not compiled using gcc. It is a Lazarus project, therefore using the fpc. I have access to the source code, but have no idea how to tell fpc not to use the ld-linux-x86-64.so.2 library – Heverton Coneglian de Freitas Jan 31 '20 at 11:44
  • @HevertonConegliandeFreitas Could you please quote the linking command (even if it is an user-friendly IDE, it still might show the command that is executed when linking). – Lorinczy Zsigmond Jan 31 '20 at 12:55
  • 1
    I've managed to successfully link the library without the wrong dependency. If you pass to fpc the argument -Cn, it omits the linking phase. Then it generates two files, one called ppas.sh with instructions to link the project and a link.res file, with all the parameters to link. At the end of the link.res file, there is a line like this: INPUT(/lib64/ld-linux-x86-64.so.2). I just removed this line and executed the .sh script, and now I can load the library into the PHP code without errors – Heverton Coneglian de Freitas Jan 31 '20 at 14:13
  • @HevertonConegliandeFreitas My test-case didn't show this; guess because my fpc is old (2.6.4), and my test-library is almost empty. The problem is, I know nothing about Free Pascal. Maybe you could share some non-trivial example source-file so that I could reproduce this behaviour. – Lorinczy Zsigmond Jan 31 '20 at 14:38
  • 1
    I know nothing about Pascal as well ;) The library I'm trying to use is an open source set of libraries used to do some fiscal integrations with the Brazilian federal department of revenue: http://svn.code.sf.net/p/acbr/code/trunk2/Projetos/ACBrLib/Fontes/NFe/ – Heverton Coneglian de Freitas Jan 31 '20 at 16:34