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

Fixed CORE-6248: A number of errors when database name is longer than 255 symbols

This commit is contained in:
AlexPeshkoff 2020-03-04 19:02:46 +03:00
parent b11189f1bb
commit 684e17d0e4
17 changed files with 141 additions and 60 deletions

View File

@ -1942,6 +1942,12 @@ C --
PARAMETER (GDS__dyn_no_create_priv = 335545264)
INTEGER*4 GDS__suspend_without_returns
PARAMETER (GDS__suspend_without_returns = 335545265)
INTEGER*4 GDS__truncate_warn
PARAMETER (GDS__truncate_warn = 335545266)
INTEGER*4 GDS__truncate_monitor
PARAMETER (GDS__truncate_monitor = 335545267)
INTEGER*4 GDS__truncate_context
PARAMETER (GDS__truncate_context = 335545268)
INTEGER*4 GDS__gfix_db_name
PARAMETER (GDS__gfix_db_name = 335740929)
INTEGER*4 GDS__gfix_invalid_sw

View File

@ -1937,6 +1937,12 @@ const
gds_dyn_no_create_priv = 335545264;
isc_suspend_without_returns = 335545265;
gds_suspend_without_returns = 335545265;
isc_truncate_warn = 335545266;
gds_truncate_warn = 335545266;
isc_truncate_monitor = 335545267;
gds_truncate_monitor = 335545267;
isc_truncate_context = 335545268;
gds_truncate_context = 335545268;
isc_gfix_db_name = 335740929;
gds_gfix_db_name = 335740929;
isc_gfix_invalid_sw = 335740930;

View File

@ -1666,25 +1666,22 @@ static void prompt_for_name(SCHAR* name, int length)
//
// Write an attribute starting with a null terminated string.
//
static void put_asciz( SCHAR attribute, const TEXT* string)
static void put_asciz( SCHAR attribute, const TEXT* str)
{
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
SSHORT l = 0;
for (const TEXT *p = string; *p; p++)
USHORT l = strlen(str);
if (l > MAX_UCHAR)
{
l++;
BURP_print(false, 343, SafeArg() << int(attribute) << "put_asciz()" << USHORT(MAX_UCHAR));
// msg 343: text for attribute @1 is too large in @2, truncating to @3 bytes
l = MAX_UCHAR;
}
fb_assert(l <= MAX_UCHAR);
put(tdgbl, attribute);
put(tdgbl, l);
if (l)
{
do {
put(tdgbl, *string++);
} while (--l);
}
while (l--)
put(tdgbl, *str++);
}

View File

