Description:
Inserting integer values whose high bits are set into fields of type "int unsigned", "smallint
unsigned", and "tinyint signed" using the C prepared statement API results in incorrect
values in the database. For the 2 unsigned types, large positive values (high bit set)
result in a 0 in the database. For signed 8-bit, negative values result in a 127 in the
database.
How to repeat:
Run the following program linked with the C API library, then inspect the database tables
uint32_table, uint16_table, sint8_table:
#include <iostream>
#include "mysql.h"
void main()
{
MYSQL sql, * mysql;
mysql_init(&sql);
mysql = mysql_real_connect(&sql,"localhost","XXXX","XXXX","testdb",0,NULL,0);
if (!mysql)
{
std::cout << "mysql_real_connect failed" << std::endl;
return;
}
mysql_query( mysql, "drop table if exists uint32_table" );
mysql_query( mysql, "drop table if exists uint16_table" );
mysql_query( mysql, "drop table if exists sint8_table" );
mysql_query( mysql, "create table uint32_table (a int unsigned)" );
mysql_query( mysql, "create table uint16_table (a smallint unsigned)" );
mysql_query( mysql, "create table sint8_table (a tinyint signed)" );
char *query = "insert into uint32_table values ( ? )";
MYSQL_STMT *stmt = mysql_prepare( mysql, query,strlen(query));
if (!stmt)
{
std::cout << "mysql_prepare failed uint32" << std::endl;
return;
}
unsigned int value = std::numeric_limits<unsigned int>::max() / 2 + 10;
std::cout << "unsigned int value = " << value << std::endl;
my_bool is_null = 0;
unsigned long length = sizeof(value);
MYSQL_BIND parm;
parm.buffer_type = MYSQL_TYPE_LONG;
parm.buffer = reinterpret_cast<char*>( &value );
parm.buffer_length = sizeof(value);
parm.length = &length;
parm.is_null = &is_null;
if (mysql_bind_param(stmt,&parm ))
{
fprintf(stderr,"mysql_bind_param uint32 failed");
return;
}
if (mysql_execute( stmt ) )
{
fprintf(stderr,"mysql_execute uint32 failed");
return;
}
mysql_stmt_close( stmt );
query = "insert into uint16_table values ( ? )";
stmt = mysql_prepare( mysql, query,strlen(query));
if (!stmt)
{
std::cout << "mysql_prepare failed uint16" << std::endl;
return;
}
unsigned short int value2 = std::numeric_limits<unsigned short int>::max() / 2 + 10;
std::cout << "unsigned short int value = " << value2 << std::endl;
length = sizeof(value2);
parm.buffer_type = MYSQL_TYPE_SHORT;
parm.buffer = reinterpret_cast<char*>( &value2 );
parm.buffer_length = sizeof(value2);
if (mysql_bind_param(stmt,&parm ))
{
fprintf(stderr,"mysql_bind_param uint16 failed");
return;
}
if (mysql_execute( stmt ) )
{
fprintf(stderr,"mysql_execute uint16 failed");
return;
}
mysql_stmt_close( stmt );
query = "insert into sint8_table values ( ? )";
stmt = mysql_prepare( mysql, query,strlen(query));
if (!stmt)
{
std::cout << "mysql_prepare failed sint8" << std::endl;
return;
}
signed char value3 = -3;
std::cout << "signed char value = " << int(value3) << std::endl;
length = sizeof(value3);
parm.buffer_type = MYSQL_TYPE_TINY;
parm.buffer = reinterpret_cast<char*>( &value3 );
parm.buffer_length = sizeof(value3);
if (mysql_bind_param(stmt,&parm ))
{
fprintf(stderr,"mysql_bind_param sint8 failed");
return;
}
if (mysql_execute( stmt ) )
{
fprintf(stderr,"mysql_execute sint8 failed");
return;
}
mysql_stmt_close( stmt );
}
Description: Inserting integer values whose high bits are set into fields of type "int unsigned", "smallint unsigned", and "tinyint signed" using the C prepared statement API results in incorrect values in the database. For the 2 unsigned types, large positive values (high bit set) result in a 0 in the database. For signed 8-bit, negative values result in a 127 in the database. How to repeat: Run the following program linked with the C API library, then inspect the database tables uint32_table, uint16_table, sint8_table: #include <iostream> #include "mysql.h" void main() { MYSQL sql, * mysql; mysql_init(&sql); mysql = mysql_real_connect(&sql,"localhost","XXXX","XXXX","testdb",0,NULL,0); if (!mysql) { std::cout << "mysql_real_connect failed" << std::endl; return; } mysql_query( mysql, "drop table if exists uint32_table" ); mysql_query( mysql, "drop table if exists uint16_table" ); mysql_query( mysql, "drop table if exists sint8_table" ); mysql_query( mysql, "create table uint32_table (a int unsigned)" ); mysql_query( mysql, "create table uint16_table (a smallint unsigned)" ); mysql_query( mysql, "create table sint8_table (a tinyint signed)" ); char *query = "insert into uint32_table values ( ? )"; MYSQL_STMT *stmt = mysql_prepare( mysql, query,strlen(query)); if (!stmt) { std::cout << "mysql_prepare failed uint32" << std::endl; return; } unsigned int value = std::numeric_limits<unsigned int>::max() / 2 + 10; std::cout << "unsigned int value = " << value << std::endl; my_bool is_null = 0; unsigned long length = sizeof(value); MYSQL_BIND parm; parm.buffer_type = MYSQL_TYPE_LONG; parm.buffer = reinterpret_cast<char*>( &value ); parm.buffer_length = sizeof(value); parm.length = &length; parm.is_null = &is_null; if (mysql_bind_param(stmt,&parm )) { fprintf(stderr,"mysql_bind_param uint32 failed"); return; } if (mysql_execute( stmt ) ) { fprintf(stderr,"mysql_execute uint32 failed"); return; } mysql_stmt_close( stmt ); query = "insert into uint16_table values ( ? )"; stmt = mysql_prepare( mysql, query,strlen(query)); if (!stmt) { std::cout << "mysql_prepare failed uint16" << std::endl; return; } unsigned short int value2 = std::numeric_limits<unsigned short int>::max() / 2 + 10; std::cout << "unsigned short int value = " << value2 << std::endl; length = sizeof(value2); parm.buffer_type = MYSQL_TYPE_SHORT; parm.buffer = reinterpret_cast<char*>( &value2 ); parm.buffer_length = sizeof(value2); if (mysql_bind_param(stmt,&parm )) { fprintf(stderr,"mysql_bind_param uint16 failed"); return; } if (mysql_execute( stmt ) ) { fprintf(stderr,"mysql_execute uint16 failed"); return; } mysql_stmt_close( stmt ); query = "insert into sint8_table values ( ? )"; stmt = mysql_prepare( mysql, query,strlen(query)); if (!stmt) { std::cout << "mysql_prepare failed sint8" << std::endl; return; } signed char value3 = -3; std::cout << "signed char value = " << int(value3) << std::endl; length = sizeof(value3); parm.buffer_type = MYSQL_TYPE_TINY; parm.buffer = reinterpret_cast<char*>( &value3 ); parm.buffer_length = sizeof(value3); if (mysql_bind_param(stmt,&parm )) { fprintf(stderr,"mysql_bind_param sint8 failed"); return; } if (mysql_execute( stmt ) ) { fprintf(stderr,"mysql_execute sint8 failed"); return; } mysql_stmt_close( stmt ); }