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

Fix for CONC-452 and CONC-453:

Various coverity scan fixes, including CONC-452 and CONC-453.
Special thanks to Lukas Javorsky for fixing numerous covscan
issues (This patch includes part of his pull request #126).

Coverity scan build was using the following cmake parameters:
-WITH_EXTERNAL_ZLIB=ON -DWITH_UNIT_TESTS=OFF.

CWE-416 (use after free) in dtoa.c (from netlib) is still open.
This commit is contained in:
Georg Richter
2020-02-14 09:52:21 +01:00
parent bc061db247
commit 1218ffac1a
15 changed files with 170 additions and 115 deletions

View File

@@ -103,5 +103,5 @@ extern const char *mariadb_client_errors[]; /* Error messages */
#define CR_VERSION_MISMATCH 5008
/* Always last, if you add new error codes please update the
value for CR_MARIADB_LAST_ERROR */
#define CR_MARIADB_LAST_ERROR CR_INVALID_STMT
#define CR_MARIADB_LAST_ERROR CR_VERSION_MISMATCH
#endif

View File

@@ -1121,7 +1121,7 @@ static Bigint *d2b(U *d, int *e, int *bits, Stack_alloc *alloc)
if ((k= lo0bits(&y)))
{
x[0]= y | z << (32 - k);
z>>= k;
z>>= (k == 32) ? (--k) : k;
}
else
x[0]= y;
@@ -1906,7 +1906,8 @@ trimzeros:
s++;
}
ret:
Bfree(S, &alloc);
if (S != NULL)
Bfree(S, &alloc);
if (mhi)
{
if (mlo && mlo != mhi)

View File

@@ -49,6 +49,7 @@
#include <mariadb_ctype.h>
#include "mysql.h"
#include <math.h> /* ceil() */
#include <limits.h>
#ifdef WIN32
#include <malloc.h>
@@ -72,6 +73,8 @@
#define LONGLONG_MAX ((long long) 0x7FFFFFFFFFFFFFFFLL)
#endif
#define MAX_DBL_STR 3 + DBL_MANT_DIG - DBL_MIN_EXP
#if defined(HAVE_LONG_LONG) && !defined(ULONGLONG_MAX)
/* First check for ANSI C99 definition: */
#ifdef ULLONG_MAX
@@ -254,19 +257,25 @@ static unsigned long long my_atoull(const char *str, const char *end_str, int *e
double my_atod(const char *number, const char *end, int *error)
{
double val= 0.0;
char buffer[255];
char buffer[MAX_DBL_STR + 1];
int len= (int)(end - number);
if (len > 254)
*error= 1;
*error= errno= 0;
len= MIN(len, 254);
memcpy(&buffer, number, len);
if (len > MAX_DBL_STR)
{
*error= 1;
len= MAX_DBL_STR;
}
memcpy(buffer, number, len);
buffer[len]= '\0';
val= strtod(buffer, NULL);
/* if (!*error)
*error= errno; */
if (errno)
*error= errno;
return val;
}
@@ -570,20 +579,25 @@ static void convert_froma_string(MYSQL_BIND *r_param, char *buffer, size_t len)
case MYSQL_TYPE_NEWDECIMAL:
default:
{
char *start= buffer + r_param->offset; /* stmt_fetch_column sets offset */
char *end= buffer + len;
size_t copylen= 0;
if (start < end)
if (len > r_param->offset)
{
copylen= end - start;
if (r_param->buffer_length)
memcpy(r_param->buffer, start, MIN(copylen, r_param->buffer_length));
}
if (copylen < r_param->buffer_length)
((char *)r_param->buffer)[copylen]= 0;
*r_param->error= (copylen > r_param->buffer_length);
char *start= buffer + r_param->offset; /* stmt_fetch_column sets offset */
char *end= buffer + len;
size_t copylen= 0;
if (start < end)
{
copylen= end - start;
if (r_param->buffer_length)
memcpy(r_param->buffer, start, MIN(copylen, r_param->buffer_length));
}
if (copylen < r_param->buffer_length)
((char *)r_param->buffer)[copylen]= 0;
*r_param->error= (copylen > r_param->buffer_length);
}
else
*r_param->error= 1;
*r_param->length= (ulong)len;
}
break;
@@ -657,7 +671,7 @@ static void convert_from_long(MYSQL_BIND *r_param, const MYSQL_FIELD *field, lon
if (display_width < r_param->buffer_length)
{
ma_bmove_upp(buffer + display_width, buffer + len, len);
/* coverity [bad_memset] */
/* coverity[bad_memset] */
memset((void*) buffer, (int) '0', display_width - len);
len= display_width;
}
@@ -880,7 +894,7 @@ static void convert_from_float(MYSQL_BIND *r_param, const MYSQL_FIELD *field, fl
if (field->length < length || field->length > MAX_DOUBLE_STRING_REP_LENGTH - 1)
break;
ma_bmove_upp(buff + field->length, buff + length, length);
/* coverity [bad_memset] */
/* coverity[bad_memset] */
memset((void*) buff, (int) '0', field->length - length);
length= field->length;
}
@@ -1103,74 +1117,68 @@ void ps_fetch_datetime(MYSQL_BIND *r_param, const MYSQL_FIELD * field,
unsigned int len= net_field_length(row);
switch (r_param->buffer_type) {
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
convert_to_datetime(t, row, len, field->type);
break;
case MYSQL_TYPE_DATE:
convert_to_datetime(t, row, len, field->type);
break;
case MYSQL_TYPE_TIME:
convert_to_datetime(t, row, len, field->type);
t->year= t->day= t->month= 0;
break;
case MYSQL_TYPE_YEAR:
{
MYSQL_TIME tm;
convert_to_datetime(&tm, row, len, field->type);
shortstore(r_param->buffer, tm.year);
break;
}
default:
{
char dtbuffer[60];
MYSQL_TIME tm;
size_t length;
convert_to_datetime(&tm, row, len, field->type);
/*
if (tm.time_type== MYSQL_TIMESTAMP_TIME && tm.day)
{
tm.hour+= tm.day * 24;
tm.day=0;
}
*/
switch(field->type) {
case MYSQL_TYPE_DATE:
length= sprintf(dtbuffer, "%04u-%02u-%02u", tm.year, tm.month, tm.day);
break;
case MYSQL_TYPE_TIME:
length= sprintf(dtbuffer, "%s%02u:%02u:%02u", (tm.neg ? "-" : ""), tm.hour, tm.minute, tm.second);
if (field->decimals && field->decimals <= 6)
{
char ms[8];
sprintf(ms, ".%06lu", tm.second_part);
if (field->decimals < 6)
ms[field->decimals + 1]= 0;
length+= strlen(ms);
strcat(dtbuffer, ms);
}
break;
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
length= sprintf(dtbuffer, "%04u-%02u-%02u %02u:%02u:%02u", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
if (field->decimals && field->decimals <= 6)
{
char ms[8];
sprintf(ms, ".%06lu", tm.second_part);
if (field->decimals < 6)
ms[field->decimals + 1]= 0;
length+= strlen(ms);
strcat(dtbuffer, ms);
}
convert_to_datetime(t, row, len, field->type);
break;
case MYSQL_TYPE_DATE:
convert_to_datetime(t, row, len, field->type);
break;
case MYSQL_TYPE_TIME:
convert_to_datetime(t, row, len, field->type);
t->year= t->day= t->month= 0;
break;
case MYSQL_TYPE_YEAR:
{
MYSQL_TIME tm;
convert_to_datetime(&tm, row, len, field->type);
shortstore(r_param->buffer, tm.year);
break;
}
default:
{
char dtbuffer[60];
MYSQL_TIME tm;
size_t length;
convert_to_datetime(&tm, row, len, field->type);
switch(field->type) {
case MYSQL_TYPE_DATE:
length= sprintf(dtbuffer, "%04u-%02u-%02u", tm.year, tm.month, tm.day);
break;
case MYSQL_TYPE_TIME:
length= sprintf(dtbuffer, "%s%02u:%02u:%02u", (tm.neg ? "-" : ""), tm.hour, tm.minute, tm.second);
if (field->decimals && field->decimals <= 6)
{
char ms[8];
sprintf(ms, ".%06lu", tm.second_part);
if (field->decimals < 6)
ms[field->decimals + 1]= 0;
length+= strlen(ms);
strcat(dtbuffer, ms);
}
break;
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIMESTAMP:
length= sprintf(dtbuffer, "%04u-%02u-%02u %02u:%02u:%02u", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
if (field->decimals && field->decimals <= 6)
{
char ms[8];
sprintf(ms, ".%06lu", tm.second_part);
if (field->decimals < 6)
ms[field->decimals + 1]= 0;
length+= strlen(ms);
strcat(dtbuffer, ms);
}
break;
default:
dtbuffer[0]= 0;
length= 0;
break;
}
convert_froma_string(r_param, dtbuffer, length);
break;
default:
dtbuffer[0]= 0;
length= 0;
break;
}
convert_froma_string(r_param, dtbuffer, length);
break;
}
}
(*row) += len;
}
@@ -1353,3 +1361,4 @@ void mysql_init_ps_subsystem(void)
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/

View File

@@ -85,6 +85,7 @@ extern ulong net_buffer_length; /* net.c */
static MYSQL_PARAMETERS mariadb_internal_parameters= {&max_allowed_packet, &net_buffer_length, 0};
static my_bool mysql_client_init=0;
static void mysql_close_options(MYSQL *mysql);
static void ma_clear_session_state(MYSQL *mysql);
extern void release_configuration_dirs();
extern char **get_default_configuration_dirs();
extern my_bool ma_init_done;
@@ -1906,6 +1907,7 @@ static void mysql_close_options(MYSQL *mysql)
static void mysql_close_memory(MYSQL *mysql)
{
ma_clear_session_state(mysql);
free(mysql->host_info);
free(mysql->host);
free(mysql->user);
@@ -1925,11 +1927,23 @@ void my_set_error(MYSQL *mysql,
{
va_list ap;
const char *errmsg;
if (!format)
{
if (error_nr >= CR_MIN_ERROR && error_nr <= CR_MYSQL_LAST_ERROR)
errmsg= ER(error_nr);
else if (error_nr >= CER_MIN_ERROR && error_nr <= CR_MARIADB_LAST_ERROR)
errmsg= CER(error_nr);
else
errmsg= ER(CR_UNKNOWN_ERROR);
}
mysql->net.last_errno= error_nr;
ma_strmake(mysql->net.sqlstate, sqlstate, SQLSTATE_LENGTH);
va_start(ap, format);
vsnprintf(mysql->net.last_error, MYSQL_ERRMSG_SIZE,
format ? format : ER(error_nr), ap);
vsnprintf(mysql->net.last_error, MYSQL_ERRMSG_SIZE - 1,
format ? format : errmsg, ap);
va_end(ap);
return;
}
@@ -1947,7 +1961,7 @@ void mysql_close_slow_part(MYSQL *mysql)
}
}
void ma_clear_session_state(MYSQL *mysql)
static void ma_clear_session_state(MYSQL *mysql)
{
uint i;
@@ -1956,7 +1970,6 @@ void ma_clear_session_state(MYSQL *mysql)
for (i= SESSION_TRACK_BEGIN; i <= SESSION_TRACK_END; i++)
{
/* we acquired memory via ma_multi_alloc, so we don't need to free data */
list_free(mysql->extension->session_state[i].list, 0);
}
memset(mysql->extension->session_state, 0, sizeof(struct st_mariadb_session_state) * SESSION_TRACK_TYPES);
@@ -2080,12 +2093,13 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
if (si_type != SESSION_TRACK_STATE_CHANGE)
net_field_length(&pos); /* ignore total length, item length will follow next */
plen= net_field_length(&pos);
if (!ma_multi_malloc(0,
if (!(session_item= ma_multi_malloc(0,
&session_item, sizeof(LIST),
&str, sizeof(MYSQL_LEX_STRING),
&data, plen,
NULL))
NULL)))
{
ma_clear_session_state(mysql);
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
return -1;
}
@@ -2111,12 +2125,13 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
if (!strncmp(str->str, "character_set_client", str->length))
set_charset= 1;
plen= net_field_length(&pos);
if (!ma_multi_malloc(0,
if (!(session_item= ma_multi_malloc(0,
&session_item, sizeof(LIST),
&str, sizeof(MYSQL_LEX_STRING),
&data, plen,
NULL))
NULL)))
{
ma_clear_session_state(mysql);
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
return -1;
}
@@ -2172,7 +2187,7 @@ int mthd_my_read_query_result(MYSQL *mysql)
if (mysql->options.extension && mysql->extension->auto_local_infile == ACCEPT_FILE_REQUEST)
mysql->extension->auto_local_infile= WAIT_FOR_QUERY;
if (!mysql || (length = ma_net_safe_read(mysql)) == packet_error)
if ((length = ma_net_safe_read(mysql)) == packet_error)
{
return(1);
}

View File

@@ -387,12 +387,14 @@ MARIADB_RPL_EVENT * STDCALL mariadb_rpl_fetch(MARIADB_RPL *rpl, MARIADB_RPL_EVEN
}
break;
default:
free(rpl_event);
return NULL;
break;
}
return rpl_event;
}
mem_error:
free(rpl_event);
SET_CLIENT_ERROR(rpl->mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
return 0;
}
@@ -458,6 +460,7 @@ int STDCALL mariadb_rpl_optionsv(MARIADB_RPL *rpl,
goto end;
}
end:
va_end(ap);
return rc;
}
@@ -501,8 +504,10 @@ int STDCALL mariadb_rpl_get_optionsv(MARIADB_RPL *rpl,
break;
}
default:
va_end(ap);
return 1;
break;
}
va_end(ap);
return 0;
}

View File

@@ -212,13 +212,15 @@ static char *load_pub_key_file(const char *filename, int *pub_key_size)
if (fseek(fp, 0, SEEK_END))
goto end;
*pub_key_size= ftell(fp);
if ((*pub_key_size= ftell(fp)) < 0)
goto end;
rewind(fp);
if (!(buffer= malloc(*pub_key_size + 1)))
goto end;
if (!fread(buffer, *pub_key_size, 1, fp))
if (fread(buffer, *pub_key_size, 1, fp) != (size_t)*pub_key_size)
goto end;
error= 0;

View File

@@ -118,7 +118,7 @@ static int dummy_fallback_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql __attr
unsigned int i, last_errno= ((MCPVIO_EXT *)vio)->mysql->net.last_errno;
if (last_errno)
strncpy(last_error, ((MCPVIO_EXT *)vio)->mysql->net.last_error,
sizeof(last_error));
sizeof(last_error) - 1);
/* safety-wise we only do 10 round-trips */
for (i=0; i < 10; i++)
@@ -131,7 +131,7 @@ static int dummy_fallback_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql __attr
}
if (last_errno)
strncpy(((MCPVIO_EXT *)vio)->mysql->net.last_error, last_error,
sizeof(((MCPVIO_EXT *)vio)->mysql->net.last_error));
sizeof(((MCPVIO_EXT *)vio)->mysql->net.last_error) - 1);
return CR_ERROR;
}

