Uploaded image for project: 'MariaDB ColumnStore'
  1. MariaDB ColumnStore
  2. MCOL-5196

REPLACE can provoke invalid capacity assertion in binary processing mode

    XMLWordPrintable

Details

    • Task
    • Status: Closed (View Workflow)
    • Major
    • Resolution: Fixed
    • 5.6.5, 6.4.2
    • 22.08.1
    • None
    • None

    Description

      REPLACE('a', 'pqrs', 'b') can provoke invalid length assertion when used with charset that is not multibyte and has MY_CS_BINSORT flag set. This is latin1_bin charset, for one example.

      The code:

        const string& str = fp[0]->data()->getStrVal(row, isNull);
        if (isNull)
          return "";
        size_t strLen = str.length();
       
        const string& fromstr = fp[1]->data()->getStrVal(row, isNull);
        if (isNull)
          return "";
        if (fromstr.length() == 0)
          return str;
        size_t fromLen = fromstr.length();
       
        const string& tostr = fp[2]->data()->getStrVal(row, isNull);
        if (isNull)
          return "";
        size_t toLen = tostr.length();
       
        bool binaryCmp = (cs->state & MY_CS_BINSORT) || !cs->use_mb();
        string newstr;
        size_t pos = 0;
        if (binaryCmp)
        {
          // Count the number of fromstr in strend so we can reserve buffer space.
          int count = 0;
          do
          {
            ++count;
            pos = str.find(fromstr, pos + fromLen);
          } while (pos != string::npos);
       
          newstr.reserve(strLen + (count * ((int)toLen - (int)fromLen)) + 1); // <- the culprit.
       
          uint32_t i = 0;
          pos = str.find(fromstr);
          if (pos == string::npos)
            return str;
          // Move the stuff into newstr
          do
          {
            if (pos > i)
              newstr = newstr + str.substr(i, pos - i);
       
            newstr = newstr + tostr;
            i = pos + fromLen;
            pos = str.find(fromstr, i);
          } while (pos != string::npos);
       
          newstr = newstr + str.substr(i, string::npos);
        }
      ...
      

      We count number of occurences starting with 1, even if there are no occurences of "fromstring" in the string "str" we are processing. Then we calculate signed integer difference between string to replace to "tostr" and string to replace "fromstring" and multiply it by count of occurences found plus 1.

      For string to process 'a', string to replace 'pqrs' and string to replace to 'a', the difference will be negative -3, count will be 1 and string to process length is 1. The end result will be a value that is about 4G bytes long or even more.

      Attachments

        Activity

          People

            sergey.zefirov Sergey Zefirov
            sergey.zefirov Sergey Zefirov
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Git Integration

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