components/perl_modules/dbd-mysql/patches/03-Fix-transferring-MYSQL_TYPE_LONG-values-on-64-bit-bi.patch
changeset 6534 7944bbb85989
parent 6533 de74a7d8f718
child 6536 2fd312fc3224
equal deleted inserted replaced
6533:de74a7d8f718 6534:7944bbb85989
     1 From 95b210810301f0a5c87adc0d682bc8424dfb41d0 Mon Sep 17 00:00:00 2001
       
     2 From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <[email protected]>
       
     3 Date: Fri, 26 Feb 2016 13:32:31 +0100
       
     4 Subject: [PATCH] Fix transferring MYSQL_TYPE_LONG values on 64-bit big endian
       
     5  systems
       
     6 MIME-Version: 1.0
       
     7 Content-Type: text/plain; charset=UTF-8
       
     8 Content-Transfer-Encoding: 8bit
       
     9 
       
    10 t/40server_prepare.t test failed on s390x platform. Server-prepared
       
    11 values of types int, smallint, and tinyint are passed to application
       
    12 as 32-bit integer. The same buffer was interpreted as long integer
       
    13 by DBD::MySQL. This caused missaligned read/write and bogus
       
    14 interpretation of the values.
       
    15 
       
    16 https://rt.cpan.org/Public/Bug/Display.html?id=57266
       
    17 https://bugzilla.redhat.com/show_bug.cgi?id=1311646
       
    18 http://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-fetch.html
       
    19 Signed-off-by: Petr Písař <[email protected]>
       
    20 ---
       
    21  dbdimp.c | 20 +++++++++++++-------
       
    22  dbdimp.h |  5 +++--
       
    23  2 files changed, 16 insertions(+), 9 deletions(-)
       
    24 
       
    25 diff --git a/dbdimp.c b/dbdimp.c
       
    26 index d507588..9a1be20 100644
       
    27 --- a/dbdimp.c
       
    28 +++ b/dbdimp.c
       
    29 @@ -18,6 +18,7 @@
       
    30  #endif
       
    31  
       
    32  #include "dbdimp.h"
       
    33 +#include <inttypes.h> /* for PRId32 */
       
    34  
       
    35  #if defined(WIN32)  &&  defined(WORD)
       
    36  #undef WORD
       
    37 @@ -3753,8 +3754,8 @@ int dbd_describe(SV* sth, imp_sth_t* imp_sth)
       
    38  
       
    39        if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
       
    40        {
       
    41 -        PerlIO_printf(DBIc_LOGPIO(imp_xxh),"\t\ti %d col_type %d fbh->length %d\n",
       
    42 -                      i, col_type, (int) fbh->length);
       
    43 +        PerlIO_printf(DBIc_LOGPIO(imp_xxh),"\t\ti %d col_type %d fbh->length %lu\n",
       
    44 +                      i, col_type, fbh->length);
       
    45          PerlIO_printf(DBIc_LOGPIO(imp_xxh),
       
    46                        "\t\tfields[i].length %lu fields[i].max_length %lu fields[i].type %d fields[i].charsetnr %d\n",
       
    47                        (long unsigned int) fields[i].length, (long unsigned int) fields[i].max_length, fields[i].type,
       
    48 @@ -4015,8 +4016,8 @@ process:
       
    49  
       
    50          case MYSQL_TYPE_LONG:
       
    51            if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
       
    52 -            PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t\tst_fetch int data %d, unsigned? %d\n",
       
    53 -                          (int) fbh->ldata, buffer->is_unsigned);
       
    54 +            PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t\tst_fetch int data %"PRId32", unsigned? %d\n",
       
    55 +                          fbh->ldata, buffer->is_unsigned);
       
    56            if (buffer->is_unsigned)
       
    57              sv_setuv(sv, fbh->ldata);
       
    58            else
       
    59 @@ -4787,6 +4788,7 @@ int dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *param, SV *value,
       
    60    int buffer_is_null= 0;
       
    61    int buffer_length= slen;
       
    62    unsigned int buffer_type= 0;
       
    63 +  IV tmp;
       
    64  #endif
       
    65  
       
    66    D_imp_dbh_from_sth;
       
    67 @@ -4874,12 +4876,16 @@ int dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *param, SV *value,
       
    68            if (!SvIOK(imp_sth->params[idx].value) && DBIc_TRACE_LEVEL(imp_xxh) >= 2)
       
    69              PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t\tTRY TO BIND AN INT NUMBER\n");
       
    70            buffer_length = sizeof imp_sth->fbind[idx].numeric_val.lval;
       
    71 -          imp_sth->fbind[idx].numeric_val.lval= SvIV(imp_sth->params[idx].value);
       
    72 +
       
    73 +          tmp = SvIV(imp_sth->params[idx].value);
       
    74 +          if (tmp > INT32_MAX)
       
    75 +	        croak("Could not bind %ld: Integer too large for MYSQL_TYPE_LONG", tmp);
       
    76 +          imp_sth->fbind[idx].numeric_val.lval= tmp;
       
    77            buffer=(void*)&(imp_sth->fbind[idx].numeric_val.lval);
       
    78            if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
       
    79              PerlIO_printf(DBIc_LOGPIO(imp_xxh),
       
    80 -                          "   SCALAR type %d ->%ld<- IS A INT NUMBER\n",
       
    81 -                          (int) sql_type, (long) (*buffer));
       
    82 +                          "   SCALAR type %d ->%"PRId32"<- IS A INT NUMBER\n",
       
    83 +                          (int) sql_type, *(int32_t *)buffer);
       
    84            break;
       
    85  
       
    86          case MYSQL_TYPE_DOUBLE:
       
    87 diff --git a/dbdimp.h b/dbdimp.h
       
    88 index 8723bcc..1ef5d72 100644
       
    89 --- a/dbdimp.h
       
    90 +++ b/dbdimp.h
       
    91 @@ -22,6 +22,7 @@
       
    92  #include <mysqld_error.h>  /* Comes MySQL */
       
    93  
       
    94  #include <errmsg.h> /* Comes with MySQL-devel */
       
    95 +#include <stdint.h> /* For int32_t */
       
    96  
       
    97  /* For now, we hardcode this, but in the future,
       
    98   * we can detect capabilities of the MySQL libraries
       
    99 @@ -212,7 +213,7 @@ typedef struct imp_sth_ph_st {
       
   100  typedef struct imp_sth_phb_st {
       
   101      union
       
   102      {
       
   103 -      long lval;
       
   104 +      int32_t lval;
       
   105        double dval;
       
   106      } numeric_val;
       
   107      unsigned long   length;
       
   108 @@ -233,7 +234,7 @@ typedef struct imp_sth_fbh_st {
       
   109      char           *data;
       
   110      int            charsetnr;
       
   111      double         ddata;
       
   112 -    long           ldata;
       
   113 +    int32_t        ldata;
       
   114  #if MYSQL_VERSION_ID < FIELD_CHARSETNR_VERSION 
       
   115      unsigned int   flags;
       
   116  #endif
       
   117 -- 
       
   118 2.5.0
       
   119