@ -431,7 +431,7 @@ static void integer_to_text(const dsc* from, dsc* to, Callbacks* cb)
// fits. Keep in mind that routine handles both string and varying
// string fields.
const USHORT length = l + neg + decimal + pad_count;
USHORT length = l + neg + decimal + pad_count;
if ((to->dsc_dtype == dtype_text && length > to->dsc_length) ||
(to->dsc_dtype == dtype_cstring && length >= to->dsc_length) ||
@ -469,7 +469,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));
length = cb->validateLength(cb->getToCharset(to->getCharSet()), length, start, TEXT_LEN(to));
// If padding is required, do it now.
@ -1802,8 +1802,32 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
const UCHAR* start = to->dsc_address;
UCHAR fill_char = ASCII_SPACE;
Jrd::CharSet* toCharset = cb->getToCharset(charset2);
ULONG toLength = 0;
ULONG fill;
switch (to->dsc_dtype)
{
case dtype_text:
length = MIN(length, to->dsc_length);
break;
case dtype_cstring:
// Note: Following is only correct for narrow and
// multibyte character sets which use a zero
// byte to represent end-of-string
fb_assert(to->dsc_length > 0);
length = MIN(length, ULONG(to->dsc_length - 1));
break;
case dtype_varying:
length = to->dsc_length > sizeof(USHORT) ?
MIN(length, (ULONG(to->dsc_length) - sizeof(USHORT))) : 0;
break;
}
cb->validateData(toCharset, length, q);
ULONG toLength = cb->validateLength(toCharset, length, q, to_size);
len -= toLength;
ULONG fill = ULONG(to->dsc_length) - toLength;
if (charset2 == ttype_binary)
fill_char = 0x00;
@ -1811,14 +1835,7 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
switch (to->dsc_dtype)
{
case dtype_text:
length = MIN(length, to->dsc_length);
cb->validateData(toCharset, length, q);
toLength = length;
len -= length;
fill = ULONG(to->dsc_length) - length;
CVT_COPY_BUFF(q, p, length);
CVT_COPY_BUFF(q, p, toLength);
if (fill > 0)
{
memset(p, fill_char, fill);
@ -1830,49 +1847,32 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
break;
case dtype_cstring:
// Note: Following is only correct for narrow and
// multibyte character sets which use a zero
// byte to represent end-of-string
fb_assert(to->dsc_length > 0);
length = MIN(length, ULONG(to->dsc_length - 1));
cb->validateData(toCharset, length, q);
toLength = length;
len -= length;
CVT_COPY_BUFF(q, p, length);
CVT_COPY_BUFF(q, p, toLength);
*p = 0;
break;
case dtype_varying:
if (to->dsc_length > sizeof(USHORT))
{
length = MIN(length, (ULONG(to->dsc_length) - sizeof(USHORT)));
cb->validateData(toCharset, length, q);
toLength = length;
len -= length;
// TMN: Here we should really have the following fb_assert
// fb_assert(length <= MAX_USHORT);
((vary*) p)->vary_length = (USHORT) length;
((vary*) p)->vary_length = (USHORT) toLength;
start = p = reinterpret_cast<UCHAR*>(((vary*) p)->vary_string);
CVT_COPY_BUFF(q, p, length);
CVT_COPY_BUFF(q, p, toLength);
}
else
memset(to->dsc_address, 0, to->dsc_length); // the best we can do
break;
}
cb->validateLength(toCharset, toLength, start, to_size);
if (len)
if (len && toLength == length)
{
// Scan the truncated string to ensure only spaces lost
// Warning: it is correct only for narrow and multi-byte
// character sets which use ASCII or NULL for the SPACE character
do {
if (*q++ != fill_char)
if (*q++ != fill_char && toLength == length)
{
cb->err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_string_truncation) <<
Arg::Gds(isc_trunc_limits) <<
@ -3545,7 +3545,7 @@ namespace
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,
virtual ULONG validateLength(Jrd::CharSet* toCharset, ULONG toLength, const UCHAR* start,
const USHORT to_size);
virtual SLONG getLocalDate();
virtual ISC_TIMESTAMP getCurrentGmtTimeStamp();
@ -3568,8 +3568,9 @@ namespace
{
}
void CommonCallbacks::validateLength(Jrd::CharSet*, SLONG, const UCHAR*, const USHORT)
ULONG CommonCallbacks::validateLength(Jrd::CharSet*, ULONG l, const UCHAR*, const USHORT)
{
return l;
}
CHARSET_ID CommonCallbacks::getChid(const dsc* d)

View File

@ -58,7 +58,7 @@ public:
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,
virtual ULONG validateLength(Jrd::CharSet* toCharset, ULONG toLength, const UCHAR* start,
const USHORT to_size) = 0;
virtual SLONG getLocalDate() = 0;
virtual ISC_TIMESTAMP getCurrentGmtTimeStamp() = 0;

View File

@ -967,6 +967,9 @@ static const struct {
{"cannot_read_new_blob", 335545263},
{"dyn_no_create_priv", 335545264},
{"suspend_without_returns", 335545265},
{"truncate_warn", 335545266},
{"truncate_monitor", 335545267},
{"truncate_context", 335545268},
{"gfix_db_name", 335740929},
{"gfix_invalid_sw", 335740930},
{"gfix_incmp_sw", 335740932},

View File

@ -1001,6 +1001,9 @@ const ISC_STATUS isc_cannot_update_old_blob = 335545262L;
const ISC_STATUS isc_cannot_read_new_blob = 335545263L;
const ISC_STATUS isc_dyn_no_create_priv = 335545264L;
const ISC_STATUS isc_suspend_without_returns = 335545265L;
const ISC_STATUS isc_truncate_warn = 335545266L;
const ISC_STATUS isc_truncate_monitor = 335545267L;
const ISC_STATUS isc_truncate_context = 335545268L;
const ISC_STATUS isc_gfix_db_name = 335740929L;
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
@ -1491,7 +1494,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L;
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
const ISC_STATUS isc_err_max = 1435;
const ISC_STATUS isc_err_max = 1438;
#else /* c definitions */
@ -2462,6 +2465,9 @@ const ISC_STATUS isc_err_max = 1435;
#define isc_cannot_read_new_blob 335545263L
#define isc_dyn_no_create_priv 335545264L
#define isc_suspend_without_returns 335545265L
#define isc_truncate_warn 335545266L
#define isc_truncate_monitor 335545267L
#define isc_truncate_context 335545268L
#define isc_gfix_db_name 335740929L
#define isc_gfix_invalid_sw 335740930L
#define isc_gfix_incmp_sw 335740932L
@ -2952,7 +2958,7 @@ const ISC_STATUS isc_err_max = 1435;
#define isc_trace_switch_param_miss 337182758L
#define isc_trace_param_act_notcompat 337182759L
#define isc_trace_mandatory_switch_miss 337182760L
#define isc_err_max 1435
#define isc_err_max 1438
#endif

View File

@ -970,6 +970,9 @@ Data source : @4"}, /* eds_statement */
{335545263, "cannot read from new BLOB"}, /* cannot_read_new_blob */
{335545264, "No permission for CREATE @1 operation"}, /* dyn_no_create_priv */
{335545265, "SUSPEND could not be used without RETURNS clause in PROCEDURE or EXECUTE BLOCK"}, /* suspend_without_returns */
{335545266, "String truncated warning due to the following reason"}, /* truncate_warn */
{335545267, "Monitoring data does not fit into the field"}, /* truncate_monitor */
{335545268, "Engine data does not fit into return value of system function"}, /* truncate_context */
{335740929, "data base file name (@1) already given"}, /* gfix_db_name */
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */

View File

@ -966,6 +966,9 @@ static const struct {
{335545263, -402}, /* 943 cannot_read_new_blob */
{335545264, -901}, /* 944 dyn_no_create_priv */
{335545265, -901}, /* 945 suspend_without_returns */
{335545266, 304}, /* 946 truncate_warn */
{335545267, 304}, /* 947 truncate_monitor */
{335545268, 304}, /* 948 truncate_context */
{335740929, -901}, /* 1 gfix_db_name */
{335740930, -901}, /* 2 gfix_invalid_sw */
{335740932, -901}, /* 4 gfix_incmp_sw */

View File

@ -966,6 +966,9 @@ static const struct {
{335545263, "42000"}, // 943 cannot_read_new_blob
{335545264, "42000"}, // 944 dyn_no_create_priv
{335545265, "42000"}, // 945 suspend_without_returns
{335545266, "01004"}, // 946 truncate_warn
{335545267, "01004"}, // 947 truncate_monitor
{335545268, "01004"}, // 948 truncate_context
{335740929, "00000"}, // 1 gfix_db_name
{335740930, "00000"}, // 2 gfix_invalid_sw
{335740932, "00000"}, // 4 gfix_incmp_sw

View File

@ -44,6 +44,7 @@
#include "../jrd/mov_proto.h"
#include "../jrd/opt_proto.h"
#include "../jrd/pag_proto.h"
#include "../jrd/cvt_proto.h"
#include "../jrd/CryptoManager.h"
#include "../jrd/Relation.h"
@ -727,7 +728,9 @@ void SnapshotData::putField(thread_db* tdbb, Record* record, const DumpField& fi
{
dsc from_desc;
from_desc.makeText(field.length, CS_METADATA, (UCHAR*) field.data);
MOV_move(tdbb, &from_desc, &to_desc);
TruncateCallbacks tcb(isc_truncate_monitor);
CVT_move_common(&from_desc, &to_desc, 0, &tcb); // no need in decimal status for string=>string move
}
}
else if (field.type == VALUE_BOOLEAN)

View File

@ -169,6 +169,7 @@ const HashAlgorithmDescriptor* HashAlgorithmDescriptor::find(const char* name)
// constants
const int oneDay = 86400;
const unsigned getContextLen = 255;
// auxiliary functions
void add10msec(ISC_TIMESTAMP* v, SINT64 msec, SINT64 multiplier);
@ -1220,7 +1221,7 @@ void makeGetSetContext(DataTypeUtilBase* /*dataTypeUtil*/, const SysFunction* fu
result->makeLong(0);
else
{
result->makeVarying(255, ttype_none);
result->makeVarying(getContextLen, ttype_none);
result->setNullable(true);
}
}
@ -4281,7 +4282,13 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar
}
dsc result;
result.makeText(resultStr.length(), resultType,
unsigned l = resultStr.length();
if (l > getContextLen)
{
l = getContextLen;
ERR_post_warning(Arg::Warning(isc_truncate_warn) << Arg::Warning(isc_truncate_context));
}
result.makeText(l, resultType,
(UCHAR*) const_cast<char*>(resultStr.c_str())); // safe const_cast
EVL_make_value(tdbb, &result, impure);

View File

@ -479,14 +479,11 @@ void EngineCallbacks::validateData(CharSet* toCharSet, SLONG length, const UCHAR
}
void EngineCallbacks::validateLength(CharSet* toCharSet, SLONG toLength, const UCHAR* start,
ULONG EngineCallbacks::validateLength(CharSet* toCharSet, ULONG toLength, const UCHAR* start,
const USHORT to_size)
{
if (toCharSet && toCharSet->isMultiByte())
{
Jrd::thread_db* tdbb = NULL;
SET_TDBB(tdbb);
const ULONG src_len = toCharSet->length(toLength, start, false);
const ULONG dest_len = (ULONG) to_size / toCharSet->maxBytesPerChar();
@ -496,6 +493,31 @@ void EngineCallbacks::validateLength(CharSet* toCharSet, SLONG toLength, const U
Arg::Gds(isc_trunc_limits) << Arg::Num(dest_len) << Arg::Num(src_len));
}
}
return toLength;
}
ULONG TruncateCallbacks::validateLength(CharSet* toCharSet, ULONG toLength, const UCHAR* start,
const USHORT to_size)
{
if (toCharSet && toCharSet->isMultiByte())
{
const ULONG dest_len = (ULONG) to_size / toCharSet->maxBytesPerChar();
for (bool first = true; ; first = false)
{
const ULONG src_len = toCharSet->length(toLength, start, false);
if (src_len <= dest_len)
break;
toLength -= (src_len - dest_len); // truncate
if (first)
ERR_post_warning(Arg::Warning(isc_truncate_warn) << Arg::Warning(truncateReason));
}
}
return toLength;
}

View File

@ -57,7 +57,7 @@ namespace Jrd
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,
virtual ULONG validateLength(CharSet* toCharset, ULONG toLength, const UCHAR* start,
const USHORT to_size);
virtual SLONG getLocalDate();
virtual ISC_TIMESTAMP getCurrentGmtTimeStamp();
@ -67,6 +67,21 @@ namespace Jrd
public:
static Firebird::GlobalPtr<EngineCallbacks> instance;
};
class TruncateCallbacks : public EngineCallbacks
{
public:
explicit TruncateCallbacks(ISC_STATUS tr)
: EngineCallbacks(ERR_post), truncateReason(tr)
{
}
virtual ULONG validateLength(CharSet* toCharset, ULONG toLength, const UCHAR* start,
const USHORT to_size);
private:
const ISC_STATUS truncateReason;
};
}
inline void CVT_move(const dsc* from, dsc* to, Firebird::DecimalStatus decSt)

View File

@ -1,7 +1,7 @@
/* MAX_NUMBER is the next number to be used, always one more than the highest message number. */
set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?);
--
('2020-02-04 12:10:00', 'JRD', 0, 946)
('2020-03-04 16:39:50', 'JRD', 0, 949)
('2015-03-17 18:33:00', 'QLI', 1, 533)
('2018-03-17 12:00:00', 'GFIX', 3, 136)
('1996-11-07 13:39:40', 'GPRE', 4, 1)

View File

@ -1053,6 +1053,9 @@ Data source : @4', NULL, NULL)
('cannot_read_new_blob', 'BLB_get_segment', 'blb.cpp', NULL, 0, 943, NULL, 'cannot read from new BLOB', NULL, NULL);
('dyn_no_create_priv', NULL, 'scl.epp', NULL, 0, 944, NULL, 'No permission for CREATE @1 operation', NULL, NULL);
('suspend_without_returns', NULL, 'StmtNodes.cpp', NULL, 0, 945, NULL, 'SUSPEND could not be used without RETURNS clause in PROCEDURE or EXECUTE BLOCK', NULL, NULL);
('truncate_warn', NULL, 'cvt.cpp', NULL, 0, 946, NULL, 'String truncated warning due to the following reason', NULL, NULL);
('truncate_monitor', NULL, 'Monitoring.cpp', NULL, 0, 947, NULL, 'Monitoring data does not fit into the field', NULL, NULL);
('truncate_context', NULL, 'SysFunction.cpp', NULL, 0, 948, NULL, 'Engine data does not fit into return value of system function', NULL, NULL);
-- QLI
(NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL);
(NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL);
@ -2507,7 +2510,7 @@ ERROR: Backup incomplete', NULL, NULL);
('gbak_max_dbkey_length', 'update_view_dbkey_lengths', 'restore.epp', NULL, 12, 340, NULL, 'value greater than @1 when calculating length of rdb$db_key for view @2', NULL, NULL);
('gbak_invalid_metadata', 'general_on_error', 'restore.epp', NULL, 12, 341, NULL, 'Invalid metadata detected. Use -FIX_FSS_METADATA option.', NULL, NULL);
('gbak_invalid_data', 'get_data', 'restore.epp', NULL, 12, 342, NULL, 'Invalid data detected. Use -FIX_FSS_DATA option.', NULL, NULL);
(NULL, 'put_asciz', 'backup.epp', NULL, 12, 343, NULL, 'text for attribute @1 is too large in @2, truncating to @3 bytes', NULL, NULL);
(NULL, 'put_asciz', NULL, NULL, 12, 343, NULL, 'text for attribute @1 is too large in @2, truncating to @3 bytes', NULL, NULL);
('gbak_inv_bkup_ver2', 'restore.epp', 'burp.cpp', 'do not change the param order', 12, 344, NULL, 'Expected backup version @2..@3. Found @1', NULL, NULL);
(NULL, 'write_relations', 'backup.epp', NULL, 12, 345, NULL, ' writing view @1', NULL, NULL);
(NULL, 'get_relation', 'restore.epp', NULL, 12, 346, NULL, ' table @1 is a view', NULL, NULL);

View File

@ -952,6 +952,9 @@ set bulk_insert INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, FA
(-402, '42', '000', 0, 943, 'cannot_read_new_blob', NULL, NULL)
(-901, '42', '000', 0, 944, 'dyn_no_create_priv', NULL, NULL)
(-901, '42', '000', 0, 945, 'suspend_without_returns', NULL, NULL)
(304, '01', '004', 0, 946, 'truncate_warn', NULL, NULL)
(304, '01', '004', 0, 947, 'truncate_monitor', NULL, NULL)
(304, '01', '004', 0, 948, 'truncate_context', NULL, NULL)
-- GFIX
(-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL)
(-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL)