PluginProbe
SQLite Database Integration / 3.1.0
SQLite Database Integration v3.1.0
3.1.0 3.0.2 3.0.1 trunk 2.1.13 2.1.14 2.1.15 2.1.16 2.2.0 2.2.1 2.2.10 2.2.11 2.2.12 2.2.13 2.2.14 2.2.15 2.2.16 2.2.17 2.2.18 2.2.19 2.2.2 2.2.20 2.2.21 2.2.22 2.2.23 All 33 releases
← All changes | wp-includes/database/mysql/class-wp-mysql-lexer.php +23 -17 3.0.1 → 3.1.0 View file →
@@ -41,9 +41,9 @@
41 41 *
42 42 * These are intended to be used with "strspn()" and "strcspn()" functions
43 43 * for fast character class matching in the SQL payload.
44 44 */
45 - const WHITESPACE_MASK = " \t\n\r\f";
45 + const WHITESPACE_MASK = " \t\n\r\f\v";
46 46 const DIGIT_MASK = '0123456789';
47 47 const HEX_DIGIT_MASK = '0123456789abcdefABCDEF';
48 48
49 49 /**
@@ -2992,24 +2992,29 @@
2992 2992
2993 2993 private function read_mysql_comment(): int {
2994 2994 // @TODO: Consider supporting optimizer hints (/*+ ... */) or document
2995 2995 // that they are not supported.
2996 - // @TODO: Implement six-digit version number support (from MySQL 8.4).
2997 2996
2998 - // MySQL-specific comment in one of the following forms:
2999 - // 1. /*! ... */ - The content is treated as SQL.
3000 - // 2. /*!12345 ... */ - The content is treated as SQL when "MySQL version >= 12345".
2997 + // MySQL-specific comments in the following forms:
2998 + // 1. /*! ... */ - The content is treated as SQL.
2999 + // 2. /*!80400 ... */ - SQL when the server version is at least 8.4.0.
3000 + // 3. /*!080400 ... */ - The same version in six-digit form (MySQL 8.1+).
3001 + //
3002 + // See: https://dev.mysql.com/doc/refman/8.4/en/comments.html
3001 3003 $this->bytes_already_read += 3; // Consume the '/*!'.
3002 3004
3003 - // Check if the next 5 characters are digits.
3004 - $digit_count = strspn( $this->sql, self::DIGIT_MASK, $this->bytes_already_read, 5 );
3005 - $is_version_comment = 5 === $digit_count;
3005 + // Version has 5 digits (Mmmrr) or 6 digits (MMmmrr + whitespace, MySQL 8.1+).
3006 + $digit_count = strspn( $this->sql, self::DIGIT_MASK, $this->bytes_already_read, 6 );
3007 + $version_length = $digit_count < 5 ? 0 : 5;
3008 + if (
3009 + 6 === $digit_count
3010 + && $this->mysql_version >= 80100
3011 + && 1 === strspn( $this->sql, self::WHITESPACE_MASK, $this->bytes_already_read + 6, 1 )
3012 + ) {
3013 + $version_length = 6;
3014 + }
3015 + $version = (int) substr( $this->sql, $this->bytes_already_read, $version_length );
3006 3016
3007 - // For version comments, extract the version number.
3008 - $version = $is_version_comment
3009 - ? (int) substr( $this->sql, $this->bytes_already_read, $digit_count )
3010 - : 0;
3011 -
3012 3017 if ( $this->mysql_version < $version ) {
3013 3018 // Version not satisfied. Treat the content as a regular comment.
3014 3019 $this->read_comment_content();
3015 3020 return self::COMMENT;
@@ -3014,9 +3019,9 @@
3014 3019 $this->read_comment_content();
3015 3020 return self::COMMENT;
3016 3021 } else {
3017 3022 // Version satisfied or not specified. Treat the content as SQL code.
3018 - $this->bytes_already_read += $digit_count; // Skip the version number.
3023 + $this->bytes_already_read += $version_length; // Skip the version number.
3019 3024 $this->in_mysql_comment = true;
3020 3025 return self::MYSQL_COMMENT_START;
3021 3026 }
3022 3027 }
@@ -3077,13 +3082,14 @@
3077 3082 }
3078 3083
3079 3084 // Determine function calls.
3080 3085 if ( isset( self::FUNCTIONS[ $type ] ) ) {
3081 - // Skip any whitespace character if the SQL mode says they should be ignored.
3086 + // Keep ignored whitespace outside the current token range.
3087 + $peek = $this->bytes_already_read;
3082 3088 if ( $this->is_sql_mode_active( self::SQL_MODE_IGNORE_SPACE ) ) {
3083 - $this->bytes_already_read += strspn( $this->sql, self::WHITESPACE_MASK, $this->bytes_already_read );
3089 + $peek += strspn( $this->sql, self::WHITESPACE_MASK, $peek );
3084 3090 }
3085 - if ( '(' !== ( $this->sql[ $this->bytes_already_read ] ?? null ) ) {
3091 + if ( '(' !== ( $this->sql[ $peek ] ?? null ) ) {
3086 3092 return self::IDENTIFIER;
3087 3093 }
3088 3094 }
3089 3095