sts-sponsors team mailing list archive
-
sts-sponsors team
-
Mailing list archive
-
Message #02840
[Bug 1939853] Re: mysqli: Using a cursor with get_result() and prepared statements causes a segmentation fault
I took a look at the autopkgtest regression for php-luasandbox on arm64.
https://autopkgtest.ubuntu.com/results/autopkgtest-
focal/focal/arm64/p/php-luasandbox/20210908_213035_50d50@/log.gz
We fail on:
FAIL profiler sorting [tests/profiler-sorting.phpt]
I started a t4.medium arm64 instance on AWS, installed autopkgtest and
ran:
$ sudo autopkgtest php-luasandbox_3.0.3-2build2.dsc --apt-
pocket=proposed -- null
Each run, the test always passes:
PASS profiler sorting [tests/profiler-sorting.phpt]
Interesting. Full test output below:
https://paste.ubuntu.com/p/3kZ2Yj4nKt/
The software I was running to conduct the tests, clearly showing php7.4
from -proposed is installed:
$ uname -a
Linux ip-172-31-28-33 5.11.0-1017-aws #18~20.04.1-Ubuntu SMP Fri Aug 27 11:19:40 UTC 2021 aarch64 aarch64 aarch64 GNU/Linux
$ sudo apt-cache policy php7.4-cli
php7.4-cli:
Installed: 7.4.3-4ubuntu2.6
Candidate: 7.4.3-4ubuntu2.6
Version table:
*** 7.4.3-4ubuntu2.6 500
500 http://ap-southeast-2c.clouds.ports.ubuntu.com/ubuntu-ports focal-proposed/main arm64 Packages
100 /var/lib/dpkg/status
So why does the test consistently fail on autopkgtest infrastructure?
Looking at the test itself:
https://paste.ubuntu.com/p/kwZNrgb3fk/
We see why. The test itself is based on completing three busy loops
counting from 0 to 1e6, 0 to 4e6 and 0 to 2e6, all within a 0.5s window.
If the arm64 based autopkgtest server / VM is under high load, then it
might get scheduled out and not complete within the timeframe, and cause
the loop to break and the test to error.
The test is inherently flaky and based on VM performance. On AWS with
just this running, the autopkgtest passes every time. This should not be
a reason to prevent php7.4 7.4.3-4ubuntu2.6 from being released to
-updates.
--
You received this bug notification because you are a member of STS
Sponsors, which is subscribed to the bug report.
https://bugs.launchpad.net/bugs/1939853
Title:
mysqli: Using a cursor with get_result() and prepared statements
causes a segmentation fault
Status in php7.4 package in Ubuntu:
Fix Released
Status in php7.2 source package in Bionic:
Fix Committed
Status in php7.4 source package in Focal:
Fix Committed
Bug description:
[Impact]
If you attempt to use a prepared statement with the mysqli database
driver to create a cursor which you then execute() and fetch rows with
get_result() and then fetch_assoc(), php with hit a segmentation fault
on every query and terminate.
This is because cursors aren't actually implemented for prepared
statements for the mysqli driver in php 7.2 and 7.4, the versions in
Bionic and Focal. When we try and use a cursor, we just segfault on a
type mismatch when the cursor calls fetch_row().
The fix comes in two forms. The first commit fixes the segfault and
makes php return an error to the user, and the second commit
implements support for cursors on prepared statements. When combined,
these commits fix the issue.
A workaround is to not use prepared statements, and instead use
query() directly.
[Test case]
Install PHP and mysql-client:
Focal:
$ sudo apt install php7.4 php7.4-mysql mysql-client
Bionic:
$ sudo apt install php7.2 php7.2-mysql mysql-client
Next, install and configure mysql 5.3:
$ sudo apt install libncurses5 libaio1 libmecab2
$ wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.35-linux-glibc2.12-x86_64.tar.gz
$ groupadd mysql
$ useradd -r -g mysql -s /bin/false mysql
$ cd /usr/local
$ tar zxvf /home/ubuntu/mysql-5.7.35-linux-glibc2.12-x86_64.tar.gz
$ ln -s mysql-5.7.35-linux-glibc2.12-x86_64 mysql
$ cd mysql
$ mkdir mysql-files
$ chown mysql:mysql mysql-files
$ chmod 750 mysql-files
$ bin/mysqld --initialize --user=mysql
$ bin/mysql_ssl_rsa_setup
$ bin/mysqld_safe --user=mysql &
# [Note] A temporary password is generated for root@localhost:
*rjfy#_w(8kM
Access the DBMS and add users, databases and tables, along with some
data:
$ mysql -h 127.0.0.1 -P 3306 -u root -p
ALTER USER 'root'@'localhost' IDENTIFIED BY 'ubuntu';
CREATE DATABASE ubuntu_releases;
use ubuntu_releases;
CREATE TABLE ubuntu_releases (year INT, month INT, name VARCHAR(20)) ;
INSERT INTO ubuntu_releases VALUES (21, 04, 'hirsute');
INSERT INTO ubuntu_releases VALUES (20, 10, 'groovy');
INSERT INTO ubuntu_releases VALUES (20, 04, 'focal');
CREATE USER 'ubuntu' IDENTIFIED BY 'ubuntu';
GRANT ALL PRIVILEGES ON ubuntu_releases.* TO 'ubuntu';
exit
Save the following script to testcase.php:
<?php
$dbConn= new mysqli("127.0.0.1", "ubuntu", "ubuntu", "ubuntu_releases", "3306");
$SQL="SELECT * from ubuntu_releases";
$stmt=$dbConn->prepare($SQL);
$stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_READ_ONLY);
$stmt->execute();
if ($stmt) {
$res = $stmt->get_result();
while($row = $res->fetch_assoc()) {
echo json_encode($row) . "\n";
}
}
$dbConn->close()
?>
Run the php script:
$ php testcase.php
Segmentation fault (core dumped)
A ppa with test packages is available below:
https://launchpad.net/~mruffell/+archive/ubuntu/sf315485-test
When you install the test packages, you should see:
$ php testcase.php
{"year":21,"month":4,"name":"hirsute"}
{"year":20,"month":10,"name":"groovy"}
{"year":20,"month":4,"name":"focal"}
[Where problems can occur]
We are changing the behaviour of how cursors work in the mysqli
database driver backend. Luckily, we are only changing how they work
for prepared statements in mysqli, and it doesn't affect any other
database driver backend, or regular queries with mysqli.
Since attempting to use a cursor with prepared statements on mysqli
backend results in a segfault due to it not being implemented, there
won't be any users that are using cursors with prepared statements,
since their applications would crash. Adding support likely won't
break any existing users, as attempting to use such features before
would result in a hard crash, versus making existing code start
working or behave differently.
There is still risk these changes could introduce a regression, and it
would be restricted to users using the mysqli database driver, which I
imagine are a significant amount of the userbase, due to the
popularity of mysql and mariadb. If a regression were to occur, users
might need to change their database driver interface code, or in worst
case, change to direct queries from prepared statements while a fix is
created.
[Other Info]
The following commit fixes the segmentation fault and changes it to an
not implemented error:
commit b5481defe64c991d0e4307372d69c0ea3cd83378
Author: Dharman <tekiela246@xxxxxxxxx>
Date: Thu Sep 17 12:35:26 2020 +0100
Subject: Fix bug #72413: Segfault with get_result and PS cursors
Link: https://github.com/php/php-src/commit/b5481defe64c991d0e4307372d69c0ea3cd83378
The following commit implements support for cursors on prepared
statements:
commit bc166844e37a6e1531a18dc0916fbe508152fc6c
Author: Nikita Popov <nikita.ppv@xxxxxxxxx>
Date: Wed Dec 16 12:12:06 2020 +0100
Subject: MySQLnd: Support cursors in store/get result
Link: https://github.com/php/php-src/commit/bc166844e37a6e1531a18dc0916fbe508152fc6c
Both of these commits landed in php 7.4.13 and 7.4.15, which means
they are already present in hirsute 7.5.16 and impish 8.0.
Both commits required backports to remove the NEWS hunk, and the
second commit needed indentation adjustments. For Bionic, the second
commit required two changes. There are two hunks in
ext/mysqlnd/mysqlnd_ps.c particularly around the function
mysqlnd_stmt_send_cursor_fetch_command() and a small change to
ext/mysqli/tests/bug77935.phpt, moving ); after SQL block.
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/php7.4/+bug/1939853/+subscriptions