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:
parent
28a48633b5
commit
c8a6620661
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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};
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user