Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-41570

EXPORT_SET() takes number_of_bits modulo 2^32 before clipping it to 64: EXPORT_SET(3,'foo','bar',',',4294967296) = ''

    XMLWordPrintable

Details

    Description

      EXPORT_SET(bits, on, off, separator, number_of_bits) clips number_of_bits to 64
      when it is larger than 64 – 65, 1000 and 2^64-1 all give 64 items – except
      when it is 2^32 or more, where it is first taken modulo 2^32:

      SELECT EXPORT_SET(3,'foo','bar',',',65);            -- 64 items  (correct, clipped)
      SELECT EXPORT_SET(3,'foo','bar',',',4);             -- 'foo,foo,bar,bar'
      SELECT EXPORT_SET(3,'foo','bar',',',4294967296);    -- ''               (2^32     -> 0 items)
      SELECT EXPORT_SET(3,'foo','bar',',',4294967300);    -- 'foo,foo,bar,bar' (2^32 + 4 -> 4 items)
      SELECT EXPORT_SET(3,'foo','bar',',',-4294967294);   -- 'foo,foo'        (-> 2 items)
      

      The MySQL manual documents the clip ("number_of_bits is silently clipped to 64 if
      larger than 64. It is treated as an unsigned integer, so a value of -1 is
      effectively the same as 64."), and MariaDB follows it for every other value,
      including 18446744073709551615 and -1. MySQL 26.10.0 returns 64 items for every
      call above except the 4-bit one.

      Where (main, 82964737): sql/item_strfunc.cc, Item_func_export_set::val_str(),
      lines 4311-4313:

          num_set_values = (uint) args[4]->val_int();
          if (num_set_values > 64)
            num_set_values=64;
      

      The (uint) cast happens before the comparison with 64.

      Not the same code path as MDEV-40971 / MDEV-40987 (JSON path indexes, PERIOD_ADD,
      SUBSTRING_INDEX, ELT): this is the number_of_bits argument of EXPORT_SET, in Item_func_export_set::val_str() (sql/item_strfunc.cc);
      a fix there does not change this one.

      ================================================================================
      STEPS TO REPRODUCE
      ================================================================================

      SELECT EXPORT_SET(3,'foo','bar',',',4294967296);                 -- 1
      SELECT EXPORT_SET(3,'foo','bar',',',4294967300);                 -- 2
      SELECT EXPORT_SET(3,'foo','bar',',',-4294967294);                -- 3
      SELECT LENGTH(EXPORT_SET(3,'foo','bar',',',65));                 -- 4
      

      ================================================================================
      EXPECTED
      ================================================================================

      1.  'foo,foo,bar,bar,...'  (64 items, 255 characters)
      2.  same as 1
      3.  same as 1
      4.  255
      

      (MySQL 26.10.0 returns exactly this.)

      ================================================================================
      ACTUAL (13.2.0 main 82964737; identical on 13.0.2, 11.8.9, 10.11.19, 10.6.28)
      ================================================================================

      1.  ''
      2.  'foo,foo,bar,bar'
      3.  'foo,foo'
      4.  255
      

      No warnings.

      ================================================================================
      SUGGESTED FIX
      ================================================================================

      Clip before narrowing, treating the argument as unsigned as documented:

          ulonglong n= (ulonglong) args[4]->val_int();
          num_set_values= n > 64 ? 64 : (uint) n;
      

      ================================================================================
      ATTACHMENTS
      ================================================================================

      repro.py (pymysql; exits 1 while the recorded wrong answers are returned).
      VERIFY-main-82964737-2026-10-14.txt: transcript on main and the four release images.

      Attachments

        Issue Links

          Activity

            People

              raghunandan.bhat Raghunandan Bhat
              kehan5800 Ke Han
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.