Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bus error with PDO Firebird on RPI with 64 bit kernel and 32 bit userland #10908

Closed
rvk01 opened this issue Mar 22, 2023 · 12 comments
Closed

Bus error with PDO Firebird on RPI with 64 bit kernel and 32 bit userland #10908

rvk01 opened this issue Mar 22, 2023 · 12 comments

Comments

@rvk01
Copy link

rvk01 commented Mar 22, 2023

Description

With a simple apt-get upgrade on my RPI 4 it was upgraded to a 64 bit kernel automatically :(
uname -a
Linux space01 6.1.19-v8+ #1637 SMP PREEMPT Tue Mar 14 11:11:47 GMT 2023 aarch64 GNU/Linux

Now the SELECT of a BIGINT and NUMERIC(18,3) always results in a "Bus error".

Switching back to the 32 bit kernel (with arm_64bit=0 in /boot/config.txt) it works again:
uname -a
Linux space01 6.1.19-v7l+ #1637 SMP Tue Mar 14 11:07:55 GMT 2023 armv7l

But I can't use the 32 bit kernel anymore because of multiple out of memory errors.
(with 8GB there is too little space in the lower memory)

Casting a BIGINT to INTEGER and a NUMERIC(18,3) to NUMERIC(9,3) works too.
(It seems from NUMERIC(10,3) and above the error occurs again.)

Reproduce with the following code (command for creating testdatabase is in the comments):

<?php

// Environment Raspberry Pi 4 8GB / Raspbian GNU/Linux 11 (bullseye)

// PHP 8.2.4 with PDO
// php8.2-common    8.2.4-1+0~20230316.17+debian11~1.gbp556b04
// php8.2-interbase 8.2.4-1+0~20230316.17+debian11~1.gbp556b04
// Firebird client LI-V6.3.7.33374 Firebird 3.0

// Working in kernel 32 bit: Linux space01 6.1.19-v7l+ #1637 SMP Tue Mar 14 11:07:55 GMT 2023 armv7l
// Not working in kernel 64 bit: Linux space01 6.1.19-v8+ #1637 SMP PREEMPT Tue Mar 14 11:11:47 GMT 2023 aarch64 GNU/Linux

/*
Create the test database on a console terminal (maybe adjust the path of the database):

isql-fb <<EOF
CREATE DATABASE 'localhost:/home/firebird/testdb.fdb' USER 'SYSDBA' PASSWORD 'masterkey' PAGE_SIZE 8192;
COMMIT;
CONNECT 'localhost:/home/firebird/testdb.fdb' USER 'SYSDBA' PASSWORD 'masterkey';
CREATE TABLE TESTTABLE(
  ID BIGINT NOT NULL,
  CODE VARCHAR(60) NOT NULL,
  NUM NUMERIC(18, 3)
);
INSERT INTO TESTTABLE VALUES(1, 'ABC', 12.34);
COMMIT;
exit;
EOF

*/

$fb = new PDO("firebird:dbname=localhost:/home/firebird/testdb.fdb;charset=utf8", 'SYSDBA', 'masterkey');

// the following sql gives the results (in the comments)

$sql="SELECT CODE FROM TESTTABLE"; // works fine
$sql="SELECT ID   FROM TESTTABLE"; // Bus error
$sql="SELECT NUM  FROM TESTTABLE"; // Bus error
$sql="SELECT *    FROM TESTTABLE"; // Bus error

$sql="SELECT CAST(NUM AS NUMERIC(9, 3)) FROM TESTTABLE"; // works fine
$sql="SELECT CAST(ID AS INTEGER)        FROM TESTTABLE"; // works fine
$sql="SELECT CAST(ID AS BIGINT)         FROM TESTTABLE"; // Bus error

foreach ($fb->query($sql) as $row) {
  print_r($row);
  print("\n");
}

Resulted in this output:

Bus error

But I expected this output instead:

Array
(
    [CAST] => 1
    [0] => 1
)

PHP Version

PHP 8.2.4

Operating System

Raspbian GNU/Linux 11 (bullseye)

@rvk01 rvk01 changed the title Bus error with SELECT in PDO Firebird on RPI with 64 bit kernel and 32 bit userspace Bus error with PDO Firebird on RPI with 64 bit kernel and 32 bit userspace Mar 22, 2023
@rvk01 rvk01 changed the title Bus error with PDO Firebird on RPI with 64 bit kernel and 32 bit userspace Bus error with PDO Firebird on RPI with 64 bit kernel and 32 bit userland Mar 22, 2023
@nielsdos
Copy link
Member

I can reproduce this. It's a misaligned memory access. I'll work on a fix and a test case and submit a PR soon.
Thanks for the nice issue report with the great reproducer, really nice easy-to-follow instructions!

nielsdos added a commit to nielsdos/php-src that referenced this issue Mar 23, 2023
…l and 32 bit userland

The alignment of sqldata is in most cases only the basic alignment,
so the code type-puns it to a larger type, it *can* crash due to the
misaligned access. This is only an issue for types > 4 bytes because
every sensible system requires an alignment of at least 4 bytes for
allocated data.

Even though this patch uses memcpy, the compiler is smart enough to
optimise it to something more efficient, especially on x86.
This is just the usual approach to solve these alignment problems.

Actually, unaligned memory access is undefined behaviour, so even on x86
platforms, where the bug doesn't cause a crash, this can be problematic.
Furthermore, even though the issue talks about a 64-bit kernel and
32-bit userspace, this doesn't necessarily need to be the case to
trigger this crash.

Test was Co-authored-by: rvk01
@rvk01
Copy link
Author

rvk01 commented Mar 24, 2023

I can reproduce this. It's a misaligned memory access. I'll work on a fix and a test case and submit a PR soon. Thanks for the nice issue report with the great reproducer, really nice easy-to-follow instructions!

Thanks for picking this up so fast. I appreciate that greatly. I tried to test your changes as good as I could (I'm not that familiar with compiling PHP) but I've managed to create a pdo_firebird.so for the newer PHP version (I didn't know which switched I needed to use for a complete install).

The BIGINT and NUMERIC work (the last you added this morning). I'm not sure how far you are but it seems that TIMESTAMP also has a problem (don't know if you added that one already).

(CASTing a TIMESTAMP to DATE works)

@nielsdos
Copy link
Member

Thanks for testing. I'll handle timestamp now too and update the test to check timestamp.

@rvk01
Copy link
Author

rvk01 commented Mar 24, 2023

Thanks for testing. I'll handle timestamp now too and update the test to check timestamp.

Sorry... I've got another one... BLOB fields have the same problem :(
(specifically BLOB SUB_TYPE 0)

Can there still be any other larger fields we missed?

(Newer Firebird also has INT128, but I don't use that yet, not sure if you got that one too)

@nielsdos
Copy link
Member

No need to apologize, on the contrary, it's good that you find these issues!
I'll handle BLOB too, thanks for pointing that out.

I don't see INT128 in our Firebird code, so maybe we should create a feature request to add support for that.

@rvk01
Copy link
Author

rvk01 commented Mar 24, 2023

Ah, Ok. I still maintain Firebird 2.5 code so I have no need for INT128 support... yet :)

The complete list of datatypes is here (but you probably already know):
https://firebirdsql.org/file/documentation/chunk/en/refdocs/fblangref40/fblangref40-datatypes.html
The bigger types probably all have the problem (but I think we tackled these now).

I'll test it again when I see the changes in your tree. (I'll include all the fields I use then)

I guess it'll take some time before these changes trickle down to production version, so I'll use my own compiled pdo_firebird.so version until then ;)

