Skip to content
Snippets Groups Projects
  1. Dec 08, 2022
  2. Dec 07, 2022
    • Vladimir Davydov's avatar
      box: don't stop parsing authentication request if user doesn't exist · 995d2a00
      Vladimir Davydov authored
      Currently, we stop without checking the authentication request body if
      the specified user doesn't exist. As a result, one can check if a user
      exists by sending a malformed authentication request: for an existing
      user, the server will reply with ER_INVALID_MSGPACK error while if the
      user doesn't exist, the error will be set to ER_CREDS_MISMATCH. To fix
      this, let's parse the authentication request body even if the user
      doesn't exist.
      
      Closes https://github.com/tarantool/security/issues/21
      
      NO_DOC=bug fix
      
      (cherry picked from commit 42badb87)
      995d2a00
    • Vladimir Davydov's avatar
      box: run box.session.on_auth triggers if the user doesn't exist · e1a79d79
      Vladimir Davydov authored
      The triggers are supposed to run on any authentication attempt,
      successful or not. Without it, the admin may not notice a malefactor
      enumerating user names.
      
      Closes #8017
      
      NO_DOC=bug fix
      
      (cherry picked from commit 8a2f1653)
      e1a79d79
    • Vladimir Davydov's avatar
      box: drop redundant guest password checks from authenticate · 586b1ffb
      Vladimir Davydov authored
      The guest can't have a non-empty password - it's explicitly prevented by
      the _user trigger callback:
      
      https://github.com/tarantool/tarantool/blob/2ed06651c317f2d46631b0d55e4b88f2c8a6c0a0/src/box/alter.cc#L2930-L2936
      
      So there's no need to check the guest user password in authenticate.
      
      NO_DOC=code cleanup
      NO_TEST=code cleanup
      NO_CHANGELOG=code cleanup
      
      (cherry picked from commit 26f69561)
      586b1ffb
    • Ilya Verbin's avatar
      log: improve logging of tables · 9e986ee9
      Ilya Verbin authored
      1. Fixed modification of a variable passed to the logging function
         (both log formats)
      
         tarantool> a = {foo = 'bar', file = 'c://autorun.bat'}
         tarantool> log.info(a)
         [...]
         tarantool> a
         (before) - foo: bar
          (after) - foo: bar
                    file: c://autorun.bat
      
      2. Fixed the drop of fields with reserved internal names (plain log format)
      
         tarantool> log.info({foo = 'bar', pid = 666})
         (before) {"foo":"bar"}
          (after) {"foo":"bar","pid":666}
      
      3. Now if 'message' field is absent, it is set to the first field of the
         table (JSON log format)
      
         tarantool> log.info({'Hello, world', key = 'value'})
         (before) {[...], "1":"Hello, world", "key":"value", [...]}
          (after) {[...], "message":"Hello, world", "key":"value", [...]}
      
      4. Fixed assertion on a table without string keys (JSON log format)
      
         If a Lua table, passed to say(), contains only integer indexes,
         json.encode() will encode it as an array rather than a map, thereafter
         say_format_json() will produce improperly formatted JSON string, or get
         assertion failure. Fix it by encoding all kinds of tables as maps.
      
      Closes #3853
      Closes #7955
      
      NO_DOC=Mostly bug fixes, the format of the JSON log is not documented.
      
      (cherry picked from commit 85ef1118)
      9e986ee9
    • Ilya Verbin's avatar
      test: fix flaky gh_6539_log_user_space_empty_or_nil_select_test · 81c021c3
      Ilya Verbin authored
      Turn LuaJIT off for this test on AArch64 in the scope of the issue [1].
      
      Also increase grep_log_bytes. Currently the message is 235 byte long,
      which is pretty close to 256. If one more item is added to the traceback,
      the test will fail.
      
      ```
      C> Potentially long select from space 'test_memtx' (512)
       stack traceback:
              builtin/box/schema.lua:2528: in function 'check_select_safety'
              builtin/box/schema.lua:2545: in function 'select'
              eval:1: in main chunk
              [C]: at 0x556e8ffd5c
      ```
      
      [1] Related to #8011
      Closes tarantool/tarantool-qa#264
      
      NO_DOC=test fix
      NO_CHANGELOG=test fix
      
      (cherry picked from commit 84306671)
      81c021c3
    • Igor Munkin's avatar
      luajit: bump new version · 38717877
      Igor Munkin authored
      * Fix narrowing of unary minus.
      * Don't compile math.modf() anymore.
      * OSX/ARM64: Fix external unwinding.
      * Fix build with busybox grep.
      * BSD: Fix build with BSD grep.
      * OSX/ARM64: Disable unwind info.
      * ARM64: Reorder interpreter stack frame and fix unwinding.
      * OSX/ARM64: Disable external unwinding for now.
      * OSX: Fix build by hardcoding external frame unwinding.
      * Cleanup and enable external unwinding for more platforms.
      * test: remove TAP side effects in getmetrics tests
      * test: relax JIT setup in misc.getmetrics test
      * test: relax JIT setup in lj-430-maxirconst test
      * GC64: enable sysprof support
      
      Closes #6096
      Closes #6976
      Closes #7919
      Relates to #781
      Relates to #7762
      Part of #7230
      
      NO_DOC=LuaJIT submodule bump
      NO_TEST=LuaJIT submodule bump
      38717877
  3. Dec 06, 2022
  4. Dec 05, 2022
    • Yaroslav Lobankov's avatar
      test: use luatest modules instead of internal ones · c7b4118f
      Yaroslav Lobankov authored
      Some internal modules have been recently copied to luatest repo [1,2]
      and now they can be safely removed, and the corresponding functionality
      from luatest can be used instead.
      
      Affected modules:
      
      - test/luatest_helpers/server.lua
      
      [1] tarantool/luatest#258
      [2] tarantool/luatest#266
      
      Closes tarantool/luatest#239
      
      NO_DOC=testing stuff
      NO_TEST=testing stuff
      NO_CHANGELOG=testing stuff
      
      (cherry picked from commit 21fc0770)
      c7b4118f
    • Yaroslav Lobankov's avatar
      test: bump test-run to version w/ updated luatest · 52b8e01a
      Yaroslav Lobankov authored
      Bump test-run to new version with the following improvements:
      
      - Bump luatest to 0.5.7-17-g1387aa8 [1]
      
      [1] tarantool/test-run#360
      
      Part of tarantool/luatest#239
      
      NO_DOC=testing stuff
      NO_TEST=testing stuff
      NO_CHANGELOG=testing stuff
      
      (cherry picked from commit 9687656f)
      52b8e01a
    • Vladislav Shpilevoy's avatar
      test: factor wal play until "synchro busy" out · eb672b4a
      Vladislav Shpilevoy authored
      The function play_wal_until_synchro_queue_is_busy() was used in a
      few tests copy-pasted since it was considered to be too specific
      for a few rare tests. But apparently it is going to be used again
      in a new test in a future commit.
      
      The patch makes this function a method of server object to reuse
      it properly.
      
      Needed for #7253
      
      NO_DOC=refactoring
      NO_CHANGELOG=refactoring
      
      (cherry picked from commit 135fd0ff)
      eb672b4a
    • Ilya Verbin's avatar
      cmake: fix wrong CPU architecture reported on M1/M2 Macs · 106b856a
      Ilya Verbin authored
      This patch removes an old CMake kludge, which sets CMAKE_SYSTEM_PROCESSOR
      to "x86_64" on all 64-bit architectures, even on ARM (on Darwin).
      
      Closes #7495
      
      NO_DOC=bugfix
      
      (cherry picked from commit d76be7ef)
      106b856a
  5. Dec 02, 2022
    • Ilya Verbin's avatar
      backtrace: update sp before saving registers to a stack frame · ee1a94e3
      Ilya Verbin authored
      backtrace_collect() is suffering from the same issue as coro_transfer(),
      see commit 215630e6 ("coro: update sp before saving registers to a
      stack frame").
      
      It stores x19-x30 and d8-d15 registers to the stack, but only after that
      it updates the stack pointer. If a SIGALRM signal is delivered during
      the execution of backtrace_collect, the signal handler will use the
      stack starting from current sp, thus corrupting the saved registers.
      
      Fix this by updating the stack pointer at the beginning of
      backtrace_collect. The constraint of the input operand `bt` is changed
      from "m" to "r" to force `bt` always be passed to the inline assembly
      via the register. Passing on stack will not work after this fix.
      
      Closes #7985
      
      NO_DOC=bugfix
      NO_TEST=Hard to create a stable reproducer
      
      (cherry picked from commit 9adc4aa7)
      ee1a94e3
  6. Nov 30, 2022
    • Georgiy Lebedev's avatar
      memtx: fix logic of read tracker rebinding during rollback · 8eaf7436
      Georgiy Lebedev authored
      During rollback read trackers are rebound to newer or older story, if
      present. The problem with the current logic is that read trackers are
      basically rebound in the first available index: all information about key
      parts read from other indexes gets lost — rebind read trackers in all
      indexes.
      
      Closes #7828
      
      NO_DOC=bugfix
      
      (cherry picked from commit 559b27db)
      8eaf7436
    • Georgiy Lebedev's avatar
      memtx: fix use-after-free of successor in `tree_iterator_start` · fb2da349
      Georgiy Lebedev authored
      We assumed that the successor tuple's story could not get garbage collected
      on clarify of result tuple in `tree_iterator_start`, since they coincide in
      case of regular iterators. But this is not the case for reverse iterators:
      the result tuple is of-by-one from the successor, which means the
      successor's story can get garbage collected along with the tuple itself
      getting deleted, leading to use-after-free of successor: remove garbage
      collection from `memtx_tx_tuple_clarify` and call it manually.
      
      The crash in #7756 revealed that the `put` in transaction manager's story
      hash table was performed incorrectly: fix it and add an assertion that
      nothing was replaced.
      
      Closes #7755
      Closes #7756
      
      NO_DOC=bugfix
      
      (cherry picked from commit 651535bc)
      fb2da349
  7. Nov 29, 2022
    • Andrey Saranchin's avatar
      replication: make before_replace work better with space _cluster · c05023cc
      Andrey Saranchin authored
      Firstly, there is an assertion that checks if replica_id haven't been
      changed after it's registration. Let's replace this assertion with warning
      message about id being altered - new id will be used for affected replica.
      
      Secondly, if before_replace trigger, set on space _cluster, returns nil,
      tarantool will crash with segmentation fault. This patch handles the case.
      
      Closes #7846
      
      NO_DOC=bugfix
      
      (cherry picked from commit a470bb63)
      c05023cc
  8. Nov 25, 2022
    • Ilya Verbin's avatar
      test: fix flaky gh_6539_log_user_space_empty_or_nil_select_test · d60ab9dd
      Ilya Verbin authored
      The test fails with:
      
        not ok 2 ...ty_or_nil_select.test_log_entry_presence_for_memtx_user_space
        gh_6539_log_user_space_empty_or_nil_select_test.lua:122: log must contain
        a critical entry about `box.space.test_memtx:select({0}, {limit = 1001,
        iterator = "ALL"})` call on a memtx user space
        expected: a value evaluating to true, actual: nil
      
      Looks like it happens, because g.server:grep_log() is executed before
      g.server:eval(call) completes writing to the log.
      In other tests grep_log() is wrapped into t.helpers.retrying() in order
      to avoid such issues, so do the same here.
      
      May close tarantool/tarantool-qa#264
      
      NO_DOC=test fix
      NO_CHANGELOG=test fix
      
      (cherry picked from commit e4f1c891)
      d60ab9dd
  9. Nov 23, 2022
    • Vladimir Davydov's avatar
      vinyl: fix tuple missing in cache after reading rolled backed DELETE · 9e9c06da
      Vladimir Davydov authored
      The read iterator skips DELETE statements. If a skipped DELETE statement
      was read from the transaction write set, the read iterator breaks the
      current cache chain by clearing vy_read_iterator::last_cached, because
      the deleted tuple may actually be present at a lower level so adding
      a gap there until the transaction is committed would be incorrect, see
      commit dd926790 ("vinyl: fix a bug in adding of a cache chain").
      
      The problem is vy_cache_add() assumes that if last_cached is NULL
      the tuple added to the cache must be the first tuple that meets the
      iteration criteria and sets the cache node boundary level accordingly.
      This may lead to the previous tuple being erroneously skipped later
      in case the transaction that attempted to delete it is rolled back.
      
      Fix this issue by passing the flag indicating if the current tuple is
      the first result of the iteration explicitly to vy_cache_add().
      
      Closes #7947
      
      NO_DOC=bug fix
      
      (cherry picked from commit e00f16e4)
      9e9c06da
    • Igor Munkin's avatar
      luajit: bump new version · 6006b1b9
      Igor Munkin authored
      * Ensure correct stack top for OOM error message.
      * x86/x64: Check for jcc when using xor r,r in emit_loadi().
      * Save trace recorder state around VM event call.
      * Fix io.close() error message.
      * Fix io.close().
      * Cleanup math function compilation and fix inconsistencies.
      
      Closes #3840
      Closes #6782
      Part of #7230
      
      NO_DOC=LuaJIT submodule bump
      NO_TEST=LuaJIT submodule bump
      6006b1b9
  10. Nov 22, 2022
    • Yan Shtunder's avatar
      replication: invalid recovery from xlog · 650e5a23
      Yan Shtunder authored
      If you shut down the replica and delete all xlog files on it, and it
      reconnect to the master, may occur the restore error. Because there are
      intermediate xlog files between the snap on the replica and the last
      xlog on the master. When restoring xlog files on the replica, it can be
      occurred that prev_signature < signature and this will lead to the crash
      of the master.
      
      Closes #5158
      
      NO_DOC=bugfix
      
      (cherry picked from commit f53fde16)
      650e5a23
    • Ilya Verbin's avatar
      box: inherit index collation from the space format · 7503bac2
      Ilya Verbin authored
      If create_index('...', {parts = {...}}) is called without the `collation`
      option, then use collation from the space format.
      
      Closes #5104
      
      @TarantoolBot document
      Title: Index options are inherited from the space format
      Root document: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/create_index/
      
      If `is_nullable` and `collation` options are not set, then they are
      inherited from the space format, if applicable for that field type.
      
      (cherry picked from commit f2f40ff7)
      7503bac2
  11. Nov 21, 2022
    • Serge Petrenko's avatar
      qsync: fix local writes failing on non-empty synchro queue · 1d70774c
      Serge Petrenko authored
      Local spaces can be written to on any replica, even on a read-only one.
      This makes sense, because local space data isn't replicated, so it can't
      lead to a conflict or violate consistency anyhow.
      
      However, when used together with synchronous replication, local spaces
      can't be written to by anyone but the synchro queue owner:
      ```
      tarantool> box.info.synchro.queue.len
      ---
      - 1
      ...
      tarantool> box.space.loc:replace{2}
      ---
      - error: Found uncommitted sync transactions from other instance with id 1
      ...
      ```
      Fix this and allow to put transactions touching local spaces to the
      synchro queue even if it is claimed by someone else.
      
      Note, we can't let local transactions bypass the synchro queue completely.
      This would lead to consistency loss in a case when synchro queue
      contains a transaction [sync_row, local_row], and another transcation
      [local_row], probably based on the sync transaction, bypasses the limbo.
      
      Closes #7592
      
      NO_DOC=bugfix
      
      (cherry picked from commit fb5a990f)
      1d70774c
  12. Nov 18, 2022
    • Ilya Verbin's avatar
      box: fix rollback of read-only transaction statements · cba6f917
      Ilya Verbin authored
      Existence of txn_commit_ro_stmt assumes there is txn_rollback_ro_stmt,
      but it does not exist. Instead, currently we use txn_rollback_stmt, which
      has nothing to do with 'ro' statements, and will just rollback the
      currently running normal statement.
      
      As an example, consider box_index_iterator. It calls txn_begin_ro_stmt,
      which does not produce any artefacts in an existing `struct txn`. But in
      case of the iterator creation fail it calls txn_rollback_stmt, which will
      rollback the currently being executed 'rw' statement.
      
      Drop txn_commit_ro_stmt and introduce txn_end_ro_stmt, which is called
      regardless of 'ro' statement result.
      
      NO_DOC=bugfix
      
      Closes #5501
      
      (cherry picked from commit d94eb857)
      cba6f917
  13. Nov 15, 2022
    • Ilya Verbin's avatar
      coro: update sp before saving registers to a stack frame · 9e0da2a4
      Ilya Verbin authored
      Currently AArch64 version of coro_transfer stores x19-x30 and d8-d15
      registers to the stack, but only after that it updates the stack pointer.
      If a SIGALRM signal is delivered during the execution of coro_transfer,
      the signal handler will use the stack starting from current sp, thus
      corrupting the saved registers.
      
      Fix this by updating the stack pointer at the beginning of coro_transfer.
      x2 register is still required, because `str sp, [x0, #0]` is invalid in
      the A64 instruction set.
      
      Closes #7484
      Closes #7523
      
      NO_DOC=bugfix
      NO_TEST=Hard to create a stable reproducer,
              mostly covered by existing tests.
      
      (cherry picked from commit 215630e6)
      9e0da2a4
  14. Nov 11, 2022
    • Vladimir Davydov's avatar
      test: fix flaky box-luatest/gh_7917_log_row_on_recovery_error_test · 02908e62
      Vladimir Davydov authored
      The test fails with:
      
        master | 2022-11-11 09:03:32.093 [4128822] main/103/default.lua F>
        can't initialize storage: unlink, called on fd 30, aka unix/:(socket),
        peer of unix/:(socket): Address already in use
      
      Looks like it happens, because both test cases share the socket path.
      The fix is the same as in commit 3f86cd04 ("test: fix flaky
      'test_ignore_with_force_recovery'") - use different socket paths.
      
      Follow-up commit b2dab5f4 ("memtx: log bad row on snapshot recovery
      error").
      
      NO_DOC=test fix
      NO_CHANGELOG=test fix
      
      (cherry picked from commit 3d3e9dea)
    • Kirill Yukhin's avatar
      Generate changelog for 2.10.4 · 816000e1
      Kirill Yukhin authored
      Generate changelog for 2.10.4 release.
      Also, clean changelogs/unreleased folder.
      
      NO_DOC=no code changes
      NO_TEST=no code changes
      NO_CHANGELOG=no code changes
    • Pavel Semyonov's avatar
      Proofread 2.10.4 CE changelog · 6dc50f73
      Pavel Semyonov authored
      Fix wording, punctuation, and formatting.
      
      NO_CHANGELOG=changelog
      NO_DOC=changelog
      NO_TEST=changelog
      6dc50f73
    • Igor Munkin's avatar
      luajit: bump new version · 72016243
      Igor Munkin authored
      * ci: add workflow for legacy CMake GNU Make build
      * build: fix build with the original Makefile
      * ci: drop integration for macOS with disabled GC64
      * ci: add 'self-hosted' tag to runs-on
      * ci: use Ninja generator in CI workflows
      * ci: use CMAKE_EXTRA_PARAMS in LuaJIT integration
      * test: replace result variable in MakeLuaPath.cmake
      * ci: merge Linux and macOS workflows
      * ci: merge x86_64 and ARM64 workflows
      * ci: remove arch prefix for macOS M1 workflow
      * ci: remove excess parallel level setup
      * ci: use out of source build in GitHub Actions
      * test: fix tarantool suite for out of source build
      * test: introduce MakeLuaPath.cmake helper
      * test: introduce utils.profilename helper
      
      NO_DOC=LuaJIT submodule bump
      NO_TEST=LuaJIT submodule bum
      NO_CHANGELOG=ci
      72016243
  15. Nov 10, 2022
  16. Nov 09, 2022
    • Georgiy Lebedev's avatar
      memtx: fix conflict handling of stories in secondary indexes · 4a28f0fb
      Georgiy Lebedev authored
      If we find a newer story in the secondary index, the statement of which
      deletes a story added in the same transaction, there can be two cases: if
      the secondary index is not unique, then it is conflicted by primary index
      (since it's `cmp_def` is extended with the primary index's
      `key_def`, every history chain in the secondary index has a corresponding
      chain in the primary index). Otherwise, the prepared story must also
      conflict the newer one.
      
      Summarizing the above: remove the unnecessary check.
      
      Closes #7761
      
      NO_DOC=bugfix
      
      (cherry picked from commit a1ba58d2)
      4a28f0fb
    • Georgiy Lebedev's avatar
      memtx: add assertion and test for gap tracker retention during rollback · 55f6a918
      Georgiy Lebedev authored
      Gap trackers are stored in the story at the top of the history chain (see
      `memtx_tx_story_{un}link_top_light`): following this logic, during rollback
      we need to rebind them to the older story. We already maintain this in
      56cf737c, since a story is not retained iff it has a newer story (which
      means it does not store trackers) or if it has an older story (in which
      case rebinding is done in `memtx_tx_story_{un}link_top_light`): add an
      assertion that a story deleted during rollback does not have any gap
      trackers and a test for this case.
      
      Follow-up 56cf737c
      
      NO_CHANGELOG=internal
      NO_DOC=internal
      
      (cherry picked from commit e0114464)
      55f6a918
    • Georgiy Lebedev's avatar
      memtx: split `memtx_tx_story_unlink_both` logic in two separate contexts · 5ee35e61
      Georgiy Lebedev authored
      `memtx_tx_story_unlink_both` is called in two separate contexts: on space
      delete and on rollback. In the former case we need to simply unlink the
      story, while in the latter case we need to rebind read and gap trackers,
      and, perhaps do some other logic in the future. Calling
      `memtx_tx_story_unlink_both` in the former context can trigger assertion:
      split the function and its helpers into two separate functions for each
      case, grouping the common logic into third `*_common` functions.
      
      Closes #7757
      
      NO_DOC=bugfix
      
      (cherry picked from commit 21d3af42)
      5ee35e61
  17. Nov 07, 2022
    • Georgiy Lebedev's avatar
      test: add test for replacement of absolute paths in diagnostics (#7808) · 7886e84b
      Georgiy Lebedev authored
      Since this feature is compiler-dependent, we need to skip the test if the
      server was build with a compiler that does not support the
      `-fmacro-prefix-map` flag.
      
      Follow-up #7808
      
      NO_CHANGELOG=test
      NO_DOC=test
      NO_TEST=test
      
      (cherry picked from commit ffb17a55)
      7886e84b
    • Georgiy Lebedev's avatar
      build: store compiler ID and version in `COMPILER_INFO` · 9dcd907b
      Georgiy Lebedev authored
      Currently, `tarantool.build.compiler` stores the `CMAKE_C_COMPILER` and
      `CMAKE_CXX_COMPILER` strings from CMake, which are basically paths to the
      compiler used for build, and are usually set to `/usr/bin/cc` and
      `/usr/bin/c++` accordingly, which does not yield any useful information:
      instead, set it to `${CMAKE_C_COMPILER_ID}-${CMAKE_C_COMPILER_VERSION}`,
      assuming the same compiler is used for building C and C++.
      
      Closes #7888
      
      @TarantoolBot document
      Title: change of information shown in compiler information
      Compiler information provided by `tarantool --version` and
      `tarantool.build.compiler` now show
      `${CMAKE_C_COMPILER_ID}-${CMAKE_C_COMPILER_VERSION}` instead of paths to C
      and C++ compilers used to build tarantool, for instance:
      
      ```console
      tarantool> tarantool.build.compiler
      
      ---
      - Clang-14.0.0.14000029
      ...
      
      tarantool> tarantool.build.compiler
      
      ---
      - GNU-12.2.0
      ...
      ```
      
      (cherry picked from commit aec0393e)
      9dcd907b
    • Georgiy Lebedev's avatar
      build: revert usage of relative paths in debugging information · e16e22dd
      Georgiy Lebedev authored
      The `-Wa,--debug-prefix-map` compiler flag breaks GNU-based LTO, and also
      we cannot reliably test this feature.
      
      Follow-up 256da010
      
      NO_CHANGELOG=bugfix
      NO_DOC=bugfix
      NO_TEST=bugfix
      
      (cherry picked from commit 41c7db41)
      e16e22dd
    • Mergen Imeev's avatar
      box: rework index_def_is_valid() · 056e26a1
      Mergen Imeev authored
      This patch renames index_def_is_valid() to index_def_check() and makes
      it return 0 or -1 because that function sets a diag.
      
      NO_DOC=refactoring
      NO_TEST=refactoring
      NO_CHANGELOG=refactoring
      
      (cherry picked from commit 5df76ade)
      056e26a1
    • Mergen Imeev's avatar
      sql: throw error on creation of too many indexes · 30ae8b1a
      Mergen Imeev authored
      Prior to this patch, there was no error of creating too many indexes in
      SQL. This led to a situation where indexes with IDs greater than
      BOX_INDEX_MAX were not created, but no error was thrown. For example, in
      the case of CREATE TABLE, only indexes with an ID less than
      BOX_INDEX_MAX were created. Now an error is thrown when creating too
      many indexes.
      
      Closes #5526
      
      NO_DOC=bugfix
      
      (cherry picked from commit 2705e227)
      30ae8b1a
Loading