8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 22:03:03 +01:00

Fixed CORE-2615 - Silent truncation when using utf8 parameters and utf8 client character set encoding

This commit is contained in:
asfernandes 2009-09-04 15:20:48 +00:00
parent 28a48633b5
commit c8a6620661
5 changed files with 139 additions and 79 deletions

View File

@ -134,13 +134,6 @@ static void integer_to_text(const dsc*, dsc*, Callbacks*);
static void string_to_datetime(const dsc*, GDS_TIMESTAMP*, const EXPECT_DATETIME, ErrorFunction);
static SINT64 hex_to_value(const char*& string, const char* end);
static bool transliterate(const dsc* from, dsc* to, CHARSET_ID& charset2, ErrorFunction err);
static Jrd::CharSet* getToCharset(CHARSET_ID charset2);
static void validateData(Jrd::CharSet* toCharSet, SLONG length, const UCHAR* q, ErrorFunction err);
static void validateLength(Jrd::CharSet* toCharSet, SLONG toLength, const UCHAR* start, const USHORT to_size, ErrorFunction err);
static CHARSET_ID getChid(const dsc* to);
static SLONG getCurDate();
static void isVersion4(bool& v4);
static void localError(const Firebird::Arg::StatusVector&);
class DummyException {};
@ -411,7 +404,7 @@ static void integer_to_text(const dsc* from, dsc* to, Callbacks* cb)
} while (++scale);
}
cb->validateLength(cb->getToCharset(to->getCharSet()), length, start, TEXT_LEN(to), cb->err);
cb->validateLength(cb->getToCharset(to->getCharSet()), length, start, TEXT_LEN(to));
// If padding is required, do it now.
@ -1430,7 +1423,7 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
cb->err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_string_truncation));
Jrd::CharSet* charSet = cb->getToCharset(to->getCharSet());
cb->validateData(charSet, from->dsc_length, from->dsc_address, cb->err);
cb->validateData(charSet, from->dsc_length, from->dsc_address);
memcpy(ptr, from->dsc_address, from->dsc_length);
l -= from->dsc_length;
@ -1486,7 +1479,7 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
*/
CHARSET_ID charset2;
if (cb->transliterate(from, to, charset2, cb->err))
if (cb->transliterate(from, to, charset2))
return;
{ // scope
@ -1510,7 +1503,7 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
{
case dtype_text:
length = MIN(length, to->dsc_length);
cb->validateData(toCharset, length, q, cb->err);
cb->validateData(toCharset, length, q);
toLength = length;
l -= length;
@ -1534,7 +1527,7 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
fb_assert(to->dsc_length > 0)
length = MIN(length, ULONG(to->dsc_length - 1));
cb->validateData(toCharset, length, q, cb->err);
cb->validateData(toCharset, length, q);
toLength = length;
l -= length;
@ -1544,7 +1537,7 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
case dtype_varying:
length = MIN(length, (ULONG(to->dsc_length) - sizeof(USHORT)));
cb->validateData(toCharset, length, q, cb->err);
cb->validateData(toCharset, length, q);
toLength = length;
l -= length;
@ -1556,7 +1549,7 @@ void CVT_move_common(const dsc* from, dsc* to, Callbacks* cb)
break;
}
cb->validateLength(toCharset, toLength, start, to_size, cb->err);
cb->validateLength(toCharset, toLength, start, to_size);
if (l)
{
@ -2628,45 +2621,68 @@ static SINT64 hex_to_value(const char*& string, const char* end)
return value;
}
static bool transliterate(const dsc*, dsc* to, CHARSET_ID& charset2, ErrorFunction)
namespace
{
charset2 = INTL_TTYPE(to);
return false;
}
class CommonCallbacks : public Callbacks
{
public:
CommonCallbacks()
: Callbacks(localError)
{
}
public:
virtual bool transliterate(const dsc* from, dsc* to, CHARSET_ID&);
virtual CHARSET_ID getChid(const dsc* d);
virtual Jrd::CharSet* getToCharset(CHARSET_ID charset2);
virtual void validateData(Jrd::CharSet* toCharset, SLONG length, const UCHAR* q);
virtual void validateLength(Jrd::CharSet* toCharset, SLONG toLength, const UCHAR* start,
const USHORT to_size);
virtual SLONG getCurDate();
virtual void isVersion4(bool& v4);
static Jrd::CharSet* getToCharset(CHARSET_ID)
{
return NULL;
}
public:
static CommonCallbacks instance;
};
CommonCallbacks CommonCallbacks::instance;
static void validateData(Jrd::CharSet*, SLONG, const UCHAR*, ErrorFunction)
{
}
bool CommonCallbacks::transliterate(const dsc*, dsc* to, CHARSET_ID& charset2)
{
charset2 = INTL_TTYPE(to);
return false;
}
Jrd::CharSet* CommonCallbacks::getToCharset(CHARSET_ID)
{
return NULL;
}
static void validateLength(Jrd::CharSet*, SLONG, const UCHAR*, const USHORT, ErrorFunction)
{
}
void CommonCallbacks::validateData(Jrd::CharSet*, SLONG, const UCHAR*)
{
}
void CommonCallbacks::validateLength(Jrd::CharSet*, SLONG, const UCHAR*, const USHORT)
{
}
static CHARSET_ID getChid(const dsc* d)
{
return INTL_TTYPE(d);
}
CHARSET_ID CommonCallbacks::getChid(const dsc* d)
{
return INTL_TTYPE(d);
}
SLONG CommonCallbacks::getCurDate()
{
return TimeStamp::getCurrentTimeStamp().value().timestamp_date;
}
static SLONG getCurDate()
{
return Firebird::TimeStamp::getCurrentTimeStamp().value().timestamp_date;
}
void CommonCallbacks::isVersion4(bool& /*v4*/)
{
}
} // namespace
static void isVersion4(bool& /*v4*/)
{
}
static void localError(const Firebird::Arg::StatusVector&)
{
throw DummyException();
@ -2685,8 +2701,5 @@ void CVT_move(const dsc* from, dsc* to, ErrorFunction err)
* Move (and possible convert) something to something else.
*
**************************************/
Callbacks toCommon = {transliterate, getChid, err, getToCharset,
validateData, validateLength, getCurDate, isVersion4};
CVT_move_common(from, to, &toCommon);
CVT_move_common(from, to, &CommonCallbacks::instance);
}

