Attached is a debdiff for Focal.

I have run the three tests included in these changes, and they all
succeed:

ext/mysqli/tests/ps_cursor_multiple_result_sets.phpt
ext/mysqli/tests/bug77935.phpt
ext/mysqli/tests/mysqli_stmt_get_result.phpt

https://paste.ubuntu.com/p/ZBz9wtXcDr/

** Description changed:

  [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()
+  $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 <[email protected]>
  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 <[email protected]>
  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.
+ 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.

** Patch added: "Debdiff for php on Focal"
   
https://bugs.launchpad.net/ubuntu/+source/php7.4/+bug/1939853/+attachment/5518352/+files/lp1939853_focal.debdiff

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/1939853

Title:
  mysqli: Using a cursor with get_result() and prepared statements
  causes a segmentation fault

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/php7.2/+bug/1939853/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to