1
0
mirror of https://github.com/mariadb-corporation/mariadb-connector-c.git synced 2025-08-08 14:02:17 +03:00

Fix for CONC-623:

If callback function returns a non zero return code, execute
will now abort with error CR_ERR_STMT_PARAM_CALLBACK.
This commit is contained in:
Georg Richter
2023-01-15 15:12:38 +01:00
parent 82fa150f8b
commit 5f6133653d
4 changed files with 74 additions and 7 deletions

View File

@@ -106,10 +106,11 @@ extern const char *mariadb_client_errors[]; /* Error messages */
#define CR_ERR_NET_READ 5013 #define CR_ERR_NET_READ 5013
#define CR_ERR_NET_WRITE 5014 #define CR_ERR_NET_WRITE 5014
#define CR_ERR_NET_UNCOMPRESS 5015 #define CR_ERR_NET_UNCOMPRESS 5015
#define CR_ERR_STMT_PARAM_CALLBACK 5016
/* Always last, if you add new error codes please update the /* Always last, if you add new error codes please update the
value for CR_MARIADB_LAST_ERROR */ value for CR_MARIADB_LAST_ERROR */
#define CR_MARIADB_LAST_ERROR CR_ERR_NET_UNCOMPRESS #define CR_MARIADB_LAST_ERROR CR_ERR_STMT_PARAM_CALLBACK
#endif #endif

View File

@@ -110,6 +110,7 @@ const char *mariadb_client_errors[] =
/* 5013 */ "Read error: %s (%d)", /* 5013 */ "Read error: %s (%d)",
/* 5014 */ "Write error: %s (%d)", /* 5014 */ "Write error: %s (%d)",
/* 5015 */ "Error while uncompressing packet", /* 5015 */ "Error while uncompressing packet",
/* 5016 */ "Error while retrieving parameter from callback function",
"" ""
}; };

View File

@@ -941,7 +941,10 @@ unsigned char* ma_stmt_execute_generate_bulk_request(MYSQL_STMT *stmt, size_t *r
/* preallocate length bytes */ /* preallocate length bytes */
if (!(start= p= (uchar *)malloc(length))) if (!(start= p= (uchar *)malloc(length)))
goto mem_error; {
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
goto error;
}
int4store(p, stmt->stmt_id); int4store(p, stmt->stmt_id);
p += STMT_ID_LENGTH; p += STMT_ID_LENGTH;
@@ -973,7 +976,10 @@ unsigned char* ma_stmt_execute_generate_bulk_request(MYSQL_STMT *stmt, size_t *r
size_t offset= p - start; size_t offset= p - start;
length= offset + stmt->param_count * 2 + 20; length= offset + stmt->param_count * 2 + 20;
if (!(start= (uchar *)realloc(start, length))) if (!(start= (uchar *)realloc(start, length)))
goto mem_error; {
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
goto error;
}
p= start + offset; p= start + offset;
} }
for (i = 0; i < stmt->param_count; i++) for (i = 0; i < stmt->param_count; i++)
@@ -991,7 +997,13 @@ unsigned char* ma_stmt_execute_generate_bulk_request(MYSQL_STMT *stmt, size_t *r
/* If callback for parameters was specified, we need to /* If callback for parameters was specified, we need to
update bind information for new row */ update bind information for new row */
if (stmt->param_callback) if (stmt->param_callback)
stmt->param_callback(stmt->user_data, stmt->params, j); {
if (stmt->param_callback(stmt->user_data, stmt->params, j))
{
SET_CLIENT_STMT_ERROR(stmt, CR_ERR_STMT_PARAM_CALLBACK, SQLSTATE_UNKNOWN, 0);
goto error;
}
}
if (mysql_stmt_skip_paramset(stmt, j)) if (mysql_stmt_skip_paramset(stmt, j))
continue; continue;
@@ -1059,7 +1071,10 @@ unsigned char* ma_stmt_execute_generate_bulk_request(MYSQL_STMT *stmt, size_t *r
size_t offset= p - start; size_t offset= p - start;
length= MAX(2 * length, offset + size + 20); length= MAX(2 * length, offset + size + 20);
if (!(start= (uchar *)realloc(start, length))) if (!(start= (uchar *)realloc(start, length)))
goto mem_error; {
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
goto error;
}
p= start + offset; p= start + offset;
} }
@@ -1075,8 +1090,7 @@ unsigned char* ma_stmt_execute_generate_bulk_request(MYSQL_STMT *stmt, size_t *r
stmt->send_types_to_server= 0; stmt->send_types_to_server= 0;
*request_len = (size_t)(p - start); *request_len = (size_t)(p - start);
return start; return start;
mem_error: error:
SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
free(start); free(start);
*request_len= 0; *request_len= 0;
return NULL; return NULL;

View File

@@ -5587,7 +5587,58 @@ static int test_mdev19838(MYSQL *mysql)
return OK; return OK;
} }
my_bool conc623_param_callback(void *data __attribute((unused)),
MYSQL_BIND *bind __attribute((unused)),
unsigned int row_nr __attribute((unused)))
{
return 1;
}
static int test_conc623(MYSQL *mysql)
{
int rc;
unsigned int paramcount= 1;
unsigned int array_size= 2;
MYSQL_BIND bind;
MYSQL_STMT *stmt= mysql_stmt_init(mysql);
rc= mysql_query(mysql, "CREATE OR REPLACE TEMPORARY TABLE t1 (a int)");
rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CB_USER_DATA, mysql);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, &paramcount);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CB_PARAM, conc623_param_callback);
check_stmt_rc(rc, stmt);
bind.buffer_type= MYSQL_TYPE_LONG;
rc= mysql_stmt_bind_param(stmt, &bind);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_prepare(stmt, SL("INSERT INTO t1 VALUES (?)"));
check_stmt_rc(rc, stmt);
rc= mysql_stmt_execute(stmt);
if (!rc)
{
diag("Error expected from callback function");
mysql_stmt_close(stmt);
return FAIL;
}
diag("Error (expected) %s", mysql_stmt_error(stmt));
mysql_stmt_close(stmt);
return OK;
}
struct my_tests_st my_tests[] = { struct my_tests_st my_tests[] = {
{"test_conc623", test_conc623, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_mdev19838", test_mdev19838, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_mdev19838", test_mdev19838, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_conc525", test_conc525, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc525", test_conc525, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
{"test_conc566", test_conc566, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, {"test_conc566", test_conc566, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},