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-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

@@ -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,21 +579,26 @@ 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;
*r_param->length= (ulong)len;
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
*/