summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2019-03-25 17:36:35 +0100
committerOlivier Bertrand <bertrandop@gmail.com>2019-03-25 17:36:35 +0100
commit48d2141ba5e14c56173ef947da7141c455a62644 (patch)
tree892e3e3059661449f96e01835112afda8fb51713
parente0c147c2da6e7daf3e5c76f91da6aaefad2affe6 (diff)
downloadmariadb-git-48d2141ba5e14c56173ef947da7141c455a62644.tar.gz
- Fix MDEV-15793: Server crash in PlugCloseFile with sql_mode=''
Fixed by replacing sprinf by snprintf in ShowValue to avoid buffer overflow. It nows always use a buffer and returns int. modified: storage/connect/tabdos.cpp modified: storage/connect/tabfmt.cpp modified: storage/connect/value.cpp modified: storage/connect/value.h
-rw-r--r--storage/connect/CMakeLists.txt27
-rw-r--r--storage/connect/filamdbf.cpp4
-rwxr-xr-xstorage/connect/filamvct.cpp5
-rw-r--r--storage/connect/ha_connect.cc110
-rw-r--r--storage/connect/ha_connect.h3
-rw-r--r--storage/connect/inihandl.cpp2
-rw-r--r--storage/connect/javaconn.cpp2
-rw-r--r--storage/connect/json.h1
-rw-r--r--storage/connect/jsonudf.cpp50
-rw-r--r--storage/connect/tabdos.cpp42
-rw-r--r--storage/connect/tabfmt.cpp13
-rw-r--r--storage/connect/user_connect.cc3
-rw-r--r--storage/connect/value.cpp97
-rw-r--r--storage/connect/value.h16
14 files changed, 211 insertions, 164 deletions
diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt
index 58d9ab1f1c3..c8747f889c6 100644
--- a/storage/connect/CMakeLists.txt
+++ b/storage/connect/CMakeLists.txt
@@ -109,6 +109,7 @@ IF(CONNECT_WITH_LIBXML2)
FIND_PACKAGE(LibXml2)
IF (LIBXML2_FOUND)
INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR})
+ SET(ZLIB_LIBRARY "z") # see ZLIB_INCLUDE_DIR below
SET(XML_LIBRARY ${LIBXML2_LIBRARIES})
SET(CONNECT_SOURCES ${CONNECT_SOURCES} libdoc.cpp libdoc.h)
add_definitions(-DLIBXML2_SUPPORT)
@@ -124,7 +125,6 @@ IF(WIN32)
OPTION(CONNECT_WITH_MSXML "Compile CONNECT storage engine with MSXML support" ON)
IF(CONNECT_WITH_MSXML)
add_definitions(-DMSX6 -DDOMDOC_SUPPORT)
- message(STATUS "MSXML library version: msxml6")
SET(MSXML_FOUND 1)
SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h)
ENDIF(CONNECT_WITH_MSXML)
@@ -326,6 +326,14 @@ IF(NOT TARGET connect)
RETURN()
ENDIF()
+# Don't link with bundled zlib and systel libxml2 at the same time.
+# System libxml2 uses system zlib, might conflict with the bundled one.
+IF (XML_LIBRARY AND BUILD_BUNDLED_ZLIB)
+ GET_PROPERTY(INCS TARGET connect PROPERTY INCLUDE_DIRECTORIES)
+ LIST(REMOVE_ITEM INCS ${ZLIB_INCLUDE_DIR})
+ SET_PROPERTY(TARGET connect PROPERTY INCLUDE_DIRECTORIES ${INCS})
+ENDIF()
+
IF(WIN32)
IF (libmongoc-1.0_FOUND)
SET_TARGET_PROPERTIES(connect PROPERTIES LINK_FLAGS
@@ -346,23 +354,6 @@ IF(WIN32)
DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine)
ENDIF(WIN32)
-IF(NOT TARGET connect)
- RETURN()
-ENDIF()
-
-# Install some extra files that belong to connect engine
-IF(WIN32)
- # install ha_connect.lib
- GET_TARGET_PROPERTY(CONNECT_LOCATION connect LOCATION)
- STRING(REPLACE "dll" "lib" CONNECT_LIB ${CONNECT_LOCATION})
- IF(CMAKE_CONFIGURATION_TYPES)
- STRING(REPLACE "${CMAKE_CFG_INTDIR}" "\${CMAKE_INSTALL_CONFIG_NAME}"
- CONNECT_LIB ${CONNECT_LIB})
- ENDIF()
- INSTALL(FILES ${CONNECT_LIB}
- DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine)
-ENDIF(WIN32)
-
IF(CONNECT_WITH_JDBC AND JAVA_FOUND AND JNI_FOUND)
# TODO: Find how to compile and install the java wrapper classes
# Find required libraries and include directories
diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp
index 893e3da0d46..c8bab2b53a4 100644
--- a/storage/connect/filamdbf.cpp
+++ b/storage/connect/filamdbf.cpp
@@ -447,7 +447,7 @@ int DBFFAM::Cardinality(PGLOBAL g)
if (rln && Lrecl != rln) {
// This happens always on some Linux platforms
- sprintf(g->Message, MSG(BAD_LRECL), Lrecl, rln);
+ sprintf(g->Message, MSG(BAD_LRECL), Lrecl, (ushort)rln);
if (Accept) {
Lrecl = rln;
@@ -967,7 +967,7 @@ int DBMFAM::Cardinality(PGLOBAL g)
if (rln && Lrecl != rln) {
// This happens always on some Linux platforms
- sprintf(g->Message, MSG(BAD_LRECL), Lrecl, rln);
+ sprintf(g->Message, MSG(BAD_LRECL), Lrecl, (ushort)rln);
if (Accept) {
Lrecl = rln;
diff --git a/storage/connect/filamvct.cpp b/storage/connect/filamvct.cpp
index e8a4ba890bf..6d0779b150a 100755
--- a/storage/connect/filamvct.cpp
+++ b/storage/connect/filamvct.cpp
@@ -65,11 +65,6 @@
extern int num_read, num_there; // Statistics
static int num_write;
-#if defined(UNIX)
-// Add dummy strerror (NGC)
-char *strerror(int num);
-#endif // UNIX
-
/***********************************************************************/
/* Header containing block info for not split VEC tables. */
/* Block and last values can be calculated from NumRec and Nrec. */
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index b34db942530..191230cb03c 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -204,6 +204,26 @@ pthread_mutex_t parmut;
pthread_mutex_t usrmut;
pthread_mutex_t tblmut;
+#if defined(DEVELOPMENT)
+char *GetUserVariable(PGLOBAL g, const uchar *varname);
+
+char *GetUserVariable(PGLOBAL g, const uchar *varname)
+{
+ char buf[1024];
+ bool b;
+ THD *thd = current_thd;
+ CHARSET_INFO *cs = system_charset_info;
+ String *str = NULL, tmp(buf, sizeof(buf), cs);
+ HASH uvars = thd->user_vars;
+ user_var_entry *uvar = (user_var_entry*)my_hash_search(&uvars, varname, 0);
+
+ if (uvar)
+ str = uvar->val_str(&b, &tmp, NOT_FIXED_DEC);
+
+ return str ? PlugDup(g, str->ptr()) : NULL;
+}; // end of GetUserVariable
+#endif // DEVELOPMENT
+
/***********************************************************************/
/* Utility functions. */
/***********************************************************************/
@@ -1795,7 +1815,9 @@ PCSZ ha_connect::GetDBName(PCSZ name)
const char *ha_connect::GetTableName(void)
{
- return tshp ? tshp->table_name.str : table_share->table_name.str;
+ const char *path= tshp ? tshp->path.str : table_share->path.str;
+ const char *name= strrchr(path, slash);
+ return name ? name+1 : path;
} // end of GetTableName
char *ha_connect::GetPartName(void)
@@ -4678,9 +4700,6 @@ int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type)
PGLOBAL g= GetPlug(thd, xp);
DBUG_ENTER("ha_connect::start_stmt");
- if (table->triggers)
- g->More= 1; // We don't know which columns are used by the trigger
-
if (check_privileges(thd, GetTableOptionStruct(), table->s->db.str, true))
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
@@ -4708,8 +4727,24 @@ int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type)
break;
} // endswitch mode
- xmod= CheckMode(g, thd, newmode, &chk, &cras);
- DBUG_RETURN((xmod == MODE_ERROR) ? HA_ERR_INTERNAL_ERROR : 0);
+ if (newmode == MODE_ANY) {
+ if (CloseTable(g)) {
+ // Make error a warning to avoid crash
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
+ rc = 0;
+ } // endif Close
+
+ locked = 0;
+ xmod = MODE_ANY; // For info commands
+ DBUG_RETURN(rc);
+ } // endif MODE_ANY
+
+ newmode = CheckMode(g, thd, newmode, &chk, &cras);
+
+ if (newmode == MODE_ERROR)
+ DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+
+ DBUG_RETURN(check_stmt(g, newmode, cras));
} // end of start_stmt
/**
@@ -4891,21 +4926,16 @@ int ha_connect::external_lock(THD *thd, int lock_type)
// Make it a warning to avoid crash
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
rc= 0;
- //my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
- //rc = HA_ERR_INTERNAL_ERROR;
} // endif Close
locked= 0;
-// m_lock_type= lock_type;
xmod= MODE_ANY; // For info commands
DBUG_RETURN(rc);
- } // endif MODE_ANY
- else
- if (check_privileges(thd, options, table->s->db.str)) {
- strcpy(g->Message, "This operation requires the FILE privilege");
- htrc("%s\n", g->Message);
- DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
- } // endif check_privileges
+ } else if (check_privileges(thd, options, table->s->db.str)) {
+ strcpy(g->Message, "This operation requires the FILE privilege");
+ htrc("%s\n", g->Message);
+ DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+ } // endif check_privileges
DBUG_ASSERT(table && table->s);
@@ -4916,43 +4946,31 @@ int ha_connect::external_lock(THD *thd, int lock_type)
if (newmode == MODE_ERROR)
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
- // If this is the start of a new query, cleanup the previous one
+ DBUG_RETURN(check_stmt(g, newmode, cras));
+} // end of external_lock
+
+
+int ha_connect::check_stmt(PGLOBAL g, MODE newmode, bool cras)
+{
+ int rc = 0;
+ DBUG_ENTER("ha_connect::check_stmt");
+
+ // If this is the start of a new query, cleanup the previous one
if (xp->CheckCleanup()) {
tdbp= NULL;
valid_info= false;
- } // endif CheckCleanup
-
-#if 0
- if (xcheck) {
- // This must occur after CheckCleanup
- if (!g->Xchk) {
- g->Xchk= new(g) XCHK;
- ((PCHK)g->Xchk)->oldsep= GetBooleanOption("Sepindex", false);
- ((PCHK)g->Xchk)->oldpix= GetIndexInfo();
- } // endif Xchk
-
- } else
- g->Xchk= NULL;
-#endif // 0
+ } // endif CheckCleanup
if (cras)
g->Createas= 1; // To tell external tables of a multi-table command
- if (trace(1)) {
-#if 0
- htrc("xcheck=%d cras=%d\n", xcheck, cras);
-
- if (xcheck)
- htrc("oldsep=%d oldpix=%p\n",
- ((PCHK)g->Xchk)->oldsep, ((PCHK)g->Xchk)->oldpix);
-#endif // 0
- htrc("Calling CntCheckDB db=%s cras=%d\n", GetDBName(NULL), cras);
- } // endif trace
+ if (trace(1))
+ htrc("Calling CntCheckDB db=%s cras=%d\n", GetDBName(NULL), cras);
// Set or reset the good database environment
if (CntCheckDB(g, this, GetDBName(NULL))) {
- htrc("%p external_lock: %s\n", this, g->Message);
- rc= HA_ERR_INTERNAL_ERROR;
+ htrc("%p check_stmt: %s\n", this, g->Message);
+ rc= HA_ERR_INTERNAL_ERROR;
// This can NOT be called without open called first, but
// the table can have been closed since then
} else if (!tdbp || xp->CheckQuery(valid_query_id) || xmod != newmode) {
@@ -4972,10 +4990,10 @@ int ha_connect::external_lock(THD *thd, int lock_type)
} // endif tdbp
if (trace(1))
- htrc("external_lock: rc=%d\n", rc);
+ htrc("check_stmt: rc=%d\n", rc);
DBUG_RETURN(rc);
-} // end of external_lock
+} // end of check_stmt
/**
@@ -6257,7 +6275,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
TABLE *st= table; // Probably unuseful
THD *thd= ha_thd();
LEX_STRING cnc = table_arg->s->connect_string;
-#if defined(WITH_PARTITION_STORAGE_ENGINE)
+#ifdef WITH_PARTITION_STORAGE_ENGINE
partition_info *part_info= table_arg->part_info;
#else // !WITH_PARTITION_STORAGE_ENGINE
#define part_info 0
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index 07b1c2d2e7d..ea495557fcf 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -507,7 +507,8 @@ private:
protected:
bool check_privileges(THD *thd, PTOS options, char *dbn, bool quick=false);
MODE CheckMode(PGLOBAL g, THD *thd, MODE newmode, bool *chk, bool *cras);
- char *GetDBfromName(const char *name);
+ int check_stmt(PGLOBAL g, MODE newmode, bool cras);
+ char *GetDBfromName(const char *name);
// Members
static ulong num; // Tracable handler number
diff --git a/storage/connect/inihandl.cpp b/storage/connect/inihandl.cpp
index c039a980bcb..8a911cb05c0 100644
--- a/storage/connect/inihandl.cpp
+++ b/storage/connect/inihandl.cpp
@@ -194,7 +194,7 @@ static void PROFILE_Save( FILE *file, PROFILESECTION *section )
}
for (key = section->key; key; key = key->next)
- if (key->name && key->name[0]) {
+ if (key->name[0]) {
fprintf(file, "%s", SVP(key->name));
if (key->value)
diff --git a/storage/connect/javaconn.cpp b/storage/connect/javaconn.cpp
index f05db1892d9..f919344f20b 100644
--- a/storage/connect/javaconn.cpp
+++ b/storage/connect/javaconn.cpp
@@ -441,7 +441,7 @@ bool JAVAConn::Open(PGLOBAL g)
//=============== load and initialize Java VM and JNI interface =============
rc = CreateJavaVM(&jvm, (void**)&env, &vm_args); // YES !!
- delete options; // we then no longer need the initialisation options.
+ delete[] options; // we then no longer need the initialisation options.
switch (rc) {
case JNI_OK:
diff --git a/storage/connect/json.h b/storage/connect/json.h
index cc394401cc3..1d058ad575f 100644
--- a/storage/connect/json.h
+++ b/storage/connect/json.h
@@ -299,4 +299,3 @@ class JVALUE : public JSON {
PJVAL Next; // Next value in array
bool Del; // True when deleted
}; // end of class JVALUE
-
diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp
index d5a3a840173..df9c7200416 100644
--- a/storage/connect/jsonudf.cpp
+++ b/storage/connect/jsonudf.cpp
@@ -1666,7 +1666,8 @@ static PCSZ MakeKey(PGLOBAL g, UDF_ARGS *args, int i)
if (args->arg_count > (unsigned)i) {
int j = 0, n = args->attribute_lengths[i];
my_bool b; // true if attribute is zero terminated
- PSZ p, s = args->attributes[i];
+ PSZ p;
+ PCSZ s = args->attributes[i];
if (s && *s && (n || *s == '\'')) {
if ((b = (!n || !s[n])))
@@ -5805,6 +5806,52 @@ char *envar(UDF_INIT *initid, UDF_ARGS *args, char *result,
return str;
} // end of envar
+#if defined(DEVELOPMENT)
+extern char *GetUserVariable(PGLOBAL g, const uchar *varname);
+
+/*********************************************************************************/
+/* Utility function returning a user variable value. */
+/*********************************************************************************/
+my_bool uvar_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
+{
+ unsigned long reslen, memlen;
+
+ if (args->arg_count != 1) {
+ strcpy(message, "Unique argument must be a user variable name");
+ return true;
+ } else
+ CalcLen(args, false, reslen, memlen, true);
+
+ initid->maybe_null = true;
+ return JsonInit(initid, args, message, true, reslen, memlen, 2048);
+} // end of uvar_init
+
+char *uvar(UDF_INIT *initid, UDF_ARGS *args, char *result,
+ unsigned long *res_length, char *is_null, char *)
+{
+ char *str, varname[256];
+ PGLOBAL g = (PGLOBAL)initid->ptr;
+ int n = MY_MIN(args->lengths[0], sizeof(varname) - 1);
+
+ PlugSubSet(g->Sarea, g->Sarea_Size);
+ memcpy(varname, args->args[0], n);
+ varname[n] = 0;
+
+ if (!(str = GetUserVariable(g, (const uchar*)&varname))) {
+ *res_length = 0;
+ *is_null = 1;
+ } else
+ *res_length = strlen(str);
+
+ return str;
+} // end of uvar
+
+void uvar_deinit(UDF_INIT* initid)
+{
+ JsonFreeMem((PGLOBAL)initid->ptr);
+} // end of uvar_deinit
+#endif // DEVELOPMENT
+
/*********************************************************************************/
/* Returns the distinct number of B occurences in A. */
/*********************************************************************************/
@@ -5851,4 +5898,3 @@ long long countin(UDF_INIT *initid, UDF_ARGS *args, char *result,
free(str2);
return n;
} // end of countin
-
diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp
index 29cbbb35765..4f6e2c81744 100644
--- a/storage/connect/tabdos.cpp
+++ b/storage/connect/tabdos.cpp
@@ -1,11 +1,11 @@
/************* TabDos C++ Program Source Code File (.CPP) **************/
/* PROGRAM NAME: TABDOS */
/* ------------- */
-/* Version 4.9.3 */
+/* Version 4.9.4 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 1998-2017 */
+/* (C) Copyright to the author Olivier BERTRAND 1998-2019 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -2492,8 +2492,10 @@ bool DOSCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
} // endif's Value, Buf_Type
// Allocate the buffer used in WriteColumn for numeric columns
- if (!Buf && IsTypeNum(Buf_Type))
- Buf = (char*)PlugSubAlloc(g, NULL, MY_MAX(32, Long + Dcm + 1));
+ if (!Buf && IsTypeNum(Buf_Type))
+ Buf = (char*)PlugSubAlloc(g, NULL, MY_MAX(64, Long + 1));
+ else // Text columns do not need additional buffer
+ Buf = (char*)Value->GetTo_Val();
// Because Colblk's have been made from a copy of the original TDB in
// case of Update, we must reset them to point to the original one.
@@ -2603,8 +2605,8 @@ void DOSCOL::ReadColumn(PGLOBAL g)
/***********************************************************************/
void DOSCOL::WriteColumn(PGLOBAL g)
{
- char *p, *p2, fmt[32];
- int i, k, len, field;
+ char *p, fmt[32];
+ int i, k, n, len, field;
PTDBDOS tdbp = (PTDBDOS)To_Tdb;
if (trace(2))
@@ -2679,8 +2681,8 @@ void DOSCOL::WriteColumn(PGLOBAL g)
case TYPE_DOUBLE:
case TYPE_DECIM:
strcpy(fmt, (Ldz) ? "%0*.*lf" : "%*.*lf");
- sprintf(Buf, fmt, field + ((Nod && Dcm) ? 1 : 0),
- Dcm, Value->GetFloatValue());
+ len = field + ((Nod && Dcm) ? 1 : 0);
+ snprintf(Buf, len, fmt, len, Dcm, Value->GetFloatValue());
len = strlen(Buf);
if (Nod && Dcm)
@@ -2699,35 +2701,37 @@ void DOSCOL::WriteColumn(PGLOBAL g)
throw 31;
} // endswitch BufType
- p2 = Buf;
+ n = strlen(Buf);
} else // Standard CONNECT format
- p2 = Value->ShowValue(Buf, field);
+ n = Value->ShowValue(Buf, field);
if (trace(1))
- htrc("new length(%p)=%d\n", p2, strlen(p2));
+ htrc("new length(%p)=%d\n", Buf, n);
- if ((len = strlen(p2)) > field) {
- sprintf(g->Message, MSG(VALUE_TOO_LONG), p2, Name, field);
+ if ((len = n) > field) {
+ char *p = Value->GetCharString(Buf);
+
+ sprintf(g->Message, MSG(VALUE_TOO_LONG), p, Name, field);
throw 31;
} else if (Dsp)
for (i = 0; i < len; i++)
- if (p2[i] == '.')
- p2[i] = Dsp;
+ if (Buf[i] == '.')
+ Buf[i] = Dsp;
if (trace(2))
- htrc("buffer=%s\n", p2);
+ htrc("buffer=%s\n", Buf);
/*******************************************************************/
/* Updating must be done only when not in checking pass. */
/*******************************************************************/
if (Status) {
memset(p, ' ', field);
- memcpy(p, p2, len);
+ memcpy(p, Buf, len);
if (trace(2))
htrc(" col write: '%.*s'\n", len, p);
- } // endif Use
+ } // endif Status
} else // BIN compressed table
/*******************************************************************/
@@ -2738,7 +2742,7 @@ void DOSCOL::WriteColumn(PGLOBAL g)
sprintf(g->Message, MSG(BIN_F_TOO_LONG),
Name, Value->GetSize(), Long);
throw 31;
- } // endif
+ } // endif
} // end of WriteColumn
diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp
index 63fa2a63668..02720a3089a 100644
--- a/storage/connect/tabfmt.cpp
+++ b/storage/connect/tabfmt.cpp
@@ -1485,8 +1485,8 @@ void CSVCOL::ReadColumn(PGLOBAL g)
/***********************************************************************/
void CSVCOL::WriteColumn(PGLOBAL g)
{
- char *p, buf[64];
- int flen;
+ char *p;
+ int n, flen;
PTDBCSV tdbp = (PTDBCSV)To_Tdb;
if (trace(2))
@@ -1508,13 +1508,14 @@ void CSVCOL::WriteColumn(PGLOBAL g)
/*********************************************************************/
/* Get the string representation of the column value. */
/*********************************************************************/
- p = Value->ShowValue(buf);
+ p = Value->GetCharString(Buf);
+ n = strlen(p);
if (trace(2))
- htrc("new length(%p)=%d\n", p, strlen(p));
+ htrc("new length(%p)=%d\n", p, n);
- if ((signed)strlen(p) > flen) {
- sprintf(g->Message, MSG(BAD_FLD_LENGTH), Name, p, flen,
+ if (n > flen) {
+ sprintf(g->Message, MSG(BAD_FLD_LENGTH), Name, p, n,
tdbp->RowNumber(g), tdbp->GetFile(g));
throw 34;
} else if (Dsp)
diff --git a/storage/connect/user_connect.cc b/storage/connect/user_connect.cc
index a2a8faf9b38..d366e0222df 100644
--- a/storage/connect/user_connect.cc
+++ b/storage/connect/user_connect.cc
@@ -177,7 +177,8 @@ bool user_connect::CheckCleanup(bool force)
g->Createas = 0;
g->Alchecked = 0;
g->Mrr = 0;
- last_query_id= thdp->query_id;
+ g->More = 0;
+ last_query_id= thdp->query_id;
if (trace(65) && !force)
printf("=====> Begin new query %llu\n", last_query_id);
diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp
index e159efaa989..d9330a68a15 100644
--- a/storage/connect/value.cpp
+++ b/storage/connect/value.cpp
@@ -1,7 +1,7 @@
/************* Value C++ Functions Source Code File (.CPP) *************/
-/* Name: VALUE.CPP Version 2.8 */
+/* Name: VALUE.CPP Version 2.9 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2001-2017 */
+/* (C) Copyright to the author Olivier BERTRAND 2001-2019 */
/* */
/* This file contains the VALUE and derived classes family functions. */
/* These classes contain values of different types. They are used so */
@@ -882,18 +882,16 @@ bool TYPVAL<TYPE>::GetBinValue(void *buf, int buflen, bool go)
/* TYPVAL ShowValue: get string representation of a typed value. */
/***********************************************************************/
template <class TYPE>
-char *TYPVAL<TYPE>::ShowValue(char *buf, int len)
+int TYPVAL<TYPE>::ShowValue(char *buf, int len)
{
- sprintf(buf, Xfmt, len, Tval);
- return buf;
+ return snprintf(buf, len + 1, Xfmt, len, Tval);
} // end of ShowValue
template <>
-char *TYPVAL<double>::ShowValue(char *buf, int len)
+int TYPVAL<double>::ShowValue(char *buf, int len)
{
- // TODO: use snprintf to avoid possible overflow
- sprintf(buf, Xfmt, len, Prec, Tval);
- return buf;
+ // TODO: use a more appropriate format to avoid possible truncation
+ return snprintf(buf, len + 1, Xfmt, len, Prec, Tval);
} // end of ShowValue
/***********************************************************************/
@@ -1588,10 +1586,17 @@ bool TYPVAL<PSZ>::GetBinValue(void *buf, int buflen, bool go)
/***********************************************************************/
/* STRING ShowValue: get string representation of a char value. */
/***********************************************************************/
-char *TYPVAL<PSZ>::ShowValue(char *, int)
- {
- return Strp;
- } // end of ShowValue
+int TYPVAL<PSZ>::ShowValue(char *buf, int buflen)
+{
+ int len = (Null) ? 0 : strlen(Strp);
+
+ if (buf && buf != Strp) {
+ memset(buf, ' ', buflen + 1);
+ memcpy(buf, Strp, MY_MIN(len, buflen));
+ } // endif buf
+
+ return len;
+} // end of ShowValue
/***********************************************************************/
/* STRING GetCharString: get string representation of a char value. */
@@ -1800,10 +1805,9 @@ void DECVAL::Reset(void)
/***********************************************************************/
/* DECIMAL ShowValue: get string representation right justified. */
/***********************************************************************/
-char *DECVAL::ShowValue(char *buf, int len)
+int DECVAL::ShowValue(char *buf, int len)
{
- sprintf(buf, Xfmt, len, Strp);
- return buf;
+ return snprintf(buf, len + 1, Xfmt, len, Strp);
} // end of ShowValue
/***********************************************************************/
@@ -1868,14 +1872,13 @@ int DECVAL::CompareValue(PVAL vp)
BINVAL::BINVAL(PGLOBAL g, void *p, int cl, int n) : VALUE(TYPE_BIN)
{
assert(g);
-//Len = n;
- Len = (g) ? n : (p) ? strlen((char*)p) : 0;
+ Len = n;
Clen = cl;
Binp = PlugSubAlloc(g, NULL, Clen + 1);
memset(Binp, 0, Clen + 1);
if (p)
- memcpy(Binp, p, Len);
+ memcpy(Binp, p, MY_MIN(Len,Clen));
Chrp = NULL;
} // end of BINVAL constructor
@@ -2264,14 +2267,12 @@ bool BINVAL::GetBinValue(void *buf, int buflen, bool go)
/***********************************************************************/
/* BINVAL ShowValue: get string representation of a binary value. */
/***********************************************************************/
-char *BINVAL::ShowValue(char *buf, int len)
- {
- //int n = MY_MIN(Len, len / 2);
-
- //sprintf(buf, GetXfmt(), n, Binp);
- //return buf;
- return (char*)Binp;
- } // end of ShowValue
+int BINVAL::ShowValue(char *buf, int len)
+{
+ memset(buf, 0, len + 1);
+ memcpy(buf, Binp, MY_MIN(len, Len));
+ return Len;
+} // end of ShowValue
/***********************************************************************/
/* BINVAL GetCharString: get string representation of a binary value. */
@@ -2749,43 +2750,33 @@ char *DTVAL::GetCharString(char *p)
/***********************************************************************/
/* DTVAL ShowValue: get string representation of a date value. */
/***********************************************************************/
-char *DTVAL::ShowValue(char *buf, int len)
- {
- if (Pdtp) {
- char *p;
+int DTVAL::ShowValue(char *buf, int len)
+{
+ int rv = 0;
+ if (Pdtp) {
if (!Null) {
- size_t m, n = 0;
+ size_t n = 0, m = len + 1;
struct tm tm, *ptm = GetGmTime(&tm);
-
-
-
- if (Len < len) {
- p = buf;
- m = len;
- } else {
- p = Sdate;
- m = Len + 1;
- } // endif Len
if (ptm)
- n = strftime(p, m, Pdtp->OutFmt, ptm);
+ n = strftime(buf, m, Pdtp->OutFmt, ptm);
if (!n) {
- *p = '\0';
- strncat(p, "Error", m);
- } // endif n
+ *buf = '\0';
+ strncat(buf, "Error", m);
+ rv = 5;
+ } else
+ rv = (int)n;
- } else {
- p = buf;
- *p = '\0'; // DEFAULT VALUE ???
- } // endif Null
+ } else
+ *buf = '\0'; // DEFAULT VALUE ???
- return p;
} else
- return TYPVAL<int>::ShowValue(buf, len);
+ rv = TYPVAL<int>::ShowValue(buf, len);
- } // end of ShowValue
+ return rv;
+} // end of ShowValue
#if 0 // Not used by CONNECT
/***********************************************************************/
diff --git a/storage/connect/value.h b/storage/connect/value.h
index 6613e25100a..4f7d9a440fa 100644
--- a/storage/connect/value.h
+++ b/storage/connect/value.h
@@ -1,7 +1,7 @@
/**************** Value H Declares Source Code File (.H) ***************/
-/* Name: VALUE.H Version 2.3 */
+/* Name: VALUE.H Version 2.4 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2001-2017 */
+/* (C) Copyright to the author Olivier BERTRAND 2001-2019 */
/* */
/* This file contains the VALUE and derived classes declares. */
/***********************************************************************/
@@ -117,7 +117,7 @@ class DllExport VALUE : public BLOCK {
virtual void SetValue_pvblk(PVBLK blk, int n) = 0;
virtual void SetBinValue(void *p) = 0;
virtual bool GetBinValue(void *buf, int buflen, bool go) = 0;
- virtual char *ShowValue(char *buf, int len = 0) = 0;
+ virtual int ShowValue(char *buf, int len) = 0;
virtual char *GetCharString(char *p) = 0;
virtual bool IsEqual(PVAL vp, bool chktype) = 0;
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
@@ -229,7 +229,7 @@ class DllExport TYPVAL : public VALUE {
virtual void SetValue_pvblk(PVBLK blk, int n);
virtual void SetBinValue(void *p);
virtual bool GetBinValue(void *buf, int buflen, bool go);
- virtual char *ShowValue(char *buf, int);
+ virtual int ShowValue(char *buf, int len);
virtual char *GetCharString(char *p);
virtual bool IsEqual(PVAL vp, bool chktype);
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
@@ -302,7 +302,7 @@ class DllExport TYPVAL<PSZ>: public VALUE {
virtual void SetBinValue(void *p);
virtual int CompareValue(PVAL vp);
virtual bool GetBinValue(void *buf, int buflen, bool go);
- virtual char *ShowValue(char *buf, int);
+ virtual int ShowValue(char *buf, int len);
virtual char *GetCharString(char *p);
virtual bool IsEqual(PVAL vp, bool chktype);
virtual bool Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op);
@@ -334,7 +334,7 @@ class DllExport DECVAL: public TYPVAL<PSZ> {
// Methods
virtual bool GetBinValue(void *buf, int buflen, bool go);
- virtual char *ShowValue(char *buf, int);
+ virtual int ShowValue(char *buf, int len);
virtual bool IsEqual(PVAL vp, bool chktype);
virtual int CompareValue(PVAL vp);
@@ -387,7 +387,7 @@ class DllExport BINVAL: public VALUE {
virtual void SetBinValue(void *p);
virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual int CompareValue(PVAL) {assert(false); return 0;}
- virtual char *ShowValue(char *buf, int);
+ virtual int ShowValue(char *buf, int len);
virtual char *GetCharString(char *p);
virtual bool IsEqual(PVAL vp, bool chktype);
virtual bool FormatValue(PVAL vp, PCSZ fmt);
@@ -415,7 +415,7 @@ class DllExport DTVAL : public TYPVAL<int> {
virtual void SetValue_psz(PCSZ s);
virtual void SetValue_pvblk(PVBLK blk, int n);
virtual char *GetCharString(char *p);
- virtual char *ShowValue(char *buf, int);
+ virtual int ShowValue(char *buf, int len);
virtual bool FormatValue(PVAL vp, PCSZ fmt);
bool SetFormat(PGLOBAL g, PCSZ fmt, int len, int year = 0);
bool SetFormat(PGLOBAL g, PVAL valp);