View File

@ -37,16 +37,30 @@ class CharSet;
namespace Firebird {
struct Callbacks
class Callbacks
{
bool (*transliterate)(const dsc* from, dsc* to, CHARSET_ID&, ErrorFunction err);
CHARSET_ID (*getChid)(const dsc* d);
ErrorFunction err;
Jrd::CharSet* (*getToCharset)(CHARSET_ID charset2);
void (*validateData)(Jrd::CharSet* toCharset, SLONG length, const UCHAR* q, ErrorFunction err);
void (*validateLength)(Jrd::CharSet* toCharset, SLONG toLength, const UCHAR* start, const USHORT to_size, ErrorFunction err);
SLONG (*getCurDate)();
void (*isVersion4)(bool& v4);
public:
Callbacks(ErrorFunction aErr)
: err(aErr)
{
}
virtual ~Callbacks()
{
}
public:
virtual bool transliterate(const dsc* from, dsc* to, CHARSET_ID&) = 0;
virtual CHARSET_ID getChid(const dsc* d) = 0;
virtual Jrd::CharSet* getToCharset(CHARSET_ID charset2) = 0;
virtual void validateData(Jrd::CharSet* toCharset, SLONG length, const UCHAR* q) = 0;
virtual void validateLength(Jrd::CharSet* toCharset, SLONG toLength, const UCHAR* start,
const USHORT to_size) = 0;
virtual SLONG getCurDate() = 0;
virtual void isVersion4(bool& v4) = 0;
public:
const ErrorFunction err;
};
}

View File

@ -29,6 +29,7 @@
#include "../dsql/dsql.h"
#include "gen/iberror.h"
#include "../jrd/jrd.h"
#include "../jrd/cvt_proto.h"
#include "../dsql/errd_proto.h"
#include "../dsql/movd_proto.h"
#include "../common/cvt.h"
@ -38,6 +39,23 @@ using namespace Firebird;
static void post_error(const Arg::StatusVector&);
namespace
{
class DsqlCallbacks : public EngineCallbacks
{
public:
DsqlCallbacks()
: EngineCallbacks(post_error)
{
}
public:
static DsqlCallbacks instance;
};
DsqlCallbacks DsqlCallbacks::instance;
} // namespace
/**
@ -52,7 +70,7 @@ static void post_error(const Arg::StatusVector&);
**/
void MOVD_move(const dsc* from, dsc* to)
{
CVT_move(from, to, post_error);
CVT_move_common(from, to, &DsqlCallbacks::instance);
}

View File