View File

@@ -83,7 +83,6 @@ static int auth_old_password(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
we use the old scramble.
*/
pkt= (uchar*)mysql->scramble_buff;
pkt_len= SCRAMBLE_LENGTH_323 + 1;
}
else
{

View File

@@ -50,7 +50,11 @@
/* qhasm: z2 = z1^2^1 */
/* asm 1: fe_sq(>z2=fe#1,<z1=fe#11); for (i = 1;i < 1;++i) fe_sq(>z2=fe#1,>z2=fe#1); */
/* asm 2: fe_sq(>z2=t0,<z1=z); for (i = 1;i < 1;++i) fe_sq(>z2=t0,>z2=t0); */
fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0);
fe_sq(t0,z);
/* covscan CWE-561 dead code: variable i can't be < 1
for (i = 1;i < 1;++i) fe_sq(t0,t0);
*/
/* qhasm: z8 = z2^2^2 */
/* asm 1: fe_sq(>z8=fe#2,<z2=fe#1); for (i = 1;i < 2;++i) fe_sq(>z8=fe#2,>z8=fe#2); */
@@ -70,7 +74,11 @@ fe_mul(t0,t0,t1);
/* qhasm: z22 = z11^2^1 */
/* asm 1: fe_sq(>z22=fe#1,<z11=fe#1); for (i = 1;i < 1;++i) fe_sq(>z22=fe#1,>z22=fe#1); */
/* asm 2: fe_sq(>z22=t0,<z11=t0); for (i = 1;i < 1;++i) fe_sq(>z22=t0,>z22=t0); */
fe_sq(t0,t0); for (i = 1;i < 1;++i) fe_sq(t0,t0);
fe_sq(t0,t0);
/* covscan CWE-561 dead code: variable i can't be < 1
for (i = 1;i < 1;++i) fe_sq(t0,t0);
*/
/* qhasm: z_5_0 = z9*z22 */
/* asm 1: fe_mul(>z_5_0=fe#1,<z9=fe#2,<z22=fe#1); */

