From 793b72b1a0baa5070adacaac0e12fd995a6fbabe Mon Sep 17 00:00:00 2001
From: root <patg@patg.net>
Date: Wed, 16 Nov 2016 03:40:40 +0000
Subject: [PATCH] Added Pali's fix for CVE-2016-1249

---
 dbdimp.c                   |  18 +------
 lib/Bundle/DBD/mysql.pm    |   2 +-
 lib/DBD/mysql.pm           |   2 +-
 mysql.xs                   | 128 +++------------------------------------------
 t/40server_prepare_crash.t |   8 ++-
 6 files changed, 22 insertions(+), 139 deletions(-)

Index: DBD-mysql-4.021/dbdimp.c
===================================================================
--- DBD-mysql-4.021.orig/dbdimp.c
+++ DBD-mysql-4.021/dbdimp.c
@@ -2608,7 +2608,7 @@ dbd_st_prepare(
   dTHX;
 #if MYSQL_VERSION_ID >= SERVER_PREPARE_VERSION
   char *str_ptr;
-  int col_type, prepare_retval, limit_flag=0;
+  int prepare_retval, limit_flag=0;
   MYSQL_BIND *bind, *bind_end;
   imp_sth_phb_t *fbind;
 #endif
@@ -2797,7 +2797,6 @@ dbd_st_prepare(
 
       if (DBIc_NUM_PARAMS(imp_sth) > 0)
       {
-        int has_statement_fields= imp_sth->stmt->fields != 0;
         /* Allocate memory for bind variables */
         imp_sth->bind=            alloc_bind(DBIc_NUM_PARAMS(imp_sth));
         imp_sth->fbind=           alloc_fbind(DBIc_NUM_PARAMS(imp_sth));
@@ -2811,20 +2810,7 @@ dbd_st_prepare(
              bind < bind_end ;
              bind++, fbind++, i++ )
         {
-          /*
-            if this statement has a result set, field types will be
-            correctly identified. If there is no result set, such as
-            with an INSERT, fields will not be defined, and all buffer_type
-            will default to MYSQL_TYPE_VAR_STRING
-          */
-          col_type= (has_statement_fields ?
-                     imp_sth->stmt->fields[i].type : MYSQL_TYPE_STRING);
-
-          bind->buffer_type=  mysql_to_perl_type(col_type);
-
-          if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
-            PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t\tmysql_to_perl_type returned %d\n", col_type);
-
+          bind->buffer_type=  MYSQL_TYPE_STRING;
           bind->buffer=       NULL;
           bind->length=       &(fbind->length);
           bind->is_null=      (char*) &(fbind->is_null);
Index: DBD-mysql-4.021/mysql.xs
===================================================================
--- DBD-mysql-4.021.orig/mysql.xs
+++ DBD-mysql-4.021/mysql.xs
@@ -259,15 +259,11 @@ do(dbh, statement, attr=Nullsv, ...)
   STRLEN slen;
   char            *str_ptr, *statement_ptr, *buffer;
   int             has_binded;
-  int             col_type= MYSQL_TYPE_STRING;
-  int             buffer_is_null= 0;
   int             buffer_length= slen;
   int             buffer_type= 0;
-  int             param_type= SQL_VARCHAR;
   int             use_server_side_prepare= 0;
   MYSQL_STMT      *stmt= NULL;
   MYSQL_BIND      *bind= NULL;
-  imp_sth_phb_t   *fbind= NULL;
 #endif
     ASYNC_CHECK_XS(dbh);
 #if MYSQL_VERSION_ID >= MULTIPLE_RESULT_SET_VERSION
@@ -360,137 +356,36 @@ do(dbh, statement, attr=Nullsv, ...)
         */
         int i;
         num_params= items - 3;
-        /*num_params = mysql_stmt_param_count(stmt);*/
-        Newz(0, params, sizeof(*params)*num_params, struct imp_sth_ph_st);
         Newz(0, bind, (unsigned int) num_params, MYSQL_BIND);
-        Newz(0, fbind, (unsigned int) num_params, imp_sth_phb_t);
 
         for (i = 0; i < num_params; i++)
         {
           int defined= 0;
-          params[i].value= ST(i+3);
+          SV *param= ST(i+3);
 
-          if (params[i].value)
+          if (param)
           {
-            if (SvMAGICAL(params[i].value))
-              mg_get(params[i].value);
-            if (SvOK(params[i].value))
+            if (SvMAGICAL(param))
+              mg_get(param);
+            if (SvOK(param))
               defined= 1;
           }
           if (defined)
           {
-            buffer= SvPV(params[i].value, slen);
-            buffer_is_null= 0;
+            buffer= SvPV(param, slen);
             buffer_length= slen;
+            buffer_type= MYSQL_TYPE_STRING;
           }
           else
           {
             buffer= NULL;
-            buffer_is_null= 1;
             buffer_length= 0;
-          }
-
-          /*
-            if this statement has a result set, field types will be
-            correctly identified. If there is no result set, such as
-            with an INSERT, fields will not be defined, and all
-            buffer_type will default to MYSQL_TYPE_VAR_STRING
-          */
-          col_type= (stmt->fields) ? stmt->fields[i].type : MYSQL_TYPE_STRING;
-
-          switch (col_type) {
-#if MYSQL_VERSION_ID > 50003
-          case MYSQL_TYPE_NEWDECIMAL:
-#endif
-          case MYSQL_TYPE_DECIMAL:
-            param_type= SQL_DECIMAL;
-            buffer_type= MYSQL_TYPE_DOUBLE;
-            break;
-
-          case MYSQL_TYPE_DOUBLE:
-            param_type= SQL_DOUBLE;
-            buffer_type= MYSQL_TYPE_DOUBLE;
-            break;
-
-          case MYSQL_TYPE_FLOAT:
-            buffer_type= MYSQL_TYPE_DOUBLE;
-            param_type= SQL_FLOAT;
-            break;
-
-          case MYSQL_TYPE_SHORT:
-            buffer_type= MYSQL_TYPE_DOUBLE;
-            param_type= SQL_FLOAT;
-            break;
-
-          case MYSQL_TYPE_TINY:
-            buffer_type= MYSQL_TYPE_DOUBLE;
-            param_type= SQL_FLOAT;
-            break;
-
-          case MYSQL_TYPE_LONG:
-            buffer_type= MYSQL_TYPE_LONG;
-            param_type= SQL_BIGINT;
-            break;
-
-          case MYSQL_TYPE_INT24:
-          case MYSQL_TYPE_YEAR:
-            buffer_type= MYSQL_TYPE_LONG;
-            param_type= SQL_INTEGER; 
-            break;
-
-          case MYSQL_TYPE_LONGLONG:
-            /* perl handles long long as double
-             * so we'll set this to string */
-            buffer_type= MYSQL_TYPE_STRING;
-            param_type= SQL_VARCHAR;
-            break;
-
-          case MYSQL_TYPE_NEWDATE:
-          case MYSQL_TYPE_DATE:
-            buffer_type= MYSQL_TYPE_STRING;
-            param_type= SQL_DATE;
-            break;
-
-          case MYSQL_TYPE_TIME:
-            buffer_type= MYSQL_TYPE_STRING;
-            param_type= SQL_TIME;
-            break;
-
-          case MYSQL_TYPE_TIMESTAMP:
-            buffer_type= MYSQL_TYPE_STRING;
-            param_type= SQL_TIMESTAMP;
-            break;
-
-          case MYSQL_TYPE_VAR_STRING:
-          case MYSQL_TYPE_STRING:
-          case MYSQL_TYPE_DATETIME:
-            buffer_type= MYSQL_TYPE_STRING;
-            param_type= SQL_VARCHAR;
-            break;
-
-          case MYSQL_TYPE_BLOB:
-            buffer_type= MYSQL_TYPE_BLOB;
-            param_type= SQL_BINARY;
-            break;
-
-          case MYSQL_TYPE_GEOMETRY:
-            buffer_type= MYSQL_TYPE_BLOB;
-            param_type= SQL_BINARY;
-            break;
-
-
-          default:
-            buffer_type= MYSQL_TYPE_STRING;
-            param_type= SQL_VARCHAR;
-            break;
+            buffer_type= MYSQL_TYPE_NULL;
           }
 
           bind[i].buffer_type = buffer_type;
           bind[i].buffer_length= buffer_length;
           bind[i].buffer= buffer;
-          fbind[i].length= buffer_length;
-          fbind[i].is_null= buffer_is_null;
-          params[i].type= param_type;
         }
         has_binded= 0;
       }
@@ -502,8 +397,6 @@ do(dbh, statement, attr=Nullsv, ...)
                                            &has_binded);
       if (bind)
         Safefree(bind);
-      if (fbind)
-        Safefree(fbind);
 
       if(mysql_stmt_close(stmt))
       {
