|
|
2da1e0 |
From 604af7c0622261342929dd5087838af7d067976f Mon Sep 17 00:00:00 2001
|
|
|
2da1e0 |
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
|
|
|
2da1e0 |
Date: Fri, 26 Feb 2016 13:32:31 +0100
|
|
|
2da1e0 |
Subject: [PATCH] Fix transferring MYSQL_TYPE_LONG values on 64-bit big endian
|
|
|
2da1e0 |
systems
|
|
|
2da1e0 |
MIME-Version: 1.0
|
|
|
2da1e0 |
Content-Type: text/plain; charset=UTF-8
|
|
|
2da1e0 |
Content-Transfer-Encoding: 8bit
|
|
|
2da1e0 |
|
|
|
2da1e0 |
t/40server_prepare.t test failed on s390x platform. Server-prepared
|
|
|
2da1e0 |
values of types int, smallint, and tinyint are passed to application
|
|
|
2da1e0 |
as 32-bit integer. The same buffer was interpreted as long integer
|
|
|
2da1e0 |
by DBD::MySQL. This caused missaligned read/write and bogus
|
|
|
2da1e0 |
interpretation of the values.
|
|
|
2da1e0 |
|
|
|
2da1e0 |
https://rt.cpan.org/Public/Bug/Display.html?id=57266
|
|
|
2da1e0 |
https://bugzilla.redhat.com/show_bug.cgi?id=1311646
|
|
|
2da1e0 |
http://dev.mysql.com/doc/refman/5.7/en/mysql-stmt-fetch.html
|
|
|
2da1e0 |
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
|
|
2da1e0 |
Signed-off-by: Michiel Beijen <michiel.beijen@gmail.com>
|
|
|
2da1e0 |
---
|
|
|
2da1e0 |
dbdimp.c | 20 +++++++++++++-------
|
|
|
2da1e0 |
dbdimp.h | 5 +++--
|
|
|
2da1e0 |
2 files changed, 16 insertions(+), 9 deletions(-)
|
|
|
2da1e0 |
|
|
|
2da1e0 |
diff --git a/dbdimp.c b/dbdimp.c
|
|
|
2da1e0 |
index acdfee8..091df7d 100644
|
|
|
2da1e0 |
--- a/dbdimp.c
|
|
|
2da1e0 |
+++ b/dbdimp.c
|
|
|
2da1e0 |
@@ -18,6 +18,7 @@
|
|
|
2da1e0 |
#endif
|
|
|
2da1e0 |
|
|
|
2da1e0 |
#include "dbdimp.h"
|
|
|
2da1e0 |
+#include <inttypes.h> /* for PRId32 */
|
|
|
2da1e0 |
|
|
|
2da1e0 |
#if defined(WIN32) && defined(WORD)
|
|
|
2da1e0 |
#undef WORD
|
|
|
2da1e0 |
@@ -3752,8 +3753,8 @@ int dbd_describe(SV* sth, imp_sth_t* imp_sth)
|
|
|
2da1e0 |
|
|
|
2da1e0 |
if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
|
|
|
2da1e0 |
{
|
|
|
2da1e0 |
- PerlIO_printf(DBIc_LOGPIO(imp_xxh),"\t\ti %d col_type %d fbh->length %d\n",
|
|
|
2da1e0 |
- i, col_type, (int) fbh->length);
|
|
|
2da1e0 |
+ PerlIO_printf(DBIc_LOGPIO(imp_xxh),"\t\ti %d col_type %d fbh->length %lu\n",
|
|
|
2da1e0 |
+ i, col_type, fbh->length);
|
|
|
2da1e0 |
PerlIO_printf(DBIc_LOGPIO(imp_xxh),
|
|
|
2da1e0 |
"\t\tfields[i].length %lu fields[i].max_length %lu fields[i].type %d fields[i].charsetnr %d\n",
|
|
|
2da1e0 |
(long unsigned int) fields[i].length, (long unsigned int) fields[i].max_length, fields[i].type,
|
|
|
2da1e0 |
@@ -4014,8 +4015,8 @@ process:
|
|
|
2da1e0 |
|
|
|
2da1e0 |
case MYSQL_TYPE_LONG:
|
|
|
2da1e0 |
if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
|
|
|
2da1e0 |
- PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t\tst_fetch int data %d, unsigned? %d\n",
|
|
|
2da1e0 |
- (int) fbh->ldata, buffer->is_unsigned);
|
|
|
2da1e0 |
+ PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t\tst_fetch int data %"PRId32", unsigned? %d\n",
|
|
|
2da1e0 |
+ fbh->ldata, buffer->is_unsigned);
|
|
|
2da1e0 |
if (buffer->is_unsigned)
|
|
|
2da1e0 |
sv_setuv(sv, fbh->ldata);
|
|
|
2da1e0 |
else
|
|
|
2da1e0 |
@@ -4786,6 +4787,7 @@ int dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *param, SV *value,
|
|
|
2da1e0 |
int buffer_is_null= 0;
|
|
|
2da1e0 |
int buffer_length= slen;
|
|
|
2da1e0 |
unsigned int buffer_type= 0;
|
|
|
2da1e0 |
+ IV tmp;
|
|
|
2da1e0 |
#endif
|
|
|
2da1e0 |
|
|
|
2da1e0 |
D_imp_dbh_from_sth;
|
|
|
2da1e0 |
@@ -4873,12 +4875,16 @@ int dbd_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *param, SV *value,
|
|
|
2da1e0 |
if (!SvIOK(imp_sth->params[idx].value) && DBIc_TRACE_LEVEL(imp_xxh) >= 2)
|
|
|
2da1e0 |
PerlIO_printf(DBIc_LOGPIO(imp_xxh), "\t\tTRY TO BIND AN INT NUMBER\n");
|
|
|
2da1e0 |
buffer_length = sizeof imp_sth->fbind[idx].numeric_val.lval;
|
|
|
2da1e0 |
- imp_sth->fbind[idx].numeric_val.lval= SvIV(imp_sth->params[idx].value);
|
|
|
2da1e0 |
+
|
|
|
2da1e0 |
+ tmp = SvIV(imp_sth->params[idx].value);
|
|
|
2da1e0 |
+ if (tmp > INT32_MAX)
|
|
|
2da1e0 |
+ croak("Could not bind %ld: Integer too large for MYSQL_TYPE_LONG", tmp);
|
|
|
2da1e0 |
+ imp_sth->fbind[idx].numeric_val.lval= tmp;
|
|
|
2da1e0 |
buffer=(void*)&(imp_sth->fbind[idx].numeric_val.lval);
|
|
|
2da1e0 |
if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
|
|
|
2da1e0 |
PerlIO_printf(DBIc_LOGPIO(imp_xxh),
|
|
|
2da1e0 |
- " SCALAR type %d ->%ld<- IS A INT NUMBER\n",
|
|
|
2da1e0 |
- (int) sql_type, (long) (*buffer));
|
|
|
2da1e0 |
+ " SCALAR type %d ->%"PRId32"<- IS A INT NUMBER\n",
|
|
|
2da1e0 |
+ (int) sql_type, *(int32_t *)buffer);
|
|
|
2da1e0 |
break;
|
|
|
2da1e0 |
|
|
|
2da1e0 |
case MYSQL_TYPE_DOUBLE:
|
|
|
2da1e0 |
diff --git a/dbdimp.h b/dbdimp.h
|
|
|
2da1e0 |
index 8723bcc..1ef5d72 100644
|
|
|
2da1e0 |
--- a/dbdimp.h
|
|
|
2da1e0 |
+++ b/dbdimp.h
|
|
|
2da1e0 |
@@ -22,6 +22,7 @@
|
|
|
2da1e0 |
#include <mysqld_error.h> /* Comes MySQL */
|
|
|
2da1e0 |
|
|
|
2da1e0 |
#include <errmsg.h> /* Comes with MySQL-devel */
|
|
|
2da1e0 |
+#include <stdint.h> /* For int32_t */
|
|
|
2da1e0 |
|
|
|
2da1e0 |
/* For now, we hardcode this, but in the future,
|
|
|
2da1e0 |
* we can detect capabilities of the MySQL libraries
|
|
|
2da1e0 |
@@ -212,7 +213,7 @@ typedef struct imp_sth_ph_st {
|
|
|
2da1e0 |
typedef struct imp_sth_phb_st {
|
|
|
2da1e0 |
union
|
|
|
2da1e0 |
{
|
|
|
2da1e0 |
- long lval;
|
|
|
2da1e0 |
+ int32_t lval;
|
|
|
2da1e0 |
double dval;
|
|
|
2da1e0 |
} numeric_val;
|
|
|
2da1e0 |
unsigned long length;
|
|
|
2da1e0 |
@@ -233,7 +234,7 @@ typedef struct imp_sth_fbh_st {
|
|
|
2da1e0 |
char *data;
|
|
|
2da1e0 |
int charsetnr;
|
|
|
2da1e0 |
double ddata;
|
|
|
2da1e0 |
- long ldata;
|
|
|
2da1e0 |
+ int32_t ldata;
|
|
|
2da1e0 |
#if MYSQL_VERSION_ID < FIELD_CHARSETNR_VERSION
|
|
|
2da1e0 |
unsigned int flags;
|
|
|
2da1e0 |
#endif
|
|
|
2da1e0 |
--
|
|
|
2da1e0 |
2.7.4
|
|
|
2da1e0 |
|