View File

@@ -50,7 +50,10 @@
/* qhasm: z2 = z1^2^1 */
/* asm 1: fe_sq(>z2=fe#1,<z1=fe#11); for (i = 1;i < 1;++i) fe_sq(>z2=fe#1,>z2=fe#1); */
/* asm 2: fe_sq(>z2=t0,<z1=z); for (i = 1;i < 1;++i) fe_sq(>z2=t0,>z2=t0); */
fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0);
fe_sq(t0,z);
/* covscan CWE-561 dead code: variable i can't be < 1
for (i = 1;i < 1;++i) fe_sq(t0,t0);
*/
/* qhasm: z8 = z2^2^2 */
/* asm 1: fe_sq(>z8=fe#2,<z2=fe#1); for (i = 1;i < 2;++i) fe_sq(>z8=fe#2,>z8=fe#2); */
@@ -70,7 +73,10 @@ fe_mul(t0,t0,t1);
/* qhasm: z22 = z11^2^1 */
/* asm 1: fe_sq(>z22=fe#3,<z11=fe#1); for (i = 1;i < 1;++i) fe_sq(>z22=fe#3,>z22=fe#3); */
/* asm 2: fe_sq(>z22=t2,<z11=t0); for (i = 1;i < 1;++i) fe_sq(>z22=t2,>z22=t2); */
fe_sq(t2,t0); for (i = 1;i < 1;++i) fe_sq(t2,t2);
fe_sq(t2,t0);
/* covscan CWE-561 dead code: variable i can't be < 1
for (i = 1;i < 1;++i) fe_sq(t2,t2);
*/
/* qhasm: z_5_0 = z9*z22 */
/* asm 1: fe_mul(>z_5_0=fe#2,<z9=fe#2,<z22=fe#3); */