@ -88,15 +88,6 @@ using namespace Jrd;
using namespace Firebird;
static bool transliterate(const dsc* from, dsc* to, CHARSET_ID& charset2, ErrorFunction err);
static CharSet* getToCharset(CHARSET_ID charset2);
static void validateData(CharSet* toCharSet, SLONG length, const UCHAR* q, ErrorFunction err);
static void validateLength(CharSet* toCharSet, SLONG toLength, const UCHAR* start, const USHORT to_size, ErrorFunction err);
static CHARSET_ID getChid(const dsc* to);
static SLONG getCurDate();
static void isVersion4(bool& v4);
double CVT_date_to_double(const dsc* desc)
{
/**************************************
@ -376,7 +367,10 @@ GDS_TIMESTAMP CVT_get_timestamp(const dsc* desc)
}
static bool transliterate(const dsc* from, dsc* to, CHARSET_ID& charset2, ErrorFunction err)
EngineCallbacks EngineCallbacks::instance;
bool EngineCallbacks::transliterate(const dsc* from, dsc* to, CHARSET_ID& charset2)
{
CHARSET_ID charset1;
if (INTL_TTYPE(from) == ttype_dynamic)
@ -407,21 +401,22 @@ static bool transliterate(const dsc* from, dsc* to, CHARSET_ID& charset2, ErrorF
}
static CharSet* getToCharset(CHARSET_ID charset2)
CharSet* EngineCallbacks::getToCharset(CHARSET_ID charset2)
{
return charset2 == ttype_dynamic || charset2 == CS_METADATA ? NULL :
INTL_charset_lookup(NULL, charset2);
}
static void validateData(CharSet* toCharSet, SLONG length, const UCHAR* q, ErrorFunction err)
void EngineCallbacks::validateData(CharSet* toCharSet, SLONG length, const UCHAR* q)
{
if (toCharSet && !toCharSet->wellFormed(length, q))
err(Arg::Gds(isc_malformed_string));
}
static void validateLength(CharSet* toCharSet, SLONG toLength, const UCHAR* start, const USHORT to_size, ErrorFunction err)
void EngineCallbacks::validateLength(CharSet* toCharSet, SLONG toLength, const UCHAR* start,
const USHORT to_size)
{
if (toCharSet)
{
@ -439,7 +434,7 @@ static void validateLength(CharSet* toCharSet, SLONG toLength, const UCHAR* star
}
static CHARSET_ID getChid(const dsc* to)
CHARSET_ID EngineCallbacks::getChid(const dsc* to)
{
if (INTL_TTYPE(to) == ttype_dynamic)
return INTL_charset(NULL, INTL_TTYPE(to));
@ -448,7 +443,7 @@ static CHARSET_ID getChid(const dsc* to)
}
static SLONG getCurDate()
SLONG EngineCallbacks::getCurDate()
{
thread_db* tdbb = JRD_get_thread_data();
@ -462,7 +457,7 @@ static SLONG getCurDate()
}
static void isVersion4(bool& v4)
void EngineCallbacks::isVersion4(bool& v4)
{
thread_db* tdbb = JRD_get_thread_data();
@ -471,9 +466,3 @@ static void isVersion4(bool& v4)
v4 = tdbb->getRequest()->req_flags & req_blr_version4 ? true : false;
}
}
namespace Jrd
{
Callbacks toEngine = {transliterate, getChid, ERR_post, getToCharset,
validateData, validateLength, getCurDate, isVersion4};
}

View File

@ -33,13 +33,39 @@ GDS_DATE CVT_get_sql_date(const dsc*);
GDS_TIME CVT_get_sql_time(const dsc*);
GDS_TIMESTAMP CVT_get_timestamp(const dsc*);
namespace Jrd {
extern Firebird::Callbacks toEngine;
namespace Jrd
{
class EngineCallbacks : public Firebird::Callbacks
{
public:
EngineCallbacks(ErrorFunction aErr)
: Callbacks(aErr)
{
}
EngineCallbacks()
: Callbacks(ERR_post)
{
}
public:
virtual bool transliterate(const dsc* from, dsc* to, CHARSET_ID&);
virtual CHARSET_ID getChid(const dsc* d);
virtual CharSet* getToCharset(CHARSET_ID charset2);
virtual void validateData(CharSet* toCharset, SLONG length, const UCHAR* q);
virtual void validateLength(CharSet* toCharset, SLONG toLength, const UCHAR* start,
const USHORT to_size);
virtual SLONG getCurDate();
virtual void isVersion4(bool& v4);
public:
static EngineCallbacks instance;
};
}
inline void CVT_move(const dsc* from, dsc* to)
{
CVT_move_common(from, to, &Jrd::toEngine);
CVT_move_common(from, to, &Jrd::EngineCallbacks::instance);
}
#endif // JRD_CVT_PROTO_H