diff --git a/.gitignore b/.gitignore index b453d8b56780..5b6e5c23c2e1 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,10 @@ source_downloads # Configuration files for Visual Studio Code .vscode/ +/GPATH +/GRTAGS +/GTAGS + build/ datatool/ datatools/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0c3408cc4189..2dd845e45fe4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,18 +1,312 @@ -We welcome your code contributions. Before submitting code via a GitHub pull -request, or by filing a bug in https://bugs.mysql.com you will need to have -signed the Oracle Contributor Agreement, see https://oca.opensource.oracle.com - -Only pull requests from committers that can be verified as having signed the OCA -can be accepted. - -Submitting a contribution -------------------------- - -1. Make sure you have a user account at https://bugs.mysql.com. You'll need to reference - this user account when you submit your OCA (Oracle Contributor Agreement). -2. Sign the Oracle OCA. You can find instructions for doing that at the OCA Page, - at https://oca.opensource.oracle.com -3. Validate your contribution by including tests that sufficiently cover the functionality. -4. Verify that the entire test suite passes with your code applied. -5. Submit your pull request via GitHub or uploading it using the contribution tab to a bug - record in https://bugs.mysql.com (using the 'contribution' tab). +# Contributing Guide + +## Welcome to Percona Server for MySQL! + +We're excited to have you join the Percona community and participate in keeping open-source open. + +### Why Your Contribution Matters? +Main driving force of open-source project is community. We, as developers team, highly appreciate any contributions. + +Working with the MySQL 8.0 source code can be time-consuming, especially for developers new to the project. + +MySQL is a complex piece of software with a vast code base. Understanding the intricacies of its architecture, data structures, and algorithms can require significant time and effort. The code base is constantly evolving, so staying up-to-date with changes can be challenging. + +Here are some factors that contribute to the complexity of working with MySQL source code: + + + * Large code base: MySQL has a massive code base, making it difficult to navigate and understand. + * Complex architecture: MySQL architecture is intricate and involves multiple components and layers. + * Performance optimizations: MySQL is heavily optimized for performance, which can make the code base even more complex. + * Ongoing development: The MySQL project constantly evolves, with new features and bug fixes regularly added. + +However, for experienced C++ developers who are familiar with database systems and are willing to invest the time and effort, working with the MySQL source code can be a rewarding experience. It can provide a deep understanding of how MySQL works and allow for customization and optimization. + + + +It may be advisable to initially submit bug fixes to the upstream project that will eventually become part of the next +release of Percona. + +Alternatively, Percona provides expedited response times, transparent development processes, and +streamlined contribution acceptance within a public repository. + +You can contribute in one of the following ways: + +* Submit a bug report or a feature + request in [ our public Jira ](https://jira.percona.com/projects/PS/issues). +* Submit a pull request (PR) with the code patch. +* Contribute to [the documentation](https://github.com/percona/psmysql-docs/blob/innovation-release/contributing.md) +* Reach us on our [ Forums ](https://forums.percona.com/c/mysql-mariadb) + +This document describes the workflow for submitting pull requests. +By contributing, you agree to the [Percona Community code of conduct](https://percona.community/contribute/coc/). + +### Pull request actions + +Steps of the workflow for preparing, submitting and merging pull request are: + +1. [Creating Jira a issue](#creating-a-jira-issue) +2. [Forking code to your GitHub account](#forking-code-to-your-github-account) +3. [Creating a branch for your changes](#creating-a-branch-for-your-changes) +4. [First build of the MySQL source code](#first-build-of-the-mysql-source-code) +5. [Opening the code in an IDE](#opening-the-code-in-an-ide) +6. [Testing changes](#testing-changes) +7. [Preparing the pull request](#preparing-the-pull-request) +8. [Peer review and requests of changes](#peer-review-and-requests-of-changes) +9. [Merging pull request](#merging-pull-request) + +Description of each step is below. + +Thank you for helping us enhance Percona Server for MySQL. + +## Your Code and MySQL Versions + +Percona officially supports 2 "production" version lines of MySQL and keeps track on innovation version line. At the moment they are: + +1. 8.0.X - stable line. +2. 8.4.X - next stable line, or LTS line. +3. 9.X.Y - innovation line, a test bed for everything new at the moment. + +Next LTS version may be 9.7, so until then 9.X are "innovation" versions. + +It is not easy to keep track of all the changes and understand how the new code will work with different versions. +Therefore, your best bet is to work with the version line you're currently using and familiar with. Nevertheless, +Percona developers team will take care of your code, and port or backport it to other version lines if it is applicable. + +## Creating a Jira Issue + +The creation of a Jira issue is _mandatory_ first step for a Pull Request preparation. If you're going to write code for some fix or a new feature, you should first describe in form of a Jira ticket what you are going to do. + +A comprehensive description of the bug or feature is essential. It helps the team to perform thorough testing of the solution, to include of pertinent information in the release notes, and for other relevant details. + +Additionally, linking your future pull request to the corresponding issue with a detailed description will facilitate the development process and help reviewers to understand your solution. + +Also, the Jira issue number is a required part of a branch name for your new code. + +To create Jira issue, please open the [ LINK ](https://perconadev.atlassian.net/jira/software/c/projects/PS/issues) and +authenticate with your favorite social network account (Google, Facebook, etc.). Then follow the instructions and verify +your e-mail. If Jira starts to redirect you back and forth (their bug, not ours), just open a new browser window with +the link above. + +Now you're ready to an create issue. Find the big "Create" button in the top menu and press it. Choose issue type from +the second drop-down, saying it is a Bug, an Improvement, or a New feature. Fill in all the required fields below. Please, add accurate and detailed description. +Good description is a big first step to the solution. The +rest of the fields are mostly for internal use; the core team developers will fill it later. + + As soon as Jira issue is submitted, you are ready to start coding. + +## Working with the Source Code + +Steps of the workflow: + +1. [Forking the code to your GitHub account](#forking-code-to-your-github-account) +2. [Creating a branch for your changes](#creating-a-branch-for-your-changes) +3. [First build of the MySQL source code](#first-build-of-the-mysql-source-code) +4. [Setting up development environment and making changes](#setting-up-development-environment-and-making-changes) +5. [Testing changes](#testing-changes) + +### Forking code to your GitHub account + +First, you should have a GitHub account. You can not work with the Percona repository directly, you have +to [ "Fork" ](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) +our repository to your GitHub account. To do so, +open [ Percona PS repository](https://github.com/percona/percona-server) in a browser. Then, right to the repository +name you'll find the "Fork" button. Press it. +If you already have the fork, please do not forget to sync it with the Percona's one. + +Then return to your GitHub home page, find your "percona-server" repository and clone it locally. +Note +that [ creating SSH keys and putting public one to the GitHub ](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account) +settings will save a lot of time for you with GitHub workflow. After it is done, you can execute the ```ssh-agent``` to authenticate to the repository automatically during entire desktop session (KDE, Gnome, etc) in all terminals: +``` +ssh-add $HOME/.ssh/id_ecdsa +``` + +### Creating a branch for your changes + +In the cloned local repository checkout the "trunk" branch you are going to work on. For 8.0.X releases is 8.0. For +8.4.X series it is 8.4, and for 9.X.Y it is "trunk". + +Now you are ready to create a branch for your contribution. Please name the branch according to the following pattern: + +``` +PS-9876-8.0-bug_in_some_module +^^^^^^^ +Jira issue number + ^^^ + Base version + ^^^^^^^^^^^^^^^^^^^ + Very short definition of the issue +``` + + +### First build of the MySQL source code + +The next step is to compile the code in your new branch before making changes. +At this point, you need to fetch third-party code which is organized as Git sub-modules. Go to the project directory and type the following: + +``` +git submodule update --init +``` + +The Git will fetch required third-party modules into the source tree. + +Now we can try to build the project. Below is a quick and dirty shell script for that (works with GCC 14). It gives you +hints how to do outside-the-tree build and how to set CMake flags. + +``` +#!/bin/bash + +CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=Debug \ + -DBUILD_CONFIG=mysql_release \ + -DDOWNLOAD_BOOST=ON \ + -DWITH_BOOST=/home/${USER}/projects/boost\ + -DWITH_SYSTEM_LIBS=ON\ + -DWITH_ZLIB=bundled \ + -DWITH_PACKAGE_FLAGS=OFF \ + -DWITH_PERCONA_TELEMETRY=ON \ + -DCMAKE_C_COMPILER=gcc-14 \ + -DCMAKE_CXX_COMPILER=g++-14 + +SRC_DIR=$1 +if [ -z ${SRC_DIR} ] ; then + echo "Please provide source directory as 1st parameter!" + exit 1 +fi +if [ -d $SRC_DIR ] ; then + echo "Source dir is $SRC_DIR" +else + echo "Source dir $SRC_DIR does not exist" + exit 1 +fi +ABS_SRC_DIR=`realpath $SRC_DIR` +SRC_DIR_PARENT="$(dirname "$ABS_SRC_DIR")" +SRC_DIR_NAME="$(basename "$ABS_SRC_DIR")" +if [ -z $2 ] ; then + BUILD_DIR="${SRC_DIR_PARENT}/BUILD-${SRC_DIR_NAME}" +else + BUILD_DIR=$2 +fi +echo "Build dir is $BUILD_DIR" +if [ -d $BUILD_DIR ] ; then + echo "Build dir exists. Cmake will re-use cached data." +else + mkdir $BUILD_DIR +fi +cd $BUILD_DIR +cmake $CMAKE_FLAGS $ABS_SRC_DIR +make -j 16 + +``` + +Compiling from a source requires patience. MySQL has many dependencies on different libraries. The good hint is to install build dependencies for the "upstream" version of MySQL. +For example, on Ubuntu ( don't forget to enable sources in _software-properties-gtk ) run following command: +``` +apt build-dep mysql-server-core-8.0 +``` + +Another hint is to check [ documentation on compilation ](https://docs.percona.com/percona-server/8.0/compile-percona-server.html) . + +If it does not help, we recommend a try and fail approach to installing the development packages. + +When the source finally successfully compiles, you're ready to run tests and check the build. You have to run at least the "start and shutdown test" of mysqld. + +``` +cd build-percona-server/mysql-test +./mtr --debug-server main.1st +``` + +This test ensures that you have working MySQL project. Maybe it is a good idea to execute ```./mtr --debug-server``` without parameters to run default test suite. It takes time but it will show that base MySQL functionality works fine in your compiled project. + +### Setting up development environment and making changes + +When the tests are OK, you're ready to set up your favorite IDE for the project development. The build script above will +give you a clue what CMake parameters to add to the project in IDE. + +To be able to run and debug the _mysqld-debug_ binary in your IDE, first run the following command in the "mysql-test" directory of the +build tree: + +``` +./mtr --debug-server --manual-debug main.1st +``` + +Then find the string stating with "args:". This is the command line arguments you should pass to the execution of " +mysqld-debug" in your IDE. This step allows to run/debug "mysqld-debug" from the IDE. + +From this moment you're ready to code and debug! Happy coding! + +### Testing changes + +Prior to submitting your code, ensure it is thoroughly tested, both manually and with automated test suites. The maintenance of high-quality code is paramount to ensure the longevity and functionality of our project. + +Testing of MySQL is a whole big thing, so please go to +the [ official documentation on MySQL testing ](https://dev.mysql.com/doc/dev/mysql-server/latest/PAGE_TESTING_TOOLS.html) +first. + +If it is bug fix, make sure that corresponding tests from the test suite work fine. It's a good idea to patch existing +tests to cover your specific case. For the introduction of new features, the development of a comprehensive test suite is strongly recommended. + +## Preparing the Pull Request + +After finishing the tasks outlined above, you must prepare your branch for a pull request. +Please do not forget to run ``` git clang-format ``` on your code before pushing to the GitHub repository. + +Then, squash all commits to one or a couple of logically consistent commits. +For example, the fix of bug should have just one commit. If you have a new feature that requires some changes to the +existing code, then the first commit should contain required changes, and the second is a new feature and tests. +Commit message should contain the Jira issue number and then a short but explanatory description in the same line. Th next line is usually the URL of the Jira issue, and then goes the full description of the commit. The commit message is very important for us, because we do a lot of work with Git wile merging upstream releases and commit messages help us to resolve possible conflicts. +Example of the commit message: +``` +PS-9876 Fix of the compression bug with zlib call parameters + +https://perconadev.atlassian.net/browse/PS-9876 + +This code fixes compression function call parameters by proper calculation of the +offset in case of previous error. +``` + +It is not a dogma, on the other hand, we value a clean and consistent Git history. Please help us maintain this standard. + +Now you can push your local branch to your GitHub repository and make a [ cross-fork ](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork) pull request to the Percona repository. + +Please, write meaningful title for the PR and put the number of Jira issue and the target branch at the beginning of the first line in the +description. The second line is usually a link to the Jira issue. Then the short description follows. No need to write a +long description because you wrote one in the Jira issue. + +Example of a pull request form: + +Title: +``` +PS-9876 (8.0) Fix of the compression bug +``` +Description: +``` +https://perconadev.atlassian.net/browse/PS-9876 + +The first commit is update of zlib, the second is the fixes of compression function calls. +``` + +### Peer review and requests of changes + +Peer review of the code always goes before PR merge. So, you have to add some core development team members in the "Reviewers" field of PR. Assign the PR to Yura Sorokin, our team lead, and then he will add other developers if needed. + +Our GitHub pipeline runs a lot of checks on each PR. Please make sure you fixed all comments provided by checks. Well, sometime not all of them :) , you understand... + +Following this step, the development team will conduct a thorough review of your code at their earliest convenience. Our +primary objective is to ensure the highest quality standards. We encourage you to interpret our comments as +opportunities for improvement and constructive feedback. Comments may contain requests for changes in the code and suggestions how to to solve possible issues. Please, pay close attention to such comments. + +### Merging pull request + +When the review is finished and all the issues are addressed, your pull request will be approved and allowed to merge into the main source tree. Usually, the merge is performed by the author, but it is a matter of permissions of the repository, so in case you don't have permissions, please ask one of reviewers to merge PR. + +Finally, your PR is merged! Congratulations! You are now a recognized contributor. + + +## When will My Code be in the release? + +Percona releases follow upstream MySQL releases. We merge upstream code changes and our code from the "trunk" as soon as +the next official upstream release becomes available. Then we build packages and test everything thoroughly. It takes time. + +We use a "train" approach. It means, that if some code is already in one of the "trunk" branches before the official +upstream release, it will be released in Percona's packages of new release. So, if we are already in the process of +working on some fresh upstream release, PR will be merged to the "trunk" but not to the release branch. And then your code will be released after the current one. diff --git a/COPYING.innodb-deadlock-count-patch b/COPYING.innodb-deadlock-count-patch new file mode 100644 index 000000000000..d2efce408da4 --- /dev/null +++ b/COPYING.innodb-deadlock-count-patch @@ -0,0 +1,30 @@ +Portions of this software contain modifications contributed by Eric Bergen. +These contributions are used with the following license: + +Copyright (c) 2010, Eric Bergen. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of the Eric Bergen. nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/COPYING.show_temp_51 b/COPYING.show_temp_51 new file mode 100644 index 000000000000..b3bb261bed15 --- /dev/null +++ b/COPYING.show_temp_51 @@ -0,0 +1,13 @@ +Portions of this software contain modifications contributed by Venu Anuganti. +These contributions are used with the following license: + +Copyright (c) 2010, Venu Anuganti, http://venublog.com/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README b/README.MySQL similarity index 100% rename from README rename to README.MySQL diff --git a/README.md b/README.md new file mode 100644 index 000000000000..f192b318287d --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +## Percona Server for MySQL + +![PS logo](doc/source/percona-server-logo.jpg) + +Percona Server for MySQL is a free, fully compatible, enhanced, and open source drop-in replacement for any MySQL database. It provides superior performance, scalability, and instrumentation. + +Percona Server for MySQL is trusted by thousands of enterprises to provide better performance and concurrency for their most demanding workloads. It delivers higher value to MySQL server users with optimized performance, greater performance scalability and availability, enhanced backups, and increased visibility. + +## Installation + +You can install Percona Server for MySQL using the following methods: +- from the Percona repository +- Build from the [source code](https://github.com/percona/percona-server) + +The installation instructions in the official documentation are [here](https://www.percona.com/doc/percona-server/8.0/installation.html). + +## Submit a bug report or a feature request + +If you find a bug in Percona Server for MySQL, you can submit a report to the project's [Jira issue tracker](https://jira.percona.com/projects/PS/issues) + +As a general rule of thumb, please try to create a bug report that is: + +- Reproducible - include the steps on how to reproduce the issue +- Specific - include as much detail as possible, such as which version, which environment, etc. +- Unique - do not duplicate existing tickets +- Scoped to a single issue - only one issue per report + +## Licensing + +Percona is dedicated to **keeping open source open**. Whenever possible, we strive to include permissive licensing for both our software and documentation. For this project, we are using version 2 of the GNU General Public License (GPLv2). + +## How to get involved + +We encourage contributions and are always looking for new members that are as dedicated to serving the community as we are. The [Doc Contributing Guide](https://github.com/percona/psmysql-docs/blob/innovation-release/contributing.md) contains how you can contribute to the documentation. + +The [ CONTRIBUTING ](CONTRIBUTING.md) file in this directory contains instructions on contributing to the code. + +## Contact + +You can reach us by using the [Forum](https://forums.percona.com/c/mysql-mariadb/percona-server-for-mysql-8-0). diff --git a/code-of-conduct.md b/code-of-conduct.md new file mode 100644 index 000000000000..576ccf8c5f87 --- /dev/null +++ b/code-of-conduct.md @@ -0,0 +1,5 @@ +# Percona Server for MySQL Code of Conduct + +All Percona Products follow the [Percona Community Code of Conduct](https://github.com/percona/community/blob/main/content/contribute/coc.md). + +If you notice any unacceptable behavior, let us know as soon as possible by writing to . We will respond within 48 hours. \ No newline at end of file diff --git a/sql-common/client.cc b/sql-common/client.cc index 36b8a389a21b..c44642b961d7 100644 --- a/sql-common/client.cc +++ b/sql-common/client.cc @@ -3512,6 +3512,166 @@ const char *STDCALL mysql_get_ssl_cipher(MYSQL *mysql [[maybe_unused]]) { return nullptr; } +#include + +#if OPENSSL_VERSION_NUMBER < 0x10002000L +/* + Compares the DNS entry from the Subject Alternative Names (SAN) list with + the provided host name + + SYNOPSIS + ssl_cmp_san_dns_name() + dns_name pointer to a SAN list DNS entry + host_name name of the server + errptr if we fail, we'll return (a pointer to a string + describing) the reason here + + RETURN VALUES + false Success + true Failed to validate server + +*/ + +static bool ssl_cmp_san_dns_name(ASN1_STRING *dns_name, const char *host_name, + const char **errptr) { + DBUG_ENTER("ssl_cmp_san_dns_name"); + *errptr = nullptr; + if (dns_name == nullptr) { + *errptr = "Failed to get DNS name from SAN list item"; + DBUG_RETURN(true); + } +#if OPENSSL_VERSION_NUMBER < 0x10100000L + const char *cn = reinterpret_cast( + const_cast(ASN1_STRING_data(dns_name))); +#else + const char *cn = static_cast(ASN1_STRING_get0_data(dns_name)); +#endif + if (cn == nullptr) { + *errptr = "Failed to get data from SAN DNS name"; + DBUG_RETURN(true); + } + // There should not be any NULL embedded in the DNS name + if (static_cast(ASN1_STRING_length(dns_name)) != strlen(cn)) { + *errptr = "NULL embedded in the certificate SAN DNS name"; + DBUG_RETURN(true); + } + DBUG_PRINT("info", ("SAN DNS name in cert: %s", cn)); + if (!strcmp(cn, host_name)) DBUG_RETURN(false); + + DBUG_RETURN(true); +} + +/* + Compares the IP address entry from the Subject Alternative Names (SAN) list + with the provided host IP address + + SYNOPSIS + ssl_cmp_san_ip_address() + ip_address pointer to a SAN list IP address entry + host_ip IP address of the server + host_ip_len server IP address length (must be either 4 or 16) + errptr if we fail, we'll return (a pointer to a string + describing) the reason here + + RETURN VALUES + false Success + true Failed to validate server + +*/ + +static bool ssl_cmp_san_ip_address(ASN1_OCTET_STRING *ip_address, + const unsigned char *host_ip, + size_t host_ip_len, const char **errptr) { + DBUG_ENTER("ssl_cmp_san_ip_address"); + *errptr = nullptr; + if (ip_address == nullptr) { + *errptr = "Failed to get IP address from SAN list item"; + DBUG_RETURN(true); + } + const size_t ip_address_len = ASN1_STRING_length(ip_address); + /* IP address length must be either 4 (IPV4) or 16 (IPV6) */ + if (ip_address_len != 4 && ip_address_len != 16) { + *errptr = "Invalid IP address embedded in the certificate SAN IP address"; + DBUG_RETURN(true); + } +#if OPENSSL_VERSION_NUMBER < 0x10100000L + const unsigned char *ip = ASN1_STRING_data(ip_address); +#else + const unsigned char *ip = ASN1_STRING_get0_data(ip_address); +#endif + if (ip == nullptr) { + *errptr = "Failed to get data from SAN IP address"; + DBUG_RETURN(true); + } + DBUG_RETURN(!(ip_address_len == host_ip_len && + memcmp(host_ip, ip, host_ip_len) == 0)); +} + +/* + Check the certificate's Subject Alternative Names (SAN) against the + hostname / IP address we connected to + + SYNOPSIS + ssl_verify_server_cert_san() + server_cert pointer to a X509 certificate + hostname_or_ip name of the server / pointer to a V4/V6 IP address + buffer + hostname_or_ip_len 0 for host name, 4/16 for ip address + errptr if we fail, we'll return (a pointer to a string + describing) the reason here + + RETURN VALUES + false Success + true Failed to validate server + +*/ + +static bool ssl_verify_server_cert_san(X509 *server_cert, + const char *hostname_or_ip, + size_t hostname_or_ip_len, + const char **errptr) { + bool ret_validation = true; + + DBUG_ENTER("ssl_verify_server_cert_san"); + *errptr = nullptr; + GENERAL_NAMES *const sans = static_cast( + X509_get_ext_d2i(server_cert, NID_subject_alt_name, nullptr, nullptr)); + if (sans == nullptr) DBUG_RETURN(ret_validation); + + const int number_of_sans = sk_GENERAL_NAME_num(sans); + for (int i = 0; ret_validation != 0 && i < number_of_sans; ++i) { + GENERAL_NAME *san = sk_GENERAL_NAME_value(sans, i); + if (san == nullptr) { + *errptr = "Failed to get item from SAN list"; + goto error; + } + if (hostname_or_ip_len == 0) { + /* server host name was provided, check only GEN_DNS entries */ + if (san->type == GEN_DNS) { + ret_validation = + ssl_cmp_san_dns_name(san->d.dNSName, hostname_or_ip, errptr); + if (*errptr != nullptr) goto error; + } + } else { + /* server IP address was provided, check only GEN_IPADD entries */ + if (san->type == GEN_IPADD) { + ret_validation = ssl_cmp_san_ip_address( + san->d.iPAddress, + reinterpret_cast(hostname_or_ip), + hostname_or_ip_len, errptr); + if (*errptr != NULL) goto error; + } + } + } /* iterating over SAN enries */ + +error: + GENERAL_NAMES_free(sans); + + DBUG_RETURN(ret_validation); +} + +#endif /* OPENSSL_VERSION_NUMBER < 0x10002000L */ + /** Get the current SSL session serialization @@ -3658,20 +3818,21 @@ bool STDCALL mysql_get_ssl_session_reused(MYSQL *mysql) { 1 Failed to validate server */ - static int ssl_verify_server_cert(Vio *vio, const char *server_hostname, const char **errptr) { SSL *ssl; X509 *server_cert = nullptr; - int ret_validation = 1; - -#if !(OPENSSL_VERSION_NUMBER >= 0x10002000L) - int cn_loc = -1; +#if OPENSSL_VERSION_NUMBER < 0x10002000L char *cn = NULL; + int cn_loc = -1; ASN1_STRING *cn_asn1 = NULL; X509_NAME_ENTRY *cn_entry = NULL; X509_NAME *subject = NULL; + const unsigned char *ipout = nullptr; + size_t iplen = 0; #endif + ASN1_OCTET_STRING *server_ip_address = nullptr; + int ret_validation = 1; DBUG_TRACE; DBUG_PRINT("enter", ("server_hostname: %s", server_hostname)); @@ -3711,50 +3872,69 @@ static int ssl_verify_server_cert(Vio *vio, const char *server_hostname, */ ret_validation = 0; #else /* OPENSSL_VERSION_NUMBER < 0x10002000L */ - /* - OpenSSL prior to 1.0.2 do not support X509_check_host() function. - Use deprecated X509_get_subject_name() instead. - */ - subject = X509_get_subject_name((X509 *)server_cert); - // Find the CN location in the subject - cn_loc = X509_NAME_get_index_by_NID(subject, NID_commonName, -1); - if (cn_loc < 0) { - *errptr = "Failed to get CN location in the certificate subject"; - goto error; - } + /* Checking if the provided server_hostname is a V4/V6 IP address */ + server_ip_address = a2i_IPADDRESS(server_hostname); + if (server_ip_address != nullptr) { + iplen = ASN1_STRING_length(server_ip_address); + ipout = (const unsigned char *)ASN1_STRING_data(server_ip_address); + } + + ret_validation = ssl_verify_server_cert_san( + server_cert, iplen != 0 ? (const char *)ipout : server_hostname, iplen, + errptr); + if (*errptr != nullptr) goto error; + if (ret_validation != 0) { + /* + OpenSSL prior to 1.0.2 do not support X509_check_host() function. + Use deprecated X509_get_subject_name() instead. + */ + subject = X509_get_subject_name(server_cert); + // Find the CN location in the subject + cn_loc = X509_NAME_get_index_by_NID(subject, NID_commonName, -1); + if (cn_loc < 0) { + *errptr = "Failed to get CN location in the certificate subject"; + goto error; + } - // Get the CN entry for given location - cn_entry = X509_NAME_get_entry(subject, cn_loc); - if (cn_entry == NULL) { - *errptr = "Failed to get CN entry using CN location"; - goto error; - } + // Get the CN entry for given location + cn_entry = X509_NAME_get_entry(subject, cn_loc); + if (cn_entry == nullptr) { + *errptr = "Failed to get CN entry using CN location"; + goto error; + } - // Get CN from common name entry - cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry); - if (cn_asn1 == NULL) { - *errptr = "Failed to get CN from CN entry"; - goto error; - } + // Get CN from common name entry + cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry); + if (cn_asn1 == nullptr) { + *errptr = "Failed to get CN from CN entry"; + goto error; + } - cn = (char *)ASN1_STRING_data(cn_asn1); + cn = reinterpret_cast(ASN1_STRING_data(cn_asn1)); + if (cn == nullptr) { + *errptr = "Failed to get data from CN"; + goto error; + } - // There should not be any NULL embedded in the CN - if ((size_t)ASN1_STRING_length(cn_asn1) != strlen(cn)) { - *errptr = "NULL embedded in the certificate CN"; - goto error; - } + // There should not be any NULL embedded in the CN + if (static_cast(ASN1_STRING_length(cn_asn1)) != strlen(cn)) { + *errptr = "NULL embedded in the certificate CN"; + goto error; + } - DBUG_PRINT("info", ("Server hostname in cert: %s", cn)); - if (!strcmp(cn, server_hostname)) { - /* Success */ - ret_validation = 0; + DBUG_PRINT("info", ("Server hostname in cert: %s", cn)); + if (!strcmp(cn, server_hostname)) { + /* Success */ + ret_validation = 0; + } } #endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */ - *errptr = "SSL certificate validation success"; + *errptr = ret_validation != 0 ? "SSL certificate validation failure" : ""; error: + if (server_ip_address != nullptr) ASN1_OCTET_STRING_free(server_ip_address); + if (server_cert != nullptr) X509_free(server_cert); return ret_validation; } diff --git a/sql-common/net_serv.cc b/sql-common/net_serv.cc index 4e5c46f768eb..2d0815d7f9a4 100644 --- a/sql-common/net_serv.cc +++ b/sql-common/net_serv.cc @@ -2244,6 +2244,7 @@ ulong my_net_read(NET *net) { void my_net_set_read_timeout(NET *net, uint timeout) { DBUG_TRACE; DBUG_PRINT("enter", ("timeout: %d", timeout)); + if (net->read_timeout == timeout) return; net->read_timeout = timeout; if (net->vio) vio_timeout(net->vio, 0, timeout); } @@ -2251,6 +2252,7 @@ void my_net_set_read_timeout(NET *net, uint timeout) { void my_net_set_write_timeout(NET *net, uint timeout) { DBUG_TRACE; DBUG_PRINT("enter", ("timeout: %d", timeout)); + if (net->write_timeout == timeout) return; net->write_timeout = timeout; if (net->vio) vio_timeout(net->vio, 1, timeout); } diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index cad44df1245d..e0b25357c3d3 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -622,7 +622,12 @@ static inline void free_plugin_mem(st_plugin_dl *p) { PSI_SYSTEM_CALL(unload_plugin) (std::string(p->dl.str, p->dl.length).c_str()); #endif +#if !defined(HAVE_VALGRIND) && !defined(HAVE_ASAN) + /* + * Avoid closing components under ASAN / Valgrind in order to get + * meaningfull leak report */ dlclose(p->handle); +#endif } my_free(p->dl.str); if (p->version != MYSQL_PLUGIN_INTERFACE_VERSION) my_free(p->plugins); diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index ff37f7c62e7e..187cdc890748 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -2,7 +2,7 @@ # Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB # This file is public domain and comes with NO WARRANTY of any kind -# MySQL daemon start/stop script. +# MySQL (Percona Server) daemon start/stop script. # Usually this is put in /etc/init.d (at least on machines SYSV R4 based # systems) and linked to /etc/rc3.d/S99mysql and /etc/rc0.d/K01mysql. @@ -21,8 +21,8 @@ # Required-Stop: $local_fs $network $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 -# Short-Description: start and stop MySQL -# Description: MySQL is a very fast and reliable SQL database engine. +# Short-Description: start and stop MySQL (Percona Server) +# Description: Percona-Server is a SQL database engine with focus on high performance. ### END INIT INFO # If you install MySQL on some other places than @prefix@, then you @@ -258,7 +258,7 @@ case "$mode" in # Safeguard (relative paths, core dumps..) cd $basedir - echo $echo_n "Starting MySQL" + echo $echo_n "Starting MySQL (Percona Server)" if test -x $bindir/mysqld_safe then # Give extra arguments to mysqld with the my.cnf file. This script @@ -291,12 +291,12 @@ case "$mode" in if (kill -0 $mysqld_pid 2>/dev/null) then - echo $echo_n "Shutting down MySQL" + echo $echo_n "Shutting down MySQL (Percona Server)" kill $mysqld_pid # mysqld should remove the pid file when it exits, so wait for it. wait_for_pid removed "$mysqld_pid" "$mysqld_pid_file_path"; return_value=$? else - log_failure_msg "MySQL server process #$mysqld_pid is not running!" + log_failure_msg "MySQL (Percona Server) server process #$mysqld_pid is not running!" rm "$mysqld_pid_file_path" fi @@ -307,7 +307,7 @@ case "$mode" in fi exit $return_value else - log_failure_msg "MySQL server PID file could not be found!" + log_failure_msg "MySQL (Percona Server) PID file could not be found!" fi ;; @@ -325,10 +325,10 @@ case "$mode" in 'reload'|'force-reload') if test -s "$mysqld_pid_file_path" ; then read mysqld_pid < "$mysqld_pid_file_path" - kill -HUP $mysqld_pid && log_success_msg "Reloading service MySQL" + kill -HUP $mysqld_pid && log_success_msg "Reloading service MySQL (Percona Server)" touch "$mysqld_pid_file_path" else - log_failure_msg "MySQL PID file could not be found!" + log_failure_msg "MySQL (Percona Server) PID file could not be found!" exit 1 fi ;; @@ -337,10 +337,10 @@ case "$mode" in if test -s "$mysqld_pid_file_path" ; then read mysqld_pid < "$mysqld_pid_file_path" if kill -0 $mysqld_pid 2>/dev/null ; then - log_success_msg "MySQL running ($mysqld_pid)" + log_success_msg "MySQL (Percona Server) running ($mysqld_pid)" exit 0 else - log_failure_msg "MySQL is not running, but PID file exists" + log_failure_msg "MySQL (Percona Server) is not running, but PID file exists" exit 1 fi else @@ -354,13 +354,13 @@ case "$mode" in exit 5 elif test -z $mysqld_pid ; then if test -f "$lock_file_path" ; then - log_failure_msg "MySQL is not running, but lock file ($lock_file_path) exists" + log_failure_msg "MySQL (Percona Server) is not running, but lock file ($lock_file_path) exists" exit 2 fi - log_failure_msg "MySQL is not running" + log_failure_msg "MySQL (Percona Server) is not running" exit 3 else - log_failure_msg "MySQL is running but PID file could not be found" + log_failure_msg "MySQL (Percona Server) is running but PID file could not be found" exit 4 fi fi @@ -368,7 +368,7 @@ case "$mode" in *) # usage basename=`basename "$0"` - echo "Usage: $basename {start|stop|restart|reload|force-reload|status} [ MySQL server options ]" + echo "Usage: $basename {start|stop|restart|reload|force-reload|status} [ MySQL (Percona Server) options ]" exit 1 ;; esac diff --git a/testclients/bug25714.cc b/testclients/bug25714.cc index 923156ce78c5..40fa671f1979 100644 --- a/testclients/bug25714.cc +++ b/testclients/bug25714.cc @@ -69,5 +69,5 @@ int main(int argc, char **argv) { mysql_close(&conn); my_end(0); - return 0; + return OK; } diff --git a/testclients/mysql_client_test.cc b/testclients/mysql_client_test.cc index cc51968f0bef..f94309d22c91 100644 --- a/testclients/mysql_client_test.cc +++ b/testclients/mysql_client_test.cc @@ -4409,6 +4409,8 @@ static void test_field_flags() { fprintf(stdout, "\n MULTIPLE_KEY_FLAG"); if (field->flags & AUTO_INCREMENT_FLAG) fprintf(stdout, "\n AUTO_INCREMENT_FLAG"); + if (field->flags & CLUSTERING_FLAG) + fprintf(stdout, "\n CLUSTERING_FLAG"); } } mysql_free_result(result); diff --git a/utilities/innochecksum.cc b/utilities/innochecksum.cc index d01112d3c2e5..f8537a60243d 100644 --- a/utilities/innochecksum.cc +++ b/utilities/innochecksum.cc @@ -61,6 +61,7 @@ The parts not included are excluded by #ifndef UNIV_INNOCHECKSUM. */ #include "storage/innobase/include/buf0checksum.h" +#include "storage/innobase/include/dict0mem.h" /* DICT_TF_HAS_ATOMIC_BLOBS */ #include "storage/innobase/include/fil0types.h" #include "storage/innobase/include/fsp0fsp.h" /* fsp_flags_get_page_size() & @@ -83,6 +84,7 @@ static uintmax_t end_page; static uintmax_t do_page; static bool use_end_page; static bool do_one_page; +static bool display_format; /* replaces declaration in srv0srv.c */ ulong srv_page_size; ulong srv_page_size_shift; @@ -1239,6 +1241,8 @@ static struct my_option innochecksum_options[] = { {"count", 'c', "Print the count of pages in the file and exits.", &just_count, &just_count, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr}, + {"format_info", 'f', "Display information about the file format and exit", + 0, 0, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr}, {"start_page", 's', "Start on this page number (0 based).", &start_page, &start_page, nullptr, GET_ULL, REQUIRED_ARG, 0, 0, ULLONG_MAX, nullptr, 1, nullptr}, @@ -1358,6 +1362,9 @@ extern "C" bool innochecksum_get_one_option(int optid, case 'l': is_log_enabled = true; break; + case 'f': + display_format = true; + break; case 'I': case '?': usage(); @@ -1382,6 +1389,67 @@ static bool get_options(int *argc, char ***argv) { return (false); } +/** +Extract the zip size from tablespace flags. +@param[in] flags tablespace flags +@return compressed page size of the file-per-table tablespace in bytes, or zero +if the table is not compressed. */ +MY_NODISCARD +static ulint fsp_flags_get_zip_size(ulint flags) noexcept { + ulint zip_size = 0; + const ulint ssize = FSP_FLAGS_GET_ZIP_SSIZE(flags); + + /* Convert from a 'log2 minus 9' to a page size in bytes. */ + if (ssize) { + zip_size = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize); + + ut_ad(zip_size <= UNIV_ZIP_SIZE_MAX); + } + + return (zip_size); +} + +static void display_format_info(const uchar *page) noexcept { + /* Read page type. Pre-5.1.7 InnoDB always have zero in FIL_PAGE_TYPE + for the first page, later versions initialize it to + FIL_PAGE_TYPE_FSP_HDR. */ + const ulint page_type = mach_read_from_2(page + FIL_PAGE_TYPE); + + /* Read FSP flags from the page header. */ + const ulint flags = + mach_read_from_4(page + FSP_HEADER_OFFSET + FSP_SPACE_FLAGS); + + if (!page_type) { + printf("Detected file format: Antelope (pre-5.1.7).\n"); + if (flags != 0) { + printf( + "But FSP_SPACE_FLAGS is non-zero: %lu. " + "Corrupted tablespace?\n", + flags); + } + } else if (page_type == FIL_PAGE_TYPE_FSP_HDR) { + const ulint zip_size = fsp_flags_get_zip_size(flags); + + if (!flags) { + printf( + "Detected file format: " + "Antelope (5.1.7 or newer).\n"); + } else if (DICT_TF_HAS_ATOMIC_BLOBS(flags)) { + printf("Detected file format: Barracuda "); + if (!zip_size) + printf("(not compressed).\n"); + else + printf("(compressed with KEY_BLOCK_SIZE=%lu).\n", zip_size); + } else + printf("Unknown file format flags: %lu\n", flags); + } else { + printf( + "Bogus FIL_PAGE_TYPE value: %lu. Cannot detect the " + "file format.\n", + page_type); + } +} + int main(int argc, char **argv) { /* our input file. */ FILE *fil_in = nullptr; @@ -1587,8 +1655,9 @@ int main(int argc, char **argv) { } } - /* seek to the necessary position */ - if (start_page) { + /* seek to the necessary position, ignore with -f as we only need to read + the first pace */ + if (start_page && !display_format) { if (!read_from_stdin) { /* If read is not from stdin, we can use fseeko() to position the file pointer to @@ -1684,6 +1753,12 @@ int main(int argc, char **argv) { return 1; } + if (display_format) { + /* for -f, analyze only the first page and exit */ + display_format_info(buf.begin()); + break; + } + if (is_system_tablespace) { /* enable when page is double write buffer.*/ skip_page = is_page_doublewritebuffer(buf.begin());