diff options
author | Olivier Bertrand <bertrandop@gmail.com> | 2019-03-25 17:36:35 +0100 |
---|---|---|
committer | Olivier Bertrand <bertrandop@gmail.com> | 2019-03-25 17:36:35 +0100 |
commit | 48d2141ba5e14c56173ef947da7141c455a62644 (patch) | |
tree | 892e3e3059661449f96e01835112afda8fb51713 /storage/connect | |
parent | e0c147c2da6e7daf3e5c76f91da6aaefad2affe6 (diff) | |
download | mariadb-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
Diffstat (limited to 'storage/connect')
-rw-r--r-- | storage/connect/CMakeLists.txt | 27 | ||||
-rw-r--r-- | storage/connect/filamdbf.cpp | 4 | ||||
-rwxr-xr-x | storage/connect/filamvct.cpp | 5 | ||||
-rw-r--r-- | storage/connect/ha_connect.cc | 110 | ||||
-rw-r--r-- | storage/connect/ha_connect.h | 3 | ||||
-rw-r--r-- | storage/connect/inihandl.cpp | 2 | ||||
-rw-r--r-- | storage/connect/javaconn.cpp | 2 | ||||
-rw-r--r-- | storage/connect/json.h | 1 | ||||
-rw-r--r-- | storage/connect/jsonudf.cpp | 50 | ||||
-rw-r--r-- | storage/connect/tabdos.cpp | 42 | ||||
-rw-r--r-- | storage/connect/tabfmt.cpp | 13 | ||||
-rw-r--r-- | storage/connect/user_connect.cc | 3 | ||||
-rw-r--r-- | storage/connect/value.cpp | 97 | ||||
-rw-r--r-- | storage/connect/value.h | 16 |
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); |