Thanks.

@nielsdos
Copy link
Member

The complete list of datatypes is here (but you probably already know):
https://firebirdsql.org/file/documentation/chunk/en/refdocs/fblangref40/fblangref40-datatypes.html
The bigger types probably all have the problem (but I think we tackled these now).

Thanks for the list. And no I didn't actually know this, in fact, I have never used Firebird until I started working on your issue :P

I'll test it again when I see the changes in your tree. (I'll include all the fields I use then)

My tree has the fixes for the remaining issues now. :)
Let me know if you find any more issues.

I guess it'll take some time before these changes trickle down to production version, so I'll use my own compiled pdo_firebird.so version until then ;)

Sounds good!

@rvk01
Copy link
Author

rvk01 commented Mar 24, 2023

My tree has the fixes for the remaining issues now. :)
Let me know if you find any more issues.

Thanks. For now it seems to work perfect.
I'll put this through it's paces this weekend, but for now my pages are up again :)

@nielsdos
Copy link
Member

Cool. Just make sure your current git HEAD is commit 897352d which is the latest commit. It has one additional fix and I had committed that after posting my comment above.

@rvk01
Copy link
Author

rvk01 commented Mar 24, 2023

Just make sure your current git HEAD is commit 897352d which is the latest commit.

I'm still relative new to git but I think I have the latest (also got it with a pull).
git rev-parse --short HEAD
897352d

git log -1
commit 897352d (HEAD -> fix-10908, tag: list, origin/fix-10908)
Date: Fri Mar 24 17:48:56 2023 +0100 / Fix CI compilation problem

So I guess I have the latest :)
I had to hack the Zend/zend_modules.h a bit to set the correct API version (20220829) for using the pdo_firebird.so in my own production PHP 8.2 but that all seems to work fine :)

Edit: Ah. The numbers here are automatically converted to commit links :)

@nielsdos
Copy link
Member

Yep looks like you got the correct commit.

While you can hack that version number to allow 8.1 code on 8.2, it's best to rebase the patch on 8.2 so that there are no potential API mismatches. Although I think the chance is low it causes issues in this particular case.

@rvk01
Copy link
Author

rvk01 commented Mar 24, 2023

You are correct. But because I'm still learning git and merging etc, it was easier for me to just hack your complete 8.1 version for now. Even with a complete PHP 8.2 merged with this fix, I couldn't put this in production because I'm still unsure about all the switched I need to use for ./configure on a RPI4. So for now I just used

./configure --disable-opcache-jit --without-pcre-jit --with-pdo-firebird=shared --host=arm-linux --build=arm --target=arm

(which is probably different from the normal production version)

But I could take the latest PHP 8.2 (with fix) and recompile so the latest API is used (although the changes only seem to be in pdo_firebird. But maybe some other code is used too.) I'll recompile this weekend (if I can figure out git :) ).

nielsdos added a commit that referenced this issue Mar 27, 2023
* PHP-8.1:
  Fix GH-10908: Bus error with PDO Firebird on RPI with 64 bit kernel and 32 bit userland
nielsdos added a commit that referenced this issue Mar 27, 2023
* PHP-8.2:
  Handle indirect zvals in SplFixedArray::__serialize
  Fix GH-10908: Bus error with PDO Firebird on RPI with 64 bit kernel and 32 bit userland
nielsdos added a commit that referenced this issue Mar 27, 2023
It turns out that the version of Firebird influences the test in terms
of supported data types. On Windows on 8.2 we seem to be using a
different version than on 8.1. Fix it by amending the test.
The core issue is still tested in the test, it's just that not all
datatypes are tested anymore (which isn't strictly necessary anyway).
nielsdos added a commit that referenced this issue Mar 27, 2023
* PHP-8.2:
  Fix test for GH-10908
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
@nielsdos @rvk01 and others