laravel / framework

The Laravel Framework.
https://laravel.com
MIT License
32.36k stars 10.97k forks source link

Potential infinite recursion when executing `schema:dump` #52434

Closed FeBe95 closed 2 months ago

FeBe95 commented 2 months ago

Laravel Version

10.48.16

PHP Version

8.2.12

Database Driver & Version

MariaDB on Amazon RDS 10.6.16

Description

I noticed that the execution of

php artisan schema:dump

can potentially run into two infinite recursive loop here:

https://github.com/laravel/framework/blob/e1a9c5dcabb8cd49838648ddc34c5e5272e1a52c/src/Illuminate/Database/Schema/MySqlSchemaState.php#L155-L165

There's even a comment on StackOverflow, where a user ran into exactly this issue: https://stackoverflow.com/questions/59410746/getting-mysqldump-error-unknown-variable-column-statistics-0-when-exporting#comment136792230_59442494

I am fine with recursion in general, but there needs to be some kind of fail-safe to catch infinit loops here, e.g. a max retry count. We can't rely on consistent output of mysqldump here.

Steps To Reproduce

TLDR:

  1. Run composer create-project laravel/laravel column-statistics
  2. Setup MySQL/MariaDB database connection
  3. Set DB_USERNAME to a user that does not have the LOCK TABLES permission
  4. Run php artisan schema:dump

Output:

> php artisan schema:dump
mysqldump: unknown variable 'column-statistics=0'
mysqldump: Got error: 1044: "Access denied for user 'test'@'%' to database 'test_database'" when using LOCK TABLES
mysqldump: Got error: 1044: "Access denied for user 'test'@'%' to database 'test_database'" when using LOCK TABLES
mysqldump: Got error: 1044: "Access denied for user 'test'@'%' to database 'test_database'" when using LOCK TABLES
mysqldump: Got error: 1044: "Access denied for user 'test'@'%' to database 'test_database'" when using LOCK TABLES
mysqldump: Got error: 1044: "Access denied for user 'test'@'%' to database 'test_database'" when using LOCK TABLES
# ...

Detailed Explanation:

There are for sure multiple ways of triggering an infinite recursion here, but the simplest way, that I have found, is to have the word column-statistics somewhere in the path of your working directory. Now, if any error is reported by mysqldump, it will result in an infinite loop, since the working directory is part of the error output that is being parsed here: https://github.com/laravel/framework/blob/e1a9c5dcabb8cd49838648ddc34c5e5272e1a52c/src/Illuminate/Database/Schema/MySqlSchemaState.php#L155

In my case $e->getMessage() looked like this:

The command "mysqldump  --user="${:LARAVEL_LOAD_USER}" --password="${:LARAVEL_LOAD_PASSWORD}" --host="${:LARAVEL_LOAD_HOST}" --port="${:LARAVEL_LOAD_PORT}" --no-tablespaces --skip-add-locks --skip-comments --skip-set-charset --tz-utc "${:LARAVEL_LOAD_DATABASE}" --routines --result-file="${:LARAVEL_LOAD_PATH}" --no-data" failed.

Exit Code: 2(Misuse of shell builtins)

Working directory: C:\xampp\htdocs\column-statistics

Output:
================

Error Output:
================
mysqldump: Got error: 1044: "Access denied for user 'test'@'%' to database 'test_database'" when using LOCK TABLES
driesvints commented 2 months ago

Hey there,

Unfortunately we don't support this version anymore. Please check out our support policy on which versions we are currently supporting. Can you please try to upgrade to the latest version and see if your problem persists? If so, please open up a new issue and we'll help you out.

Thanks!

FeBe95 commented 2 months ago

@driesvints The project I am currently working on is indeed using Laravel 10 (like stated above). Regardless of that, I installed the latest Laravel version for the "Reproducer" by calling composer create-project laravel/laravel column-statistics. So this issue is indeed still present in the latest Laravel version. I will create a new ticket with the correct version info. Sorry for the confusion :)