View File

@@ -290,10 +290,15 @@ MA_FILE *ma_rio_open(const char *url,const char *operation)
}
rf->curl = curl_easy_init();
curl_easy_setopt(rf->curl, CURLOPT_URL, url);
curl_easy_setopt(rf->curl, CURLOPT_WRITEDATA, file);
curl_easy_setopt(rf->curl, CURLOPT_VERBOSE, 0L);
curl_easy_setopt(rf->curl, CURLOPT_WRITEFUNCTION, rio_write_callback);
if (curl_easy_setopt(rf->curl, CURLOPT_URL, url) ||
curl_easy_setopt(rf->curl, CURLOPT_WRITEDATA, file) ||
curl_easy_setopt(rf->curl, CURLOPT_VERBOSE, 0L) ||
curl_easy_setopt(rf->curl, CURLOPT_WRITEFUNCTION, rio_write_callback))
{
free(file);
free(rf);
return NULL;
}
curl_multi_add_handle(multi_handle, rf->curl);

View File

@@ -786,7 +786,13 @@ my_bool pvio_socket_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo)
else
#endif
{
strcpy(UNIXaddr.sun_path, cinfo->unix_socket);
size_t sun_path_size = sizeof(UNIXaddr.sun_path);
strncpy(UNIXaddr.sun_path, cinfo->unix_socket, sun_path_size - 1);
if (sun_path_size == strlen(UNIXaddr.sun_path) + 1 && UNIXaddr.sun_path[sun_path_size - 1] != '\0')
{
/* Making the string null-terminated */
UNIXaddr.sun_path[sun_path_size - 1] = '\0';
}
port_length= sizeof(UNIXaddr);
}
if (pvio_socket_connect_sync_or_async(pvio, (struct sockaddr *) &UNIXaddr, port_length))

View File

@@ -487,7 +487,6 @@ static int bug30472_retrieve_charset_info(MYSQL *con,
row= mysql_fetch_row(rs);
FAIL_IF(!row, "Couldn't fetch row");
strcpy(character_set_client, row[1]);
diag("cs: %s", row[1]);
mysql_free_result(rs);
rc= mysql_query(con, "SHOW VARIABLES LIKE 'character_set_results'");

View File

@@ -2191,7 +2191,7 @@ static int test_bind_negative(MYSQL *mysql)
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
check_mysql_rc(rc, mysql);
rc= mysql_query(mysql, "create temporary table t1 (c1 int unsigned)");
rc= mysql_query(mysql, "create temporary table t1 (c1 int)");
check_mysql_rc(rc, mysql);
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1), (-1)");

View File

@@ -27,7 +27,7 @@ int ZEXPORT uncompress (dest, destLen, source, sourceLen)
const Bytef *source;
uLong sourceLen;
{
z_stream stream;
z_stream stream= {0};
int err;
stream.next_in = (Bytef*)source;