Uploaded image for project: 'MariaDB Connector/C'
  1. MariaDB Connector/C
  2. CONC-459

Prepared statement insertion of a NULL MYSQL_TYPE_NEWDECIMAL type fails if buffer length is not set to 0

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed (View Workflow)
    • Priority: Minor
    • Resolution: Not a Bug
    • Affects Version/s: 3.1.7
    • Fix Version/s: N/A
    • Labels:
      None

      Description

      I have discovered that if I attempt to send a NULL value into a column that is bound as a MYSQL_TYPE_NEWDECIMAL I receive an MySQL client run out of memory from the client.

      Here is my test case:

      #include <iomanip>
      #include <iostream>
      #include <vector>
      #include <time.h>
       
      #include <mysql.h>
       
      using namespace std;
       
      void
      dropTable(MYSQL* mysql) {
          char query[] = "drop table testdfr";
          if (mysql_real_query(mysql, query, strlen(query))) {
            fprintf(stderr, "%s\n", mysql_error(mysql));
          }
      }
       
      void
      createTable(MYSQL* mysql) {
          dropTable(mysql);
          {
              char query[] = "create table testdfr(col1 DECIMAL(10,4))";
              if (mysql_real_query(mysql, query, strlen(query))) {
                fprintf(stderr, "%s\n", mysql_error(mysql));
              }
          }
      }
       
      void 
      testInsertPrepare(MYSQL* mysql) {
          MYSQL_STMT    *stmt;
          MYSQL_BIND    bind[1];
          unsigned long length[1];
          my_bool       is_null[1];
       
          stmt = mysql_stmt_init(mysql);
          if (!stmt) {
            fprintf(stderr, " mysql_stmt_init(), out of memory\n");
          }
          if (mysql_stmt_prepare(stmt, "INSERT INTO testdfr VALUES(?)", -1)) {
            fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
          }
       
          memset(bind, 0, sizeof(bind));
          bind[0].buffer_type= MYSQL_TYPE_NEWDECIMAL;
          bind[0].buffer = "1.23";
          bind[0].buffer_length = 8000;
          is_null[0] = 1;
          bind[0].is_null= &is_null[0];
          //unsigned long len = 0;
          unsigned long len = 2147483648; // DFR If this length is sufficiently large an out of memory
          bind[0].length = &len;
       
          if (mysql_stmt_bind_param(stmt, bind)) {
            fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
          }
       
          if (mysql_stmt_execute(stmt)) {
            fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
          }
       
          if (mysql_stmt_close(stmt)) {
            fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
          }
      }
       
      int
      main()
      {
          mysql_library_init(0, NULL, NULL);
       
          MYSQL* mysql_ = mysql_init(NULL);
          if(mysql_errno(mysql_)) {
              mysql_library_end();
              cerr << "??? MySQL Initialization Failed ???" << endl;
              return 1;
          } else if (mysql_ == NULL ) {
              mysql_library_end();
              cerr << "??? MySQL Initialization Failed to Allocate Connection Handle ???" << endl;
              return 1;
          }
       
          unsigned int timeout = 0;
          mysql_options(mysql_, MYSQL_OPT_CONNECT_TIMEOUT, (const char*)&timeout);
          mysql_options(mysql_, MYSQL_SET_CHARSET_NAME, MYSQL_AUTODETECT_CHARSET_NAME);
       
       
          if(!mysql_real_connect(mysql_,
                                 "server",
                                 "user",
                                 "pass",
                                 "db",
                                 3306, NULL, 0)
                                 )
          {
              cerr << "??? MySQL Connection Failed ??? " << endl << mysql_error(mysql_) << endl ;
              mysql_close(mysql_);
              return 1;
          }
       
          createTable(mysql_);
          testInsertPrepare(mysql_);
       
          mysql_close(mysql_);
          mysql_library_end();
       
          return 0;
      }
      

      Without setting the buffer length I see this error:

       MySQL client run out of memory
      

      It seems like a bug that if NULL is being sent that the buffer length should be used at all.

        Attachments

          Activity

            People

            Assignee:
            georg Georg Richter
            Reporter:
            dritter David Ritter
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: