From 7bc4c22656a540f5784949f4a14a36ef4a036fa8 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 20 Aug 2025 19:31:58 +1000 Subject: [PATCH 01/31] CONC-786: Remove DEAD_STOREs The Infer static analyser regards DEAD_STORES are writing to a variable that isn't used. This remove those writes. --- libmariadb/ma_decimal.c | 1 - libmariadb/ma_default.c | 1 - libmariadb/mariadb_dyncol.c | 3 +-- libmariadb/mariadb_lib.c | 5 ----- libmariadb/mariadb_rpl.c | 16 ---------------- libmariadb/mariadb_stmt.c | 2 +- plugins/auth/my_auth.c | 2 -- plugins/pvio/pvio_socket.c | 4 ++-- unittest/libmariadb/async.c | 2 +- 9 files changed, 5 insertions(+), 31 deletions(-) diff --git a/libmariadb/ma_decimal.c b/libmariadb/ma_decimal.c index a2841b970..e23bb7c7c 100644 --- a/libmariadb/ma_decimal.c +++ b/libmariadb/ma_decimal.c @@ -441,7 +441,6 @@ int bin2decimal(const char *from, decimal *to, int precision, int scale) default: DBUG_ASSERT(0); x= 0; } *buf= (x ^ mask) * powers10[DIG_PER_DEC1 - frac0x]; - buf++; } return error; } diff --git a/libmariadb/ma_default.c b/libmariadb/ma_default.c index 80efe1c9a..af397e967 100644 --- a/libmariadb/ma_default.c +++ b/libmariadb/ma_default.c @@ -299,7 +299,6 @@ static my_bool _mariadb_read_options_from_file(MYSQL *mysql, } *ptr=0; set_option(mysql, key, optval); - key= optval= 0; } } rc= 0; diff --git a/libmariadb/mariadb_dyncol.c b/libmariadb/mariadb_dyncol.c index 42de69eeb..d7507de4b 100644 --- a/libmariadb/mariadb_dyncol.c +++ b/libmariadb/mariadb_dyncol.c @@ -2322,7 +2322,7 @@ dynamic_column_get_internal(DYNAMIC_COLUMN *str, uint num_key, LEX_STRING *str_key) { DYN_HEADER header; - enum enum_dyncol_func_result rc= ER_DYNCOL_FORMAT; + enum enum_dyncol_func_result rc; memset(&header, 0, sizeof(header)); if (str->length == 0) @@ -3739,7 +3739,6 @@ mariadb_dyncol_check(DYNAMIC_COLUMN *str) goto end; } } - prev_num= num; prev_name= name; prev_data_offset= data_offset; prev_name_offset= name_offset; diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index fb7d60503..6078da6ce 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -1138,11 +1138,6 @@ unpack_fields(const MYSQL *mysql, field->flags= uint2korr(p); p+= 2; field->decimals= (uint) p[0]; - p++; - - /* filler */ - p+= 2; - if (INTERNAL_NUM_FIELD(field)) field->flags|= NUM_FLAG; diff --git a/libmariadb/mariadb_rpl.c b/libmariadb/mariadb_rpl.c index 38868fc67..ff4a81f77 100644 --- a/libmariadb/mariadb_rpl.c +++ b/libmariadb/mariadb_rpl.c @@ -1175,7 +1175,6 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN rpl_event->event.heartbeat.type= (uint8_t)*ev; ev+= 1; rpl_event->event.heartbeat.flags= uint2korr(ev); - ev+= 2; break; @@ -1192,7 +1191,6 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN ev+= strlen((char *)ev); /* terminating zero */ RPL_CHECK_POS(ev, ev_end, 1); - ev++; break; case START_ENCRYPTION_EVENT: @@ -1203,7 +1201,6 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN ev+= 4; memcpy(rpl_event->event.start_encryption.nonce, ev, 12); memcpy(rpl->nonce, ev, 12); - ev+= 12; rpl->encrypted= 1; break; @@ -1261,7 +1258,6 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN rpl_set_string_and_len(&rpl_event->event.checkpoint.filename, ev, len); if (ma_set_rpl_filename(rpl, ev, len)) goto mem_error; - ev+= len; break; case FORMAT_DESCRIPTION_EVENT: @@ -1312,7 +1308,6 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN if ((rpl->use_checksum= *ev++)) { rpl_event->checksum= uint4korr(ev); - ev+= 4; } break; @@ -1441,7 +1436,6 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN if (len > 0) /* optional metadata */ { rpl_parse_opt_metadata(rpl_event, ev, len); - ev+= len; } break; @@ -1451,7 +1445,6 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN rpl_event->event.rand.first_seed= uint8korr(ev); ev+= 8; rpl_event->event.rand.second_seed= uint8korr(ev); - ev+= 8; break; } @@ -1461,7 +1454,6 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN rpl_event->event.intvar.type= *ev; ev++; rpl_event->event.intvar.value= uint8korr(ev); - ev+= 8; break; case USER_VAR_EVENT: @@ -1527,7 +1519,6 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN ev+= len; if ((unsigned long)(ev - rpl_event->raw_data) < rpl_event->raw_data_size) rpl_event->event.uservar.flags= *ev; - ev++; } break; @@ -1562,7 +1553,6 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN if (ma_set_rpl_filename(rpl, ev, len)) goto mem_error; - ev+= len; break; case XID_EVENT: @@ -1630,7 +1620,6 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN { rpl_event->event.previous_gtid.content.data= ev; rpl_event->event.previous_gtid.content.length= len; - ev+= len; } break; } @@ -1652,7 +1641,6 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN memcpy(rpl_event->event.gtid_log.source_id, ev, 16); ev+= 16; rpl_event->event.gtid_log.sequence_nr= uint8korr(ev); - ev+= 8; break; case GTID_EVENT: @@ -1684,7 +1672,6 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN { RPL_CHECK_POS(ev, ev_end, 8); rpl_event->event.gtid.commit_id= uint8korr(ev); - ev+= 8; } else if (rpl_event->event.gtid.flags & (FL_PREPARED_XA | FL_COMPLETED_XA)) { @@ -1699,10 +1686,7 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN len= rpl_event->event.gtid.gtrid_len + rpl_event->event.gtid.bqual_len; RPL_CHECK_POS(ev, ev_end, len); rpl_set_string_and_len(&rpl_event->event.gtid.xid, ev, len); - ev+= len; } - else - ev+= 6; break; case GTID_LIST_EVENT: diff --git a/libmariadb/mariadb_stmt.c b/libmariadb/mariadb_stmt.c index c4a913339..55a0ee4df 100644 --- a/libmariadb/mariadb_stmt.c +++ b/libmariadb/mariadb_stmt.c @@ -2279,7 +2279,7 @@ static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags) static my_bool mysql_stmt_internal_reset(MYSQL_STMT *stmt, my_bool is_close) { MYSQL *mysql= stmt->mysql; - my_bool ret= 1; + my_bool ret; unsigned int flags= MADB_RESET_LONGDATA | MADB_RESET_BUFFER | MADB_RESET_ERROR; unsigned int last_status; diff --git a/plugins/auth/my_auth.c b/plugins/auth/my_auth.c index b5b342c4c..aeb043c91 100644 --- a/plugins/auth/my_auth.c +++ b/plugins/auth/my_auth.c @@ -66,7 +66,6 @@ static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql) we use the old scramble. */ pkt= (uchar*)mysql->scramble_buff; - pkt_len= SCRAMBLE_LENGTH + 1; } else { @@ -216,7 +215,6 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, /* see end= buff+32 below, fixed size of the packet is 32 bytes */ buff= malloc(33 + USERNAME_LENGTH + data_len + NAME_LEN + NAME_LEN + conn_attr_len + 9); - end= buff; mysql->client_flag|= mysql->options.client_flag; mysql->client_flag|= CLIENT_CAPABILITIES; diff --git a/plugins/pvio/pvio_socket.c b/plugins/pvio/pvio_socket.c index 85437351a..53a09b024 100644 --- a/plugins/pvio/pvio_socket.c +++ b/plugins/pvio/pvio_socket.c @@ -344,7 +344,7 @@ ssize_t pvio_socket_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length) */ ssize_t pvio_socket_async_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length) { - ssize_t r= -1; + ssize_t r; #ifndef _WIN32 int read_flags= MSG_DONTWAIT; #endif @@ -417,7 +417,7 @@ static ssize_t ma_recv(my_socket socket, uchar *buffer, size_t length, int flags */ ssize_t pvio_socket_async_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length) { - ssize_t r= -1; + ssize_t r; struct st_pvio_socket *csock= NULL; #ifndef _WIN32 int write_flags= MSG_DONTWAIT; diff --git a/unittest/libmariadb/async.c b/unittest/libmariadb/async.c index bc6beaffd..567a81329 100644 --- a/unittest/libmariadb/async.c +++ b/unittest/libmariadb/async.c @@ -91,7 +91,7 @@ wait_for_mysql(MYSQL *mysql, int status) #else struct pollfd pfd; int timeout; - int res= -1; + int res; pfd.fd= mysql_get_socket(mysql); pfd.events= From d9e4e74106fc3c900400aacb38a12323dd1e39ad Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 20 Aug 2025 19:33:23 +1000 Subject: [PATCH 02/31] CONC-786: ma_default: env can be declared as const char * --- libmariadb/ma_default.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libmariadb/ma_default.c b/libmariadb/ma_default.c index af397e967..052ed00ff 100644 --- a/libmariadb/ma_default.c +++ b/libmariadb/ma_default.c @@ -78,7 +78,7 @@ char **get_default_configuration_dirs() #ifdef _WIN32 char dirname[FN_REFLEN]; #endif - char *env; + const char *env; configuration_dirs= (char **)calloc(1, (MAX_CONFIG_DIRS + 1) * sizeof(char *)); if (!configuration_dirs) @@ -322,7 +322,7 @@ my_bool _mariadb_read_options(MYSQL *mysql, char filename[FN_REFLEN + 1]; unsigned int recursion_stop= 64; #ifndef _WIN32 - char *env; + const char *env; #endif if (recursion >= recursion_stop) From 7747529d223154d70a2c81dd5eb7e95e3cdb2eec Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 20 Aug 2025 19:44:04 +1000 Subject: [PATCH 03/31] CONC-786: ma_dtoa: Balloc - resolve null ptr de-reference (OOM) When allocation fails this returns. The handling in the calling function isn't implemented yet. libmariadb/ma_dtoa.c:646: error: Null Dereference(NULLPTR_DEREFERENCE) `rv` could be null (null value originating from line 644) and is dereferenced. 644. rv= (Bigint*) malloc(len); 645. 646. rv->k= k; ^ 647. rv->maxwds= x; 648. } --- libmariadb/ma_dtoa.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libmariadb/ma_dtoa.c b/libmariadb/ma_dtoa.c index 29faff54a..ddf8ebaa0 100644 --- a/libmariadb/ma_dtoa.c +++ b/libmariadb/ma_dtoa.c @@ -643,6 +643,8 @@ static Bigint *Balloc(int k, Stack_alloc *alloc) else rv= (Bigint*) malloc(len); + if (!rv) + return rv; rv->k= k; rv->maxwds= x; } From 606baea0543bd5429165acc0de3f3e93866b08c0 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 20 Aug 2025 19:46:51 +1000 Subject: [PATCH 04/31] CONC-786: mysql_stmt_send_long_data: return error on memory allocation libmariadb/mariadb_stmt.c:2414: error: Null Dereference(NULLPTR_DEREFERENCE) `cmd_buff` could be null (null value originating from line 2413) and is dereferenced. 2412. size_t packet_len= STMT_ID_LENGTH + 2 + length; 2413. uchar *cmd_buff= (uchar *)calloc(1, packet_len); 2414. int4store(cmd_buff, stmt->stmt_id); ^ 2415. int2store(cmd_buff + STMT_ID_LENGTH, param_number); 2416. memcpy(cmd_buff + STMT_ID_LENGTH + 2, data, length); --- libmariadb/mariadb_stmt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libmariadb/mariadb_stmt.c b/libmariadb/mariadb_stmt.c index 55a0ee4df..aed6cf5a4 100644 --- a/libmariadb/mariadb_stmt.c +++ b/libmariadb/mariadb_stmt.c @@ -2411,6 +2411,11 @@ my_bool STDCALL mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number, int ret; size_t packet_len= STMT_ID_LENGTH + 2 + length; uchar *cmd_buff= (uchar *)calloc(1, packet_len); + if (!cmd_buff) + { + stmt_set_error(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); + return(1); + } int4store(cmd_buff, stmt->stmt_id); int2store(cmd_buff + STMT_ID_LENGTH, param_number); memcpy(cmd_buff + STMT_ID_LENGTH + 2, data, length); From 99c60626572cac4507d746ef33829441af12dd05 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 20 Aug 2025 19:49:22 +1000 Subject: [PATCH 05/31] CONC-786: auth: send_client_reply_packet - return error if OOM plugins/auth/my_auth.c:308: error: Null Dereference(NULLPTR_DEREFERENCE) `buff` could be null (null value originating from line 218) and is dereferenced. 306. if (!(mysql->server_capabilities & CLIENT_MYSQL)) 307. mysql->client_flag&= ~CLIENT_MYSQL; 308. int4store(buff,mysql->client_flag); ^ --- plugins/auth/my_auth.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/auth/my_auth.c b/plugins/auth/my_auth.c index aeb043c91..046170e03 100644 --- a/plugins/auth/my_auth.c +++ b/plugins/auth/my_auth.c @@ -215,6 +215,11 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, /* see end= buff+32 below, fixed size of the packet is 32 bytes */ buff= malloc(33 + USERNAME_LENGTH + data_len + NAME_LEN + NAME_LEN + conn_attr_len + 9); + if (!buff) + { + my_set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); + return 1; + } mysql->client_flag|= mysql->options.client_flag; mysql->client_flag|= CLIENT_CAPABILITIES; From a7dc8112edbf1906ce694a83c8c92835e5a1d773 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 20 Aug 2025 19:50:39 +1000 Subject: [PATCH 06/31] CONC-786: tests: test return value This came up as deadstores in infer, but we can test these return values. --- unittest/libmariadb/basic-t.c | 2 ++ unittest/libmariadb/bulk1.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/unittest/libmariadb/basic-t.c b/unittest/libmariadb/basic-t.c index 40a44962b..7c587ebc2 100644 --- a/unittest/libmariadb/basic-t.c +++ b/unittest/libmariadb/basic-t.c @@ -64,6 +64,7 @@ static int test_conc75(MYSQL *my) mysql_kill(my, thread_id); mysql_ping(mysql); rc= mysql_query(mysql, "load data local infile './nonexistingfile.csv' into table a (`a`)"); + check_mysql_rc(!rc, mysql); // expected failure FAIL_IF(!test(mysql->options.client_flag | CLIENT_LOCAL_FILES), "client_flags not correct"); diag("thread1: %ld %ld", thread_id, mysql_thread_id(mysql)); FAIL_IF(thread_id == mysql_thread_id(mysql), "new thread id expected"); @@ -564,6 +565,7 @@ static int test_mysql_insert_id(MYSQL *mysql) FAIL_UNLESS(res == 20, ""); /* If first autogenerated number fails and 2nd works: */ rc= mysql_query(mysql, "insert into t4 values (null,'e')"); + check_mysql_rc(rc, mysql); res= mysql_insert_id(mysql); FAIL_UNLESS(res == 1, ""); rc= mysql_query(mysql, "insert ignore into t4 values (null,'e'),(null,'a'),(null,'e')"); diff --git a/unittest/libmariadb/bulk1.c b/unittest/libmariadb/bulk1.c index 62267cd7d..fcedef911 100644 --- a/unittest/libmariadb/bulk1.c +++ b/unittest/libmariadb/bulk1.c @@ -61,7 +61,7 @@ static int bulk1(MYSQL *mysql) if (!bulk_enabled) return SKIP; - rc= mysql_select_db(mysql, "testc"); + mysql_select_db(mysql, "testc"); rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk1"); check_mysql_rc(rc, mysql); From 10cdb70aadf92cd66566f65ed4135c595a9d9d0b Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 20 Aug 2025 19:51:28 +1000 Subject: [PATCH 07/31] CONC-786 tests: test_extended_init_values - OOM This could fail OOM, so just fail the test, unlikely as it is. --- unittest/libmariadb/basic-t.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/unittest/libmariadb/basic-t.c b/unittest/libmariadb/basic-t.c index 7c587ebc2..1927b6045 100644 --- a/unittest/libmariadb/basic-t.c +++ b/unittest/libmariadb/basic-t.c @@ -709,6 +709,10 @@ static int test_options_initcmd(MYSQL *unused __attribute__((unused))) static int test_extended_init_values(MYSQL *unused __attribute__((unused))) { MYSQL *mysql= mysql_init(NULL); + if (!mysql) + { + return FAIL; + } mysql_options(mysql, MYSQL_DEFAULT_AUTH, "unknown"); FAIL_IF(strcmp(mysql->options.extension->default_auth, "unknown"), "option not set"); From f7c5958745781058a3ea31f4b055a100b21aea07 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 20 Aug 2025 19:53:37 +1000 Subject: [PATCH 08/31] CONC-786 tests: check_mysql_rc and check_stmt_rc to cleanup This resolves Infer errors; unittest/libmariadb/async.c:151: error: Memory Leak(MEMORY_LEAK_C) Memory dynamically allocated by `malloc`, indirectly via call to `mysql_init()` on line 149 is not freed after the last access at line 151, column 5. 149. mysql_init(&mysql); 150. rc= mysql_options(&mysql, MYSQL_OPT_NONBLOCK, 0); 151. check_mysql_rc(rc, (MYSQL *)&mysql); ^ and: unittest/libmariadb/bulk1.c:231: error: Memory Leak(MEMORY_LEAK_C) Memory dynamically allocated by `malloc`, indirectly via call to `mysql_stmt_bind_param()` on line 230 is not freed after the last access at line 231, column 3. 229. 230. rc= mysql_stmt_bind_param(stmt, bind); 231. check_stmt_rc(rc, stmt); --- unittest/libmariadb/my_test.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unittest/libmariadb/my_test.h b/unittest/libmariadb/my_test.h index 94cdf6898..0d0305997 100644 --- a/unittest/libmariadb/my_test.h +++ b/unittest/libmariadb/my_test.h @@ -154,6 +154,7 @@ do {\ {\ diag("Error (%d): %s (%d) in %s line %d", rc, mysql_error(mysql), \ mysql_errno(mysql), __FILE__, __LINE__);\ + mysql_close(mysql); \ return(FAIL);\ }\ } while(0) @@ -163,6 +164,7 @@ do {\ if (rc)\ {\ diag("Error: %s (%s: %d)", mysql_stmt_error(stmt), __FILE__, __LINE__);\ + mysql_stmt_close(stmt); \ return(FAIL);\ }\ } while(0) From 662838aac5f4ba3b80667bdd4f521e6ee44f08ff Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 12:33:00 +1000 Subject: [PATCH 09/31] CONC-786: ma_open under HAVE_REMOTEIO reads from uninitialized mysql struct Infer error is: libmariadb/ma_io.c:126: error: Uninitialized Value(PULSE_UNINITIALIZED_VALUE) `mysql.options.extension` is read without initialization during the call to `mysql_client_find_plugin()`. 124. MYSQL mysql; 125. if (rio_plugin ||(rio_plugin= (struct st_mysql_client_plugin_REMOTEIO *) 126. mysql_client_find_plugin(&mysql, NULL, MARIADB_CLIENT_REMOTEIO_PLUGIN))) The mysql structure here is obsecuring the 'mysql' pointer passed to the function. The mysql_client_find_plugin uses the mysql.options.extension in mysql_load_plugin_v to determine if a path or environment variable is used to load the plugin. As the mysql pointer passed in is assumed to have been initialized. This wasn't the case with mariadb_rpl_open where the implementation adds a mysql_init, and closes it before returning. --- libmariadb/ma_io.c | 3 +-- libmariadb/mariadb_rpl.c | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/libmariadb/ma_io.c b/libmariadb/ma_io.c index 61b19a6d6..6bf18f058 100644 --- a/libmariadb/ma_io.c +++ b/libmariadb/ma_io.c @@ -121,9 +121,8 @@ MA_FILE *ma_open(const char *location, const char *mode, MYSQL *mysql) /* check if plugin for remote io is available and try * to open location */ { - MYSQL mysql; if (rio_plugin ||(rio_plugin= (struct st_mysql_client_plugin_REMOTEIO *) - mysql_client_find_plugin(&mysql, NULL, MARIADB_CLIENT_REMOTEIO_PLUGIN))) + mysql_client_find_plugin(mysql, NULL, MARIADB_CLIENT_REMOTEIO_PLUGIN))) return rio_plugin->methods->mopen(location, mode); return NULL; } diff --git a/libmariadb/mariadb_rpl.c b/libmariadb/mariadb_rpl.c index ff4a81f77..6686d2ece 100644 --- a/libmariadb/mariadb_rpl.c +++ b/libmariadb/mariadb_rpl.c @@ -842,6 +842,7 @@ int STDCALL mariadb_rpl_open(MARIADB_RPL *rpl) { char *buf[RPL_BINLOG_MAGIC_SIZE]; MYSQL mysql; + int ret_val= 0; /* Semi sync doesn't work when processing files */ rpl->is_semi_sync = 0; @@ -849,26 +850,37 @@ int STDCALL mariadb_rpl_open(MARIADB_RPL *rpl) if (rpl->fp) ma_close(rpl->fp); + if (!mysql_init(&mysql)) + { + rpl_set_error(rpl, CR_OUT_OF_MEMORY, 0); + return ENOMEM; + } + if (!(rpl->fp= ma_open((const char *)rpl->filename, "r", &mysql))) { rpl_set_error(rpl, CR_FILE_NOT_FOUND, 0, rpl->filename, errno); - return errno; + ret_val= errno; + goto error; } if (ma_read(buf, 1, RPL_BINLOG_MAGIC_SIZE, rpl->fp) != 4) { rpl_set_error(rpl, CR_FILE_READ, 0, rpl->filename, errno); - return errno; + ret_val= errno; + goto error; } /* check if it is a valid binlog file */ if (memcmp(buf, RPL_BINLOG_MAGIC, RPL_BINLOG_MAGIC_SIZE) != 0) { rpl_set_error(rpl, CR_BINLOG_INVALID_FILE, 0, rpl->filename, errno); - return errno; + ret_val= errno; } - return 0; +error: + + mysql_close(&mysql); + return ret_val; } } From 2c28fb47c6498faefb494a61a4a2b1c57297f0cf Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 13:05:19 +1000 Subject: [PATCH 10/31] CONC-786: async sock read without initialization Infer error is: ibmariadb/mariadb_async.c:86: error: Uninitialized Value(PULSE_UNINITIALIZED_VALUE) `sock` is read without initialization. 84. application context. The application will then resume us when the socket 85. polls ready for write, indicating that the connection attempt completed. 86. */ ^ Resolving this by returning an error for my_connect_async on a true value returned by ma_pvio_get_handle (indicating an error). --- libmariadb/mariadb_async.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libmariadb/mariadb_async.c b/libmariadb/mariadb_async.c index 2463d3129..681dd76ac 100644 --- a/libmariadb/mariadb_async.c +++ b/libmariadb/mariadb_async.c @@ -71,7 +71,8 @@ my_connect_async(MARIADB_PVIO *pvio, struct mysql_async_context *b= pvio->mysql->options.extension->async_context; my_socket sock; - ma_pvio_get_handle(pvio, &sock); + if (ma_pvio_get_handle(pvio, &sock)) + return -1; /* Make the socket non-blocking. */ ma_pvio_blocking(pvio, 0, 0); From dbc84229e2789fe3e524547f20ea4203781dd10f Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 13:19:41 +1000 Subject: [PATCH 11/31] CONC-786: dyncol: hdr.offset is read without initialization The init_read_hdr static function is called from 3 locations within this file for a hdr on the stack. This was the logical location to initialize offset. Infer error: libmariadb/mariadb_dyncol.c:4145: error: Uninitialized Value(PULSE_UNINITIALIZED_VALUE) `hdr.offset` is read without initialization during the call to `hdr_interval_length()`. 4143. goto err; 4144. header.length= 4145. hdr_interval_length(&header, header.entry + header.entry_size); ^ 4146. header.data= header.dtpool + header.offset; 4147. /* --- libmariadb/mariadb_dyncol.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libmariadb/mariadb_dyncol.c b/libmariadb/mariadb_dyncol.c index d7507de4b..1b3533816 100644 --- a/libmariadb/mariadb_dyncol.c +++ b/libmariadb/mariadb_dyncol.c @@ -675,6 +675,7 @@ init_read_hdr(DYN_HEADER *hdr, DYNAMIC_COLUMN *str) if (read_fixed_header(hdr, str)) return ER_DYNCOL_FORMAT; hdr->header= (uchar*)str->str + fmt_data[hdr->format].fixed_hdr; + hdr->offset= 0; calc_param(&hdr->entry_size, &hdr->header_size, fmt_data[hdr->format].fixed_hdr_entry, hdr->offset_size, hdr->column_count); From 5c600e2ec4e52389db3d78ecd75c8c936482ee43 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 13:31:36 +1000 Subject: [PATCH 12/31] CONC-786: options_add_initcommand (via mysql_optionsv) had no OOM handling From Infer: libmariadb/mariadb_lib.c:784: error: Null Dereference(NULLPTR_DEREFERENCE) `options->init_command` could be null (null value originating from line 783) and is dereferenced in the call to `ma_init_dynamic_array()`. 782. { 783. options->init_command= (DYNAMIC_ARRAY*)malloc(sizeof(DYNAMIC_ARRAY)); 784. ma_init_dynamic_array(options->init_command, sizeof(char*), 5, 5); ^ To resolve the static function we return true on this error, and let the mysql_optionsv return an CR_OUT_OF_MEMORY if either allocation failed. --- libmariadb/mariadb_lib.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index 6078da6ce..8e8e401c8 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -774,18 +774,31 @@ struct st_default_options mariadb_defaults[] = #define OPT_SET_VALUE_INT(OPTS, KEY, VAL) \ (OPTS)->KEY= (VAL) -static void options_add_initcommand(struct st_mysql_options *options, +static my_bool options_add_initcommand(struct st_mysql_options *options, const char *init_cmd) { char *insert= strdup(init_cmd); + if (!insert) + return TRUE; + if (!options->init_command) { options->init_command= (DYNAMIC_ARRAY*)malloc(sizeof(DYNAMIC_ARRAY)); + if (!options->init_command) + { + free(insert); + return TRUE; + } ma_init_dynamic_array(options->init_command, sizeof(char*), 5, 5); } if (ma_insert_dynamic(options->init_command, (gptr)&insert)) + { free(insert); + return TRUE; + } + + return FALSE; } my_bool _mariadb_set_conf_option(MYSQL *mysql, const char *config_option, const char *config_value) { @@ -3479,7 +3492,11 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) } break; case MYSQL_INIT_COMMAND: - options_add_initcommand(&mysql->options, (char *)arg1); + if (options_add_initcommand(&mysql->options, (char *)arg1)) + { + SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); + goto end; + } break; case MYSQL_READ_DEFAULT_FILE: OPT_SET_VALUE_STR(&mysql->options, my_cnf_file, (char *)arg1); @@ -3561,6 +3578,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...) if(!(mysql->options.extension= (struct st_mysql_options_extension *) calloc(1, sizeof(struct st_mysql_options_extension)))) { + my_context_destroy(&ctxt->async_context); free(ctxt); SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); goto end; From c48ea6d18c2f0503076c1b4c4bc47cc1926d1494 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 14:01:00 +1000 Subject: [PATCH 13/31] CONC-786: OFFSET to use offsetof(stddef.h) Avoid nullptr defererence: libmariadb/mariadb_lib.c:1042: error: Null Dereference(NULLPTR_DEREFERENCE) null (null value originating from line 1042) is dereferenced. 1040. ***************************************************************************/ 1041. 1042. static size_t rset_field_offsets[]= { ^ 1043. OFFSET(MYSQL_FIELD, catalog), 1044. OFFSET(MYSQL_FIELD, catalog_length), --- include/ma_global.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ma_global.h b/include/ma_global.h index 1b9b3462b..f6f2913d7 100644 --- a/include/ma_global.h +++ b/include/ma_global.h @@ -557,7 +557,7 @@ typedef long my_ptrdiff_t; /* Size to make addressable obj. */ #define ALIGN_PTR(A, t) ((t*) MY_ALIGN((A),sizeof(t))) /* Offset of filed f in structure t */ -#define OFFSET(t, f) ((size_t)(char *)&((t *)0)->f) +#define OFFSET(t, f) (offsetof(t, f)) #define ADD_TO_PTR(ptr,size,type) (type) ((unsigned char*) (ptr)+size) #define PTR_BYTE_DIFF(A,B) (my_ptrdiff_t) ((unsigned char*) (A) - (unsigned char*) (B)) From 23ce35b77f9301df87c6b00f61c7aa667485d85b Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 14:09:41 +1000 Subject: [PATCH 14/31] CONC-786: ma_get_rset_field_lengths nullptr derefernce libmariadb/mariadb_lib.c:1078: error: Null Dereference(NULLPTR_DEREFERENCE) `last_length` could be null (null value originating from line 1063) and is dereferenced. 1076. /* NULL_LENGTH (see also CONC-709) */ 1077. rc= 1; 1078. *last_length= 0; To be sure we check that last_length isn't null. --- libmariadb/mariadb_lib.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index 8e8e401c8..78f3cb012 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -1074,7 +1074,7 @@ static my_bool ma_get_rset_field_lengths(MYSQL_ROW row, unsigned int field_count unsigned long *lengths) { unsigned long *last_length= 0; - char *pos= 0; + const char *pos= 0; MYSQL_ROW end= row + field_count + 1; my_bool rc= 0; @@ -1088,7 +1088,8 @@ static my_bool ma_get_rset_field_lengths(MYSQL_ROW row, unsigned int field_count } else { /* NULL_LENGTH (see also CONC-709) */ rc= 1; - *last_length= 0; + if (last_length) + *last_length= 0; } last_length= lengths++; row++; From 9d9b2e750b986c31c384c47bf9f94c55c82bf232 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 14:39:07 +1000 Subject: [PATCH 15/31] CONC-786: feof fail - rpl memory leak + client error Where the feof failed, possibly in remote_io, this leaked memory and there was no client error. --- libmariadb/mariadb_rpl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libmariadb/mariadb_rpl.c b/libmariadb/mariadb_rpl.c index 6686d2ece..142754ebf 100644 --- a/libmariadb/mariadb_rpl.c +++ b/libmariadb/mariadb_rpl.c @@ -1076,6 +1076,8 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN if (ma_feof(rpl->fp)) { + rpl_set_error(rpl, CR_BINLOG_ERROR, 0, "Error closing file/stream"); + mariadb_free_rpl_event(rpl_event); return NULL; } From 318112a83a56c7f89290a47de6a3237aff5ffa46 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 14:42:13 +1000 Subject: [PATCH 16/31] CONC-786: rpl deadstore on processing libmariadb/mariadb_rpl.c:1247: error: Dead Store(DEAD_STORE) The value written to `&ev` is never used. 1245. RPL_CHECK_POS(ev, ev_end, len); 1246. rpl_set_string_and_len(&rpl_event->event.execute_load_query.statement, ev, len); 1247. ev+= len; ^ remove increment as result isn't used. --- libmariadb/mariadb_rpl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libmariadb/mariadb_rpl.c b/libmariadb/mariadb_rpl.c index 142754ebf..65c9c9375 100644 --- a/libmariadb/mariadb_rpl.c +++ b/libmariadb/mariadb_rpl.c @@ -1258,7 +1258,6 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN len= rpl_event->event_length - (ev - ev_start) - (rpl->use_checksum ? 4 : 0) - (EVENT_HEADER_OFS - 1); RPL_CHECK_POS(ev, ev_end, len); rpl_set_string_and_len(&rpl_event->event.execute_load_query.statement, ev, len); - ev+= len; break; } case BINLOG_CHECKPOINT_EVENT: From f9b6917cf2bb38d176f95f1f1253d5aa17b12348 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 14:46:03 +1000 Subject: [PATCH 17/31] CONC-786: mariadb_rpl_optionsv for MARIADB_RPL_FILENAME - OOM Handle malloc failure. --- libmariadb/mariadb_rpl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libmariadb/mariadb_rpl.c b/libmariadb/mariadb_rpl.c index 65c9c9375..d1770383b 100644 --- a/libmariadb/mariadb_rpl.c +++ b/libmariadb/mariadb_rpl.c @@ -1967,13 +1967,15 @@ int STDCALL mariadb_rpl_optionsv(MARIADB_RPL *rpl, switch (option) { case MARIADB_RPL_FILENAME: { - char *arg1= va_arg(ap, char *); + const char *arg1= va_arg(ap, char *); rpl->filename_length= (uint32_t)va_arg(ap, size_t); free((void *)rpl->filename); rpl->filename= NULL; if (rpl->filename_length) { rpl->filename= (char *)malloc(rpl->filename_length); + if (!rpl->filename) + goto malloc_fail; memcpy((void *)rpl->filename, arg1, rpl->filename_length); } else if (arg1) @@ -1981,6 +1983,7 @@ int STDCALL mariadb_rpl_optionsv(MARIADB_RPL *rpl, rpl->filename= strdup((const char *)arg1); if (!rpl->filename) { +malloc_fail: va_end(ap); rpl_set_error(rpl, CR_OUT_OF_MEMORY, 0); return 1; From e3b77868a50d32dbec2160d4cfada375073bc746 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 14:51:05 +1000 Subject: [PATCH 18/31] CONC-786: ma_rio_open failed to free memory plugins/io/remote_io.c:317: error: Memory Leak(MEMORY_LEAK_C) Memory dynamically allocated by `malloc` on line 286 is not freed after the last access at line 317, column 5. 315. curl_easy_cleanup(rf->curl); 316. 317. free(file); --- plugins/io/remote_io.c | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/io/remote_io.c b/plugins/io/remote_io.c index eb5b5f379..73ecf8946 100644 --- a/plugins/io/remote_io.c +++ b/plugins/io/remote_io.c @@ -314,6 +314,7 @@ MA_FILE *ma_rio_open(const char *url,const char *operation) /* cleanup */ curl_easy_cleanup(rf->curl); + free(rf); free(file); file = NULL; From c0a9e751ee35d072960e5caf56e19da2c3916fbe Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 15:09:13 +1000 Subject: [PATCH 19/31] CONC-786: test_compress check setting option --- unittest/libmariadb/connection.c | 1 + 1 file changed, 1 insertion(+) diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index 04172f052..68321f5c1 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -541,6 +541,7 @@ static int test_compress(MYSQL *mysql) /* use compressed protocol */ rc= mysql_options(mysql, MYSQL_OPT_COMPRESS, NULL); + check_mysql_rc(rc, mysql); if (!(my_test_connect(mysql, hostname, username, password, schema, port, From 9f5c5a22cb8a6d32a51743a89e8e1e9757fe94b0 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 15:10:42 +1000 Subject: [PATCH 20/31] CONC-786: test_conc26 mysql_init memory allocation failure --- unittest/libmariadb/connection.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index 68321f5c1..3d098d93d 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -646,6 +646,8 @@ int test_conc21(MYSQL *mysql) int test_conc26(MYSQL *unused __attribute__((unused))) { MYSQL *mysql= mysql_init(NULL); + if (!mysql) + return FAIL; mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "ascii"); FAIL_IF(my_test_connect(mysql, hostname, "notexistinguser", "password", schema, port, socketname, CLIENT_REMEMBER_OPTIONS), From 06caae2a43a153b2c1ffa41af30a5a80353d6756 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 15:12:28 +1000 Subject: [PATCH 21/31] CONC-786: test_conc118 check self kill --- unittest/libmariadb/connection.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index 3d098d93d..b86354687 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -769,7 +769,7 @@ static int test_conc118(MYSQL *mysql) mysql->options.unused_1= 1; - rc= mysql_kill(mysql, mysql_thread_id(mysql)); + mysql_kill(mysql, mysql_thread_id(mysql)); mysql_ping(mysql); @@ -778,7 +778,7 @@ static int test_conc118(MYSQL *mysql) FAIL_IF(mysql->options.unused_1 != 1, "options got lost"); - rc= mysql_kill(mysql, mysql_thread_id(mysql)); + mysql_kill(mysql, mysql_thread_id(mysql)); mysql_ping(mysql); rc= mysql_query(mysql, "SET @a:=1"); From a338d012ee0185098ccd0eaf63fa63a0fa68f745 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 15:15:59 +1000 Subject: [PATCH 22/31] CONC-786: test_bind_address handle missing env And check DROP USER result after making it an IF EXISTS variant. --- unittest/libmariadb/connection.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index b86354687..8aab1ae1c 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -821,6 +821,11 @@ static int test_bind_address(MYSQL *my) int rc; SKIP_SKYSQL; + if (!bind_addr) + { + diag("Missing env variable MYSQL_TEST_BINDADDR"); + return SKIP; + } if (!hostname || !strcmp(hostname, "localhost")) { @@ -828,8 +833,9 @@ static int test_bind_address(MYSQL *my) return SKIP; } - sprintf(query, "DROP USER '%s'@'%s'", username, bind_addr); + sprintf(query, "DROP USER IF EXISTS '%s'@'%s'", username, bind_addr); rc= mysql_query(my, query); + check_mysql_rc(rc, my); sprintf(query, "CREATE USER '%s'@'%s' IDENTIFIED BY '%s'", username, bind_addr, password); rc= mysql_query(my, query); From 0b8582640e942b4a727537fa73a1bf1fa1eb59ce Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 15:18:25 +1000 Subject: [PATCH 23/31] CONC-786: test_unix_socket_close free mysql on dummy socket failure --- unittest/libmariadb/connection.c | 1 + 1 file changed, 1 insertion(+) diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index 8aab1ae1c..9df816fb8 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -1082,6 +1082,7 @@ static int test_unix_socket_close(MYSQL *unused __attribute__((unused))) if (!(fp= fopen("./dummy_sock", "w"))) { diag("couldn't create dummy socket"); + mysql_close(mysql); return FAIL; } fclose(fp); From 19817791daac0c96e12e9391df6fc84bb9992a91 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 15:21:02 +1000 Subject: [PATCH 24/31] CONC-786: test_mdev13100 free mysql correctly --- unittest/libmariadb/connection.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index 9df816fb8..a4787ff01 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -1258,7 +1258,6 @@ static int test_mdev13100(MYSQL *my __attribute__((unused))) mysql_close(mysql); /* value from client-mariadb group */ - mysql= mysql_init(NULL); if (!(fp= fopen("./mdev13100.cnf", "w"))) return FAIL; @@ -1269,6 +1268,9 @@ static int test_mdev13100(MYSQL *my __attribute__((unused))) fclose(fp); + mysql= mysql_init(NULL); + if (!mysql) + return FAIL; rc= mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, "./mdev13100.cnf"); check_mysql_rc(rc, mysql); From 48f2a1ed5713bb4802e225b149bf38b41dd855b4 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 15:22:25 +1000 Subject: [PATCH 25/31] CONC-786: test_expired_pw test DROP USER [IF EXISTS] result --- unittest/libmariadb/connection.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unittest/libmariadb/connection.c b/unittest/libmariadb/connection.c index a4787ff01..760196c9a 100644 --- a/unittest/libmariadb/connection.c +++ b/unittest/libmariadb/connection.c @@ -1416,8 +1416,9 @@ static int test_expired_pw(MYSQL *my) diag("Server doesn't support password expiration"); return SKIP; } - sprintf(query, "DROP USER 'foo'@'%s'", this_host); + sprintf(query, "DROP USER IF EXISTS 'foo'@'%s'", this_host); rc= mysql_query(my, query); + check_mysql_rc(rc, my); sprintf(query, "CREATE USER 'foo'@'%s' IDENTIFIED BY 'foo'", this_host); rc= mysql_query(my, query); From b1e91575092e48bcd6c6a4ed0f37b6add05330e8 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 15:28:52 +1000 Subject: [PATCH 26/31] CONC-786: test_mdev35935 test mysql_select_db --- unittest/libmariadb/errors.c | 1 + 1 file changed, 1 insertion(+) diff --git a/unittest/libmariadb/errors.c b/unittest/libmariadb/errors.c index 6f2334a13..632b7b2b4 100644 --- a/unittest/libmariadb/errors.c +++ b/unittest/libmariadb/errors.c @@ -291,6 +291,7 @@ static int test_mdev35935(MYSQL *mysql) SKIP_MYSQL(mysql); rc= mysql_select_db(mysql, schema); + check_mysql_rc(rc, mysql); rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk1"); check_mysql_rc(rc, mysql); From 92265cedd7148f28decd83a4b8f435e7c2a494e9 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 15:30:06 +1000 Subject: [PATCH 27/31] CONC-786: execute_direct_example check create table result --- unittest/libmariadb/features-10_2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/unittest/libmariadb/features-10_2.c b/unittest/libmariadb/features-10_2.c index 6e5064dc1..e48746d9a 100644 --- a/unittest/libmariadb/features-10_2.c +++ b/unittest/libmariadb/features-10_2.c @@ -86,6 +86,7 @@ static int execute_direct_example(MYSQL *mysql) rc= mariadb_stmt_execute_direct(stmt, "DROP TABLE IF EXISTS execute_direct", -1); check_stmt_rc(rc, stmt); rc= mariadb_stmt_execute_direct(stmt, "CREATE TABLE execute_direct (a int, b varchar(20))", -1); + check_stmt_rc(rc, stmt); rc= mysql_stmt_close(stmt); stmt= mysql_stmt_init(mysql); check_stmt_rc(rc, stmt); From 9550a2705d4e890e5d37c19b6447614125cd2fc7 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 15:31:49 +1000 Subject: [PATCH 28/31] CONC-786: conc_213 fail on stmt allocation failure --- unittest/libmariadb/features-10_2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unittest/libmariadb/features-10_2.c b/unittest/libmariadb/features-10_2.c index e48746d9a..99173df96 100644 --- a/unittest/libmariadb/features-10_2.c +++ b/unittest/libmariadb/features-10_2.c @@ -129,6 +129,8 @@ static int conc_213(MYSQL *mysql) MYSQL_STMT *stmt; stmt = mysql_stmt_init(mysql); + if (!stmt) + return FAIL; memset(&bind, '\0', sizeof(bind)); From 88849b7d68c3525a2f0a05a66879ea2729b8719e Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Aug 2025 15:33:16 +1000 Subject: [PATCH 29/31] CONC-786: conc_212 check stmt close --- unittest/libmariadb/features-10_2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/unittest/libmariadb/features-10_2.c b/unittest/libmariadb/features-10_2.c index 99173df96..a1d33ad4f 100644 --- a/unittest/libmariadb/features-10_2.c +++ b/unittest/libmariadb/features-10_2.c @@ -172,6 +172,7 @@ static int conc_212(MYSQL *mysql) rc= mysql_stmt_close(stmt); + check_stmt_rc(rc, stmt); return OK; } From 19ef7531d6ddc3b90061162f326ec42e290246ee Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Fri, 22 Aug 2025 19:25:21 +1000 Subject: [PATCH 30/31] CONC-786: mysql_init - free net.extensions on fail always The net.extension is always dynamicly allocated. Its freeing shouldn't depend on free_me. Its important to set this pointer to null so that anything that calls mysql_close on this failed initialization, like mariadb_reconnect does, will not double-free the pointer. mariadb_reconnect doesn't need to set free_me to 0, it already was by virtue of a pointer passed to mysql_init. --- libmariadb/mariadb_lib.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index 78f3cb012..89947342b 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -1367,10 +1367,11 @@ mysql_init(MYSQL *mysql) mysql->options.reconnect= 0; return mysql; error: + if (mysql->net.extension) + free(mysql->net.extension); + mysql->net.extension= 0; if (mysql->free_me) { - if (mysql->net.extension) - free(mysql->net.extension); free(mysql); } return 0; @@ -2115,11 +2116,9 @@ my_bool STDCALL mariadb_reconnect(MYSQL *mysql) { /* extensions may have failed to allocate */ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); - tmp_mysql.free_me= 0; mysql_close(&tmp_mysql); return(1); } - tmp_mysql.free_me= 0; tmp_mysql.options=mysql->options; if (mysql->extension->conn_hdlr) { From 5f31ab2c41316e80d63c0162aefa4e40b9d48f91 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Sat, 23 Aug 2025 11:29:08 +1000 Subject: [PATCH 31/31] CONC-786: mariadb_reconnect mysql_init failure requires no mysql_close With the previous commit, a mysql_init failure leaves no memory allocated, so there's no need to close. This avoids a Infer error (but I didn't see the cause): libmariadb/mariadb_lib.c:2108: error: Uninitialized Value(PULSE_UNINITIALIZED_VALUE) `mysql.extension` is read without initialization during the call to `mysql_close()`. MYSQL tmp_mysql; if (!mysql_init(&tmp_mysql)) { /* extensions may have failed to allocate */ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); 2106. tmp_mysql.free_me= 0; 2107. mysql_close(&tmp_mysql); 2108. return(1); --- libmariadb/mariadb_lib.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index 89947342b..2b3fda455 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -2116,7 +2116,6 @@ my_bool STDCALL mariadb_reconnect(MYSQL *mysql) { /* extensions may have failed to allocate */ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); - mysql_close(&tmp_mysql); return(1); } tmp_mysql.options=mysql->options;