1. 20 Jul, 2023 5 commits
    • Daniel Black's avatar
      MDEV-31625 connect engine file_type=DBF insert fails · 5a44700a
      Daniel Black authored
      Add the end of file marker x1A to the DBF file and handle it
      correctly to preserve interoperability with Libreoffice, and others
      that have followed the DBF spec.
      
      The file open mode of "a+" was problematic because Linux and the OSX,
      the previous main development mode are inconsistent (see man fopen).
      The main problem per the bug report was the inability to fseek back to the
      beginning to update the records in the header.
      
      As such the "a+" mode is remove and "w+b" is used inserting to a new file
      and "r+b" is used for appending to the file.
      
      In DBFFAM::CloseTableFile move PlugCloseFile down to close the file in
      all modes.
      
      The year unlike the comments is always since 1900. Use the
      YYYY-MM-DD as an unabigious form during tracing.
      
      Thanks for Mr. Zoltan Duna for the descriptive bug report.
      5a44700a
    • Oleksandr Byelkin's avatar
      MDEV-25237 crash after setting global session_track_system_variables to an invalid value · cf50379b
      Oleksandr Byelkin authored
      Fix of typo in checking variable list corectness.
      
      Fix of error handling in case of variable list parse error
      cf50379b
    • Alexander Barkov's avatar
      MDEV-28384 UBSAN: null pointer passed as argument 1, which is declared to... · 03c2157d
      Alexander Barkov authored
      MDEV-28384 UBSAN: null pointer passed as argument 1, which is declared to never be null in my_strnncoll_binary on SELECT ... COUNT or GROUP_CONCAT
      
      Also fixes:
        MDEV-30982 UBSAN: runtime error: null pointer passed as argument 2, which is declared to never be null in my_strnncoll_binary on DELETE
      
      Calling memcmp() with a NULL pointer is undefined behaviour
      according to the C standard, even if the length argument is 0.
      
      Adding tests for length==0 before calling memcmp() into:
      - my_strnncoll_binary()
      - my_strnncoll_8bit_bin
      03c2157d
    • Alexander Barkov's avatar
      MDEV-22856 Assertion `!str || str != Ptr' and Assertion `!str || str != Ptr ||... · a79f4f6e
      Alexander Barkov authored
      MDEV-22856 Assertion `!str || str != Ptr' and Assertion `!str || str != Ptr || !is_alloced()' failed in String::copy
      
      The problem was earlier fixed by MDEV-26953.
      Adding MTR tests only.
      a79f4f6e
    • Daniel Black's avatar
      MDEV-23133 session tracker - warning message typo · d067de20
      Daniel Black authored
      Concatenation error leads to typo in the warning message
      d067de20
  2. 19 Jul, 2023 3 commits
    • Alexander Barkov's avatar
      MDEV-29019 Assertion `(length % 4) == 0' failed in my_lengthsp_utf32 on SELECT · 30f3db3c
      Alexander Barkov authored
      Problem:
      
      Item_func_conv::val_str() copied the ASCII string with the numeric base
      conversion result directly to the function result string. In case of a
      tricky character set (e.g. utf32) it produced an illformed string.
      
      Fix:
      
      Copy the base conversion result to the function result as is only if
      the function character set is ASCII compatible, go through a
      character set conversion otherwise.
      30f3db3c
    • Alexander Barkov's avatar
      MDEV-23838 Possibly wrong result or Assertion `0' failed in Item_func_round::native_op · 9e5c1fb5
      Alexander Barkov authored
      Change history in the affected code:
      
      - Since 10.4.8 (MDEV-20397 and MDEV-23311), functions ROUND(), CEILING(),
        FLOOR() return a TIME value for a TIME input.
      - Since 10.4.14 (MDEV-23525), MIN() and MAX() calculate a result for a TIME
        input using val_native() rather than val_str().
      
      Problem:
      
      The patch for MDEV-23525 did not take into account combinations like
      MIN(ROUND(time)), MAX(FLOOR(time)), etc.
      
      MIN() and MAX() with ROUND(time), CEILING(time), FLOOR(time) as an argument
      call the method val_native() of the undelying classes Item_func_round and
      Item_func_int_val. However these classes implemented the method val_native()
      as DBUG_ASSERT(0).
      
      Fix:
      
      This patch adds a TIME-specific code inside:
      - Item_func_round::val_native()
      - Item_func_int_val::val_native()
      still with DBUG_ASSERT(0) for all other data types,
      as other data types do not call val_native() of these classes.
      
      We'll need a more generic solition eventualy, e.g.
      turn Item_func_round and Item_func_int_val into Item_handled_func.
      However, this change would be too risky for 10.4 at this point.
      9e5c1fb5
    • Daniel Black's avatar
      MDEV-31545 GCC 13 -Wdangling-pointer in execute_show_status() · fbc157ab
      Daniel Black authored
      The pointer was used deep in the call path.
      
      Resolve this by setting the pointer to NULL at the end of
      the function.
      
      Tested with gcc-13.3.1 (fc38)
      
      The warning disable 38fe266e can be reverted in 10.6+ on merge.
      fbc157ab
  3. 14 Jul, 2023 2 commits
  4. 13 Jul, 2023 1 commit
    • Yuchen Pei's avatar
      MDEV-31524 Fixing spider table param / variable overriding · e1d31a10
      Yuchen Pei authored
      The existing (incorrect) overriding mechanism is:
      
      Non-minus-one var value overrides table param overrides default value.
      
      Before MDEV-27169, unspecified var value is -1. So if the user sets
      both the var to be a value other than -1 and the table param, the var
      value will prevail, which is incorrect.
      
      After MDEV-27169, unspecified var value is default value. So if the
      user does not set the var but sets the table param, the default value
      will prevail, which is even more incorrect.
      
      This patch fixes it so that table param, if specified, always
      overrides var value, and the latter if not specified or set to -1,
      falls back to the default value
      
      We achieve this by replacing all such overriding in spd_param.cc with
      macros that override in the correct way, and removing all the
      "overriding -1" lines involving table params in
      spider_set_connect_info_default() except for those table params not
      defined as sysvar/thdvar in spd_params.cc
      
      We also introduced macros for non-overriding sysvar and thdvar, so
      that the code is cleaner and less error-prone
      
      In server versions where MDEV-27169 has not been applied, we also
      backport the patch, that is, replacing -1 default values with real
      default values
      
      In server versions where MDEV-28006 has not been applied, we do the
      same for udf params
      e1d31a10
  5. 12 Jul, 2023 8 commits
  6. 11 Jul, 2023 1 commit
    • Daniel Black's avatar
      MDEV-27038 Custom configuration file procedure does not work with Docker Desktop for Windows 10+ · 23d53913
      Daniel Black authored
      Docker when mounting a configuration file into a Windows exposes the
      file with permission 0777. These world writable files are ignored by
      by MariaDB.
      
      Add the access check such that filesystem RO or immutable file is
      counted as sufficient protection on the file.
      
      Test:
      $ mkdir /tmp/src
      $ vi /tmp/src/my.cnf
      $ chmod 666 /tmp/src/my.cnf
      $ mkdir /tmp/dst
      $ sudo mount --bind /tmp/src /tmp/dst -o ro
      $ ls -la /tmp/dst
      total 4
      drwxr-xr-x.  2 dan  dan   60 Jun 15 15:12 .
      drwxrwxrwt. 25 root root 660 Jun 15 15:13 ..
      -rw-rw-rw-.  1 dan  dan   10 Jun 15 15:12 my.cnf
      $ mount | grep dst
      tmpfs on /tmp/dst type tmpfs (ro,seclabel,nr_inodes=1048576,inode64)
      
      strace client/mariadb --defaults-file=/tmp/dst/my.cnf
      
      newfstatat(AT_FDCWD, "/tmp/dst/my.cnf", {st_mode=S_IFREG|0666, st_size=10, ...}, 0) = 0
      access("/tmp/dst/my.cnf", W_OK)         = -1 EROFS (Read-only file system)
      openat(AT_FDCWD, "/tmp/dst/my.cnf", O_RDONLY|O_CLOEXEC) = 3
      
      The one failing test, but this isn't a regression, just not a total fix:
      
      $ chmod u-w /tmp/src/my.cnf
      $ ls -la /tmp/src/my.cnf
      -r--rw-rw-. 1 dan dan 18 Jun 16 10:22 /tmp/src/my.cnf
      $ strace -fe trace=access client/mariadb --defaults-file=/tmp/dst/my.cnf
      access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
      access("/etc/system-fips", F_OK)        = -1 ENOENT (No such file or directory)
      access("/tmp/dst/my.cnf", W_OK)         = -1 EACCES (Permission denied)
      Warning: World-writable config file '/tmp/dst/my.cnf' is ignored
      
      Windows test (Docker Desktop ~4.21) which was the important one to fix:
      
      dan@LAPTOP-5B5P7RCK:~$ docker run --rm  -v /mnt/c/Users/danie/Desktop/conf:/etc/mysql/conf.d/:ro -e MARIADB_ROOT_PASSWORD=bob quay.io/m
      ariadb-foundation/mariadb-devel:10.4-MDEV-27038-ro-mounts-pkgtest ls -la /etc/mysql/conf.d
      total 4
      drwxrwxrwx 1 root root  512 Jun 15 13:57 .
      drwxr-xr-x 4 root root 4096 Jun 15 07:32 ..
      -rwxrwxrwx 1 root root   43 Jun 15 13:56 myapp.cnf
      
      root@a59b38b45af1:/# strace -fe trace=access mariadb
      access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
      access("/etc/mysql/conf.d/myapp.cnf", W_OK) = -1 EROFS (Read-only file system)
      23d53913
  7. 10 Jul, 2023 2 commits
    • Monty's avatar
      MDEV-20010 Equal on two RANK window functions create wrong result · 7a5c984f
      Monty authored
      The problematic query outlined a bug in window functions sorting
      optimization. When multiple window functions are present in a query,
      we sort the sorting key (as defined by PARTITION BY and ORDER BY) from
      generic to specific.
      
      SELECT RANK() OVER (ORDER BY const_col) as r1,
             RANK() OVER (ORDER BY const_col, a) as r2,
             RANK() OVER (PARTITION BY c) as r3,
             RANK() OVER (PARTITION BY c ORDER BY b) as r4
      FROM table;
      
      For these functions, the sorting we need to do for window function
      computations are: [(const_col), (const_col, a)] and [(c), (c, b)].
      
      Instead of doing 4 different sort order, the sorts grouped within [] are
      compatible and we can use the most *specific* sort to cover both window
      functions.
      
      The bug was caused by an incorrect flagging of which sort is most
      specific for a compatible group of functions. In our specific test case,
      instead of picking (const_col, a) as the most specific sort, it would
      only sort by (const_col), which lead to wrong results for rank function.
      By ensuring that we pick the last sort key before an "incompatible sort"
      flag is met in our "ordered array of sorting specifications", we
      guarantee correct results.
      7a5c984f
    • Marko Mäkelä's avatar
      MDEV-31641 innochecksum dies with Floating point exception · 12a5fb4b
      Marko Mäkelä authored
      print_summary(): Skip index_ids for which index.pages is 0.
      Tablespaces may contain some freed pages that used to refer to indexes
      or tables that were dropped.
      12a5fb4b
  8. 07 Jul, 2023 3 commits
    • Lawrin Novitsky's avatar
      MDEV-31064 Changes in a SP are not immediately seen in I_S.parameters · 02cd3675
      Lawrin Novitsky authored
      If procedure is changed in one connection, and other procedure has
      already called the initial version of the procedure, the query to
      INFORMATION_SCHEMA.PARAMETERS would use obsolete information from sp
      cache for that connection. That happens because cache invalidating
      method only increments cache version, and does not flush (all) the
      cache(s), and changing of a procedure only invalidates cache, and
      removes the procedure's cache entry from local thread cache only.
      
      The fix adds the check if sp info obtained from the cache for forming of
      results for the query to I_S, is not obsoleted, and does not use it, if
      it is.
      
      The test has been added to main.information_schema. It changes the SP in
      one connection, and ensures, that the change is seen in the query to the
      I_S.PARAMETERS in other connection, that already has called the
      procedure before the change.
      02cd3675
    • Yury Chaikou's avatar
      MDEV-24712 get_partition_set is never executed in... · 8fb863e6
      Yury Chaikou authored
      MDEV-24712 get_partition_set is never executed in ha_partition::multi_range_key_create_key due to bitwise & with 0 constant
      
      use == to compare enum (despite the name it is not a bit flag)
      8fb863e6
    • Oleg Smirnov's avatar
      MDEV-29284 ANALYZE doesn't work with pushed derived tables · 94a8921e
      Oleg Smirnov authored
      There was no actual execution of the SQL of a pushed derived table,
      which caused "r_rows" to be always displayed as 0 and "r_total_time_ms"
      to show inaccurate numbers.
      This commit makes a derived table SQL to be executed by the storage
      engine, so the server is able to calculate the number of rows returned
      and measure the execution time more accurately
      94a8921e
  9. 06 Jul, 2023 2 commits
    • Vlad Lesin's avatar
      MDEV-10962 Deadlock with 3 concurrent DELETEs by unique key · 1bfd3cc4
      Vlad Lesin authored
      PROBLEM:
      A deadlock was possible when a transaction tried to "upgrade" an already
      held Record Lock to Next Key Lock.
      
      SOLUTION:
      This patch is based on observations that:
      (1) a Next Key Lock is equivalent to Record Lock combined with Gap Lock
      (2) a GAP Lock never has to wait for any other lock
      In case we request a Next Key Lock, we check if we already own a Record
      Lock of equal or stronger mode, and if so, then we change the requested
      lock type to GAP Lock, which we either already have, or can be granted
      immediately, as GAP locks don't conflict with any other lock types.
      (We don't consider Insert Intention Locks a Gap Lock in above statements).
      
      The reason of why we don't upgrage Record Lock to Next Key Lock is the
      following.
      
      Imagine a transaction which does something like this:
      
      for each row {
          request lock in LOCK_X|LOCK_REC_NOT_GAP mode
          request lock in LOCK_S mode
      }
      
      If we upgraded lock from Record Lock to Next Key lock, there would be
      created only two lock_t structs for each page, one for
      LOCK_X|LOCK_REC_NOT_GAP mode and one for LOCK_S mode, and then used
      their bitmaps to mark all records from the same page.
      
      The situation would look like this:
      
      request lock in LOCK_X|LOCK_REC_NOT_GAP mode on row 1:
      // -> creates new lock_t for LOCK_X|LOCK_REC_NOT_GAP mode and sets bit for
      // 1
      request lock in LOCK_S mode on row 1:
      // -> notices that we already have LOCK_X|LOCK_REC_NOT_GAP on the row 1,
      // so it upgrades it to X
      request lock in LOCK_X|LOCK_REC_NOT_GAP mode on row 2:
      // -> creates a new lock_t for LOCK_X|LOCK_REC_NOT_GAP mode (because we
      // don't have any after we've upgraded!) and sets bit for 2
      request lock in LOCK_S mode on row 2:
      // -> notices that we already have LOCK_X|LOCK_REC_NOT_GAP on the row 2,
      // so it upgrades it to X
          ...etc...etc..
      
      Each iteration of the loop creates a new lock_t struct, and in the end we
      have a lot (one for each record!) of LOCK_X locks, each with single bit
      set in the bitmap. Soon we run out of space for lock_t structs.
      
      If we create LOCK_GAP instead of lock upgrading, the above scenario works
      like the following:
      
      // -> creates new lock_t for LOCK_X|LOCK_REC_NOT_GAP mode and sets bit for
      // 1
      request lock in LOCK_S mode on row 1:
      // -> notices that we already have LOCK_X|LOCK_REC_NOT_GAP on the row 1,
      // so it creates LOCK_S|LOCK_GAP only and sets bit for 1
      request lock in LOCK_X|LOCK_REC_NOT_GAP mode on row 2:
      // -> reuses the lock_t for LOCK_X|LOCK_REC_NOT_GAP by setting bit for 2
      request lock in LOCK_S mode on row 2:
      // -> notices that we already have LOCK_X|LOCK_REC_NOT_GAP on the row 2,
      // so it reuses LOCK_S|LOCK_GAP setting bit for 2
      
      In the end we have just two locks per page, one for each mode:
      LOCK_X|LOCK_REC_NOT_GAP and LOCK_S|LOCK_GAP.
      Another benefit of this solution is that it avoids not-entirely
      const-correct, (and otherwise looking risky) "upgrading".
      
      The fix was ported from
      mysql/mysql-server@bfba840dfa7794b988c59c94658920dbe556075d
      mysql/mysql-server@75cefdb1f73b8f8ac8e22b10dfb5073adbdfdfb0
      
      Reviewed by: Marko Mäkelä
      1bfd3cc4
    • Alexander Barkov's avatar
      A cleanup for MDEV-30932 UBSAN: negation of -X cannot be represented in type .. · 19cdddf1
      Alexander Barkov authored
      "mtr --view-protocol func_math" failed because of a too long
      column names imlicitly generated for the underlying expressions.
      
      With --view-protocol they were replaced to "Name_exp_1".
      
      Adding column aliases for these expressions.
      19cdddf1
  10. 05 Jul, 2023 1 commit
  11. 04 Jul, 2023 2 commits
  12. 03 Jul, 2023 7 commits
  13. 29 Jun, 2023 3 commits
    • Sergei Golubchik's avatar
    • Alexander Barkov's avatar
      MDEV-30932 UBSAN: negation of -X cannot be represented in type .. · 67657a01
      Alexander Barkov authored
        'long long int'; cast to an unsigned type to negate this value ..
        to itself in Item_func_mul::int_op and Item_func_round::int_op
      
      Problems:
      
        The code in multiple places in the following methods:
          - Item_func_mul::int_op()
          - longlong Item_func_int_div::val_int()
          - Item_func_mod::int_op()
          - Item_func_round::int_op()
      
        did not properly check for corner values LONGLONG_MIN
        and (LONGLONG_MAX+1) before doing negation.
        This cuased UBSAN to complain about undefined behaviour.
      
      Fix summary:
      
        - Adding helper classes ULonglong, ULonglong_null, ULonglong_hybrid
          (in addition to their signed couterparts in sql/sql_type_int.h).
      
        - Moving the code performing multiplication of ulonglong numbers
          from Item_func_mul::int_op() to ULonglong_hybrid::ullmul().
      
        - Moving the code responsible for extracting absolute values
          from negative numbers to Longlong::abs().
          It makes sure to perform negation without undefinite behavior:
          LONGLONG_MIN is handled in a special way.
      
        - Moving negation related code to ULonglong::operator-().
          It makes sure to perform negation without undefinite behavior:
          (LONGLONG_MAX + 1) is handled in a special way.
      
        - Moving signed<=>unsigned conversion code to
          Longlong_hybrid::val_int() and ULonglong_hybrid::val_int().
      
        - Reusing old and new sql_type_int.h classes in multiple
          places in Item_func_xxx::int_op().
      
      Fix details (explain how sql_type_int.h classes are reused):
      
        - Instead of straight negation of negative "longlong" arguments
          *before* performing unsigned multiplication,
          Item_func_mul::int_op() now calls ULonglong_null::ullmul()
          using Longlong_hybrid_null::abs() to pass arguments.
          This fixes undefined behavior N1.
      
        - Instead of straight negation of "ulonglong" result
          *after* performing unsigned multiplication,
          Item_func_mul::int_op() now calls ULonglong_hybrid::val_int(),
          which recursively calls ULonglong::operator-().
          This fixes undefined behavior N2.
      
        - Removing duplicate negating code from Item_func_mod::int_op().
          Using ULonglong_hybrid::val_int() instead.
          This fixes undefinite behavior N3.
      
        - Removing literal "longlong" negation from Item_func_round::int_op().
          Using Longlong::abs() instead, which correctly handler LONGLONG_MIN.
          This fixes undefinite behavior N4.
      
        - Removing the duplicate (negation related) code from
          Item_func_int_div::val_int(). Reusing class ULonglong_hybrid.
          There were no undefinite behavior in here.
          However, this change allowed to reveal a bug in
          "-9223372036854775808 DIV 1".
          The removed negation code appeared to be incorrect when
          negating +9223372036854775808. It returned the "out of range" error.
          ULonglong_hybrid::operator-() now handles all values correctly
          and returns +9223372036854775808 as a negation for -9223372036854775808.
      
          Re-recording wrong results for
            SELECT -9223372036854775808 DIV  1;
          Now instead of "out of range", it returns -9223372036854775808,
          which is the smallest possible value for the expression data type
          (signed) BIGINT.
      
        - Removing "no UBSAN" branch from Item_func_splus::int_opt()
          and Item_func_minus::int_opt(), as it made UBSAN happy but
          in RelWithDebInfo some MTR tests started to fail.
      67657a01
    • Yuchen Pei's avatar