mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
19af1890b5
This commit replaces sprintf(buf, ...) with snprintf(buf, sizeof(buf), ...), specifically in the "easy" cases where buf is allocated with a size known at compile time. The changes make sure we are not write outside array/string bounds which will lead to undefined behaviour. In case the code is trying to write outside bounds - safe version of functions simply cut the string messages so we process this gracefully. All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services, Inc. bsonudf.cpp warnings cleanup by Daniel Black Reviewer: Daniel Black
441 lines
14 KiB
C++
441 lines
14 KiB
C++
/************ Xobject C++ Functions Source Code File (.CPP) ************/
|
|
/* Name: XOBJECT.CPP Version 2.5 */
|
|
/* */
|
|
/* (C) Copyright to the author Olivier BERTRAND 1998-2017 */
|
|
/* */
|
|
/* This file contains base XOBJECT class functions. */
|
|
/* Also here is the implementation of the CONSTANT class. */
|
|
/***********************************************************************/
|
|
|
|
/***********************************************************************/
|
|
/* Include mariaDB header file. */
|
|
/***********************************************************************/
|
|
#include "my_global.h"
|
|
#include "m_string.h"
|
|
|
|
/***********************************************************************/
|
|
/* Include required application header files */
|
|
/* global.h is header containing all global Plug declarations. */
|
|
/* plgdbsem.h is header containing the DB applic. declarations. */
|
|
/***********************************************************************/
|
|
#include "global.h"
|
|
#include "plgdbsem.h"
|
|
#include "xobject.h"
|
|
|
|
/***********************************************************************/
|
|
/* Macro definitions. */
|
|
/***********************************************************************/
|
|
#if defined(_DEBUG) || defined(DEBTRACE)
|
|
#define ASSERT(B) assert(B);
|
|
#else
|
|
#define ASSERT(B)
|
|
#endif
|
|
|
|
/***********************************************************************/
|
|
/* The one and only needed void object. */
|
|
/***********************************************************************/
|
|
XVOID Xvoid;
|
|
PXOB const pXVOID = &Xvoid; // Pointer used by other classes
|
|
|
|
/* ------------------------- Class XOBJECT --------------------------- */
|
|
|
|
/***********************************************************************/
|
|
/* GetCharValue: returns the Result value as a char string. */
|
|
/* Using GetCharValue provides no conversion from numeric types. */
|
|
/***********************************************************************/
|
|
PSZ XOBJECT::GetCharValue(void)
|
|
{
|
|
ASSERT(Value)
|
|
return Value->GetCharValue();
|
|
} // end of GetCharValue()
|
|
|
|
/***********************************************************************/
|
|
/* GetShortValue: returns the Result value as a short integer. */
|
|
/***********************************************************************/
|
|
short XOBJECT::GetShortValue(void)
|
|
{
|
|
ASSERT(Value)
|
|
return Value->GetShortValue();
|
|
} // end of GetShortValue
|
|
|
|
/***********************************************************************/
|
|
/* GetIntValue: returns the Result value as a int integer. */
|
|
/***********************************************************************/
|
|
int XOBJECT::GetIntValue(void)
|
|
{
|
|
ASSERT(Value)
|
|
return Value->GetIntValue();
|
|
} // end of GetIntValue
|
|
|
|
/***********************************************************************/
|
|
/* GetFloatValue: returns the Result value as a double float. */
|
|
/***********************************************************************/
|
|
double XOBJECT::GetFloatValue(void)
|
|
{
|
|
ASSERT(Value)
|
|
return Value->GetFloatValue();
|
|
} // end of GetFloatValue
|
|
|
|
/* ------------------------- Class CONSTANT -------------------------- */
|
|
|
|
/***********************************************************************/
|
|
/* CONSTANT public constructor. */
|
|
/***********************************************************************/
|
|
CONSTANT::CONSTANT(PGLOBAL g, void *value, short type)
|
|
{
|
|
if (!(Value = AllocateValue(g, value, (int)type)))
|
|
throw (int)TYPE_CONST;
|
|
|
|
Constant = true;
|
|
} // end of CONSTANT constructor
|
|
|
|
/***********************************************************************/
|
|
/* CONSTANT public constructor. */
|
|
/***********************************************************************/
|
|
CONSTANT::CONSTANT(PGLOBAL g, int n)
|
|
{
|
|
if (!(Value = AllocateValue(g, &n, TYPE_INT)))
|
|
throw (int)TYPE_CONST;
|
|
|
|
Constant = true;
|
|
} // end of CONSTANT constructor
|
|
|
|
/***********************************************************************/
|
|
/* GetLengthEx: returns an evaluation of the constant string length. */
|
|
/* Note: When converting from token to string, length has to be */
|
|
/* specified but we need the domain length, not the value length. */
|
|
/***********************************************************************/
|
|
int CONSTANT::GetLengthEx(void)
|
|
{
|
|
return Value->GetValLen();
|
|
} // end of GetLengthEx
|
|
|
|
/***********************************************************************/
|
|
/* Convert a constant to the given type. */
|
|
/***********************************************************************/
|
|
void CONSTANT::Convert(PGLOBAL g, int newtype)
|
|
{
|
|
if (Value->GetType() != newtype)
|
|
if (!(Value = AllocateValue(g, Value, newtype)))
|
|
throw (int)TYPE_CONST;
|
|
|
|
} // end of Convert
|
|
|
|
/***********************************************************************/
|
|
/* Compare: returns true if this object is equivalent to xp. */
|
|
/***********************************************************************/
|
|
bool CONSTANT::Compare(PXOB xp)
|
|
{
|
|
if (this == xp)
|
|
return true;
|
|
else if (xp->GetType() != TYPE_CONST)
|
|
return false;
|
|
else
|
|
return Value->IsEqual(xp->GetValue(), true);
|
|
|
|
} // end of Compare
|
|
|
|
#if 0
|
|
/***********************************************************************/
|
|
/* Rephrase: temporary implementation used by PlugRephraseSQL. */
|
|
/***********************************************************************/
|
|
bool CONSTANT::Rephrase(PGLOBAL g, PSZ work)
|
|
{
|
|
switch (Value->GetType()) {
|
|
case TYPE_STRING:
|
|
sprintf(work + strlen(work), "'%s'", Value->GetCharValue());
|
|
break;
|
|
case TYPE_SHORT:
|
|
sprintf(work + strlen(work), "%hd", Value->GetShortValue());
|
|
break;
|
|
case TYPE_INT:
|
|
case TYPE_DATE:
|
|
sprintf(work + strlen(work), "%d", Value->GetIntValue());
|
|
break;
|
|
case TYPE_DOUBLE:
|
|
sprintf(work + strlen(work), "%lf", Value->GetFloatValue());
|
|
break;
|
|
case TYPE_BIGINT:
|
|
sprintf(work + strlen(work), "%lld", Value->GetBigintValue());
|
|
break;
|
|
case TYPE_TINY:
|
|
sprintf(work + strlen(work), "%d", Value->GetTinyValue());
|
|
break;
|
|
default:
|
|
snprintf(g->Message, sizeof(g->Message), MSG(BAD_CONST_TYPE), Value->GetType());
|
|
return false;
|
|
} // endswitch
|
|
|
|
return false;
|
|
} // end of Rephrase
|
|
#endif // 0
|
|
|
|
/***********************************************************************/
|
|
/* Make file output of a constant object. */
|
|
/***********************************************************************/
|
|
void CONSTANT::Printf(PGLOBAL g, FILE *f, uint n)
|
|
{
|
|
Value->Printf(g, f, n);
|
|
} /* end of Printf */
|
|
|
|
/***********************************************************************/
|
|
/* Make string output of a constant object. */
|
|
/***********************************************************************/
|
|
void CONSTANT::Prints(PGLOBAL g, char *ps, uint z)
|
|
{
|
|
Value->Prints(g, ps, z);
|
|
} /* end of Prints */
|
|
|
|
/* -------------------------- Class STRING --------------------------- */
|
|
|
|
/***********************************************************************/
|
|
/* STRING public constructor for new char values. Alloc Size must be */
|
|
/* calculated because PlugSubAlloc rounds up size to multiple of 8. */
|
|
/***********************************************************************/
|
|
STRING::STRING(PGLOBAL g, uint n, PCSZ str)
|
|
{
|
|
G = g;
|
|
Length = (str) ? strlen(str) : 0;
|
|
|
|
if ((Strp = (PSZ)PlgDBSubAlloc(g, NULL, MY_MAX(n, Length) + 1))) {
|
|
if (str)
|
|
strcpy(Strp, str);
|
|
else
|
|
*Strp = 0;
|
|
|
|
Next = GetNext();
|
|
Size = (int)(Next - Strp);
|
|
Trc = false;
|
|
} else {
|
|
// This should normally never happen
|
|
Next = NULL;
|
|
Size = 0;
|
|
Trc = true;
|
|
} // endif Strp
|
|
|
|
} // end of STRING constructor
|
|
|
|
/***********************************************************************/
|
|
/* Reallocate the string memory and return the (new) position. */
|
|
/* If Next is equal to GetNext() this means that no new suballocation */
|
|
/* has been done. Then we can just increase the size of the current */
|
|
/* allocation and the Strp will remain pointing to the same memory. */
|
|
/***********************************************************************/
|
|
char *STRING::Realloc(uint len)
|
|
{
|
|
char *p;
|
|
bool b = (Next == GetNext());
|
|
|
|
p = (char*)PlgDBSubAlloc(G, NULL, b ? len - Size : len);
|
|
|
|
if (!p) {
|
|
// No more room in Sarea; this is very unlikely
|
|
strcpy(G->Message, "No more room in work area");
|
|
Trc = true;
|
|
return NULL;
|
|
} // endif p
|
|
|
|
if (b)
|
|
p = Strp;
|
|
|
|
Next = GetNext();
|
|
Size = (int)(Next - p);
|
|
return p;
|
|
} // end of Realloc
|
|
|
|
/***********************************************************************/
|
|
/* Set a STRING new PSZ value. */
|
|
/***********************************************************************/
|
|
bool STRING::Set(PCSZ s)
|
|
{
|
|
if (!s)
|
|
return false;
|
|
|
|
uint len = strlen(s) + 1;
|
|
|
|
if (len > Size) {
|
|
char *p = Realloc(len);
|
|
|
|
if (!p)
|
|
return true;
|
|
else
|
|
Strp = p;
|
|
|
|
} // endif n
|
|
|
|
strcpy(Strp, s);
|
|
Length = len - 1;
|
|
return false;
|
|
} // end of Set
|
|
|
|
/***********************************************************************/
|
|
/* Set a STRING new PSZ value. */
|
|
/***********************************************************************/
|
|
bool STRING::Set(char *s, uint n)
|
|
{
|
|
if (!s)
|
|
return false;
|
|
|
|
uint len = strnlen(s, n) + 1;
|
|
|
|
if (len > Size) {
|
|
char *p = Realloc(len);
|
|
|
|
if (!p)
|
|
return true;
|
|
else
|
|
Strp = p;
|
|
|
|
} // endif n
|
|
|
|
strncpy(Strp, s, n);
|
|
Length = len - 1;
|
|
return false;
|
|
} // end of Set
|
|
|
|
/***********************************************************************/
|
|
/* Append a char* to a STRING. */
|
|
/***********************************************************************/
|
|
bool STRING::Append(const char *s, uint ln, bool nq)
|
|
{
|
|
if (!s)
|
|
return false;
|
|
|
|
uint i, len = Length + ln + 1;
|
|
|
|
if (len > Size) {
|
|
char *p = Realloc(len);
|
|
|
|
if (!p)
|
|
return true;
|
|
else if (p != Strp) {
|
|
strcpy(p, Strp);
|
|
Strp = p;
|
|
} // endif p
|
|
|
|
} // endif n
|
|
|
|
if (nq) {
|
|
for (i = 0; i < ln; i++)
|
|
switch (s[i]) {
|
|
case '\\': Strp[Length++] = '\\'; Strp[Length++] = '\\'; break;
|
|
case '\0': Strp[Length++] = '\\'; Strp[Length++] = '0'; break;
|
|
case '\'': Strp[Length++] = '\\'; Strp[Length++] = '\''; break;
|
|
case '\n': Strp[Length++] = '\\'; Strp[Length++] = 'n'; break;
|
|
case '\r': Strp[Length++] = '\\'; Strp[Length++] = 'r'; break;
|
|
case '\032': Strp[Length++] = '\\'; Strp[Length++] = 'Z'; break;
|
|
default: Strp[Length++] = s[i];
|
|
} // endswitch s[i]
|
|
|
|
} else
|
|
for (i = 0; i < ln && s[i]; i++)
|
|
Strp[Length++] = s[i];
|
|
|
|
Strp[Length] = 0;
|
|
return false;
|
|
} // end of Append
|
|
|
|
/***********************************************************************/
|
|
/* Append a PCSZ to a STRING. */
|
|
/***********************************************************************/
|
|
bool STRING::Append(PCSZ s)
|
|
{
|
|
if (!s)
|
|
return false;
|
|
|
|
uint len = Length + strlen(s) + 1;
|
|
|
|
if (len > Size) {
|
|
char *p = Realloc(len);
|
|
|
|
if (!p)
|
|
return true;
|
|
else if (p != Strp) {
|
|
strcpy(p, Strp);
|
|
Strp = p;
|
|
} // endif p
|
|
|
|
} // endif n
|
|
|
|
strcpy(Strp + Length, s);
|
|
Length = len - 1;
|
|
return false;
|
|
} // end of Append
|
|
|
|
/***********************************************************************/
|
|
/* Append a STRING to a STRING. */
|
|
/***********************************************************************/
|
|
bool STRING::Append(STRING &str)
|
|
{
|
|
return Append(str.GetStr());
|
|
} // end of Append
|
|
|
|
/***********************************************************************/
|
|
/* Append a char to a STRING. */
|
|
/***********************************************************************/
|
|
bool STRING::Append(char c)
|
|
{
|
|
if (Length + 2 > Size) {
|
|
char *p = Realloc(Length + 2);
|
|
|
|
if (!p)
|
|
return true;
|
|
else if (p != Strp) {
|
|
strcpy(p, Strp);
|
|
Strp = p;
|
|
} // endif p
|
|
|
|
} // endif n
|
|
|
|
Strp[Length++] = c;
|
|
Strp[Length] = 0;
|
|
return false;
|
|
} // end of Append
|
|
|
|
/***********************************************************************/
|
|
/* Append a quoted PSZ to a STRING. */
|
|
/***********************************************************************/
|
|
bool STRING::Append_quoted(PCSZ s)
|
|
{
|
|
bool b = Append('\'');
|
|
|
|
if (s) for (const char *p = s; !b && *p; p++)
|
|
switch (*p) {
|
|
case '\'':
|
|
case '\\':
|
|
case '\t':
|
|
case '\n':
|
|
case '\r':
|
|
case '\b':
|
|
case '\f': b |= Append('\\');
|
|
// fall through
|
|
default:
|
|
b |= Append(*p);
|
|
break;
|
|
} // endswitch *p
|
|
|
|
return (b |= Append('\''));
|
|
} // end of Append_quoted
|
|
|
|
/***********************************************************************/
|
|
/* Resize to given length but only when last suballocated. */
|
|
/* New size should be greater than string length. */
|
|
/***********************************************************************/
|
|
bool STRING::Resize(uint newsize)
|
|
{
|
|
if (Next == GetNext() && newsize > Length) {
|
|
uint nsz = (((signed)newsize + 7) / 8) * 8;
|
|
int diff = (signed)Size - (signed)nsz;
|
|
PPOOLHEADER pp = (PPOOLHEADER)G->Sarea;
|
|
|
|
if ((signed)pp->FreeBlk + diff < 0)
|
|
return true; // Out of memory
|
|
|
|
pp->To_Free -= diff;
|
|
pp->FreeBlk += diff;
|
|
Size = nsz;
|
|
return false;
|
|
} else
|
|
return newsize > Size;
|
|
|
|
} // end of Resize
|