mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 14:03:07 +01:00
Introduce isc_dpb_version2 - format is WideTagged.
This commit is contained in:
parent
db5dc212ff
commit
443f261abf
@ -121,6 +121,32 @@ ClumpletReader::ClumpletReader(MemoryPool& pool, Kind k, const UCHAR* buffer, si
|
||||
rewind(); // this will set cur_offset and spbState
|
||||
}
|
||||
|
||||
ClumpletReader::ClumpletReader(const KindList* kl, const UCHAR* buffer, size_t buffLen, FPTR_VOID raise) :
|
||||
kind(kl->kind), static_buffer(buffer), static_buffer_end(buffer + buffLen)
|
||||
{
|
||||
if (buffLen)
|
||||
{
|
||||
while (kl->kind != EndOfList)
|
||||
{
|
||||
kind = kl->kind;
|
||||
if (getBufferTag() == kl->tag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
++kl;
|
||||
}
|
||||
if (kl->kind == EndOfList)
|
||||
{
|
||||
if (raise)
|
||||
{
|
||||
raise();
|
||||
}
|
||||
invalid_structure("Unknown tag value - missing in the list of possible");
|
||||
}
|
||||
}
|
||||
rewind(); // this will set cur_offset and spbState
|
||||
}
|
||||
|
||||
const UCHAR* ClumpletReader::getBuffer() const
|
||||
{
|
||||
return static_buffer;
|
||||
@ -672,5 +698,20 @@ bool ClumpletReader::getBoolean() const
|
||||
return length && ptr[0];
|
||||
}
|
||||
|
||||
ClumpletReader::SingleClumplet ClumpletReader::getClumplet() const
|
||||
{
|
||||
SingleClumplet rc;
|
||||
rc.tag = getClumpTag();
|
||||
rc.size = getClumpletSize(false, false, true);
|
||||
rc.data = getBytes();
|
||||
return rc;
|
||||
}
|
||||
|
||||
const ClumpletReader::KindList ClumpletReader::dpbList[] = {
|
||||
{ClumpletReader::Tagged, isc_dpb_version1},
|
||||
{ClumpletReader::WideTagged, isc_dpb_version2},
|
||||
{ClumpletReader::EndOfList, 0}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
@ -45,11 +45,24 @@ namespace Firebird {
|
||||
class ClumpletReader : protected AutoStorage
|
||||
{
|
||||
public:
|
||||
enum Kind {Tagged, UnTagged, SpbAttach, SpbStart, Tpb/*, SpbInfo*/, WideTagged, WideUnTagged, SpbItems};
|
||||
enum Kind {EndOfList, Tagged, UnTagged, SpbAttach, SpbStart, Tpb/*, SpbInfo*/, WideTagged, WideUnTagged, SpbItems};
|
||||
struct KindList
|
||||
{
|
||||
Kind kind;
|
||||
UCHAR tag;
|
||||
};
|
||||
struct SingleClumplet
|
||||
{
|
||||
UCHAR tag;
|
||||
size_t size;
|
||||
const UCHAR* data;
|
||||
};
|
||||
|
||||
// Constructor prepares an object from plain PB
|
||||
ClumpletReader(Kind k, const UCHAR* buffer, size_t buffLen);
|
||||
ClumpletReader(MemoryPool& pool, Kind k, const UCHAR* buffer, size_t buffLen);
|
||||
// Different versions of clumplets may have different kinds
|
||||
ClumpletReader(const KindList* kl, const UCHAR* buffer, size_t buffLen, FPTR_VOID raise = NULL);
|
||||
virtual ~ClumpletReader() { }
|
||||
|
||||
// Navigation in clumplet buffer
|
||||
@ -108,7 +121,7 @@ protected:
|
||||
void adjustSpbState();
|
||||
|
||||
size_t cur_offset;
|
||||
const Kind kind;
|
||||
Kind kind;
|
||||
UCHAR spbState; // Reflects state of spb parser/writer
|
||||
|
||||
// Methods are virtual so writer can override 'em
|
||||
@ -125,6 +138,9 @@ protected:
|
||||
// This is called when passed buffer appears invalid
|
||||
virtual void invalid_structure(const char* what) const;
|
||||
|
||||
// get the most generic representation of clumplet
|
||||
SingleClumplet getClumplet() const;
|
||||
|
||||
private:
|
||||
// Assignment and copy constructor not implemented.
|
||||
ClumpletReader(const ClumpletReader& from);
|
||||
@ -134,6 +150,10 @@ private:
|
||||
const UCHAR* static_buffer_end;
|
||||
|
||||
static SINT64 fromVaxInteger(const UCHAR* ptr, size_t length);
|
||||
|
||||
// Some frequently used kind lists
|
||||
public:
|
||||
static const KindList dpbList[];
|
||||
};
|
||||
|
||||
} // namespace Firebird
|
||||
|
@ -93,6 +93,19 @@ ClumpletWriter::ClumpletWriter(Kind k, size_t limit, const UCHAR* buffer, size_t
|
||||
rewind();
|
||||
}
|
||||
|
||||
ClumpletWriter::ClumpletWriter(const KindList* kl, size_t limit, const UCHAR* buffer, size_t buffLen) :
|
||||
ClumpletReader(kl, buffer, buffLen), sizeLimit(limit), kindList(kl), dynamic_buffer(getPool())
|
||||
{
|
||||
if (buffer && buffLen) {
|
||||
dynamic_buffer.push(buffer, buffLen);
|
||||
}
|
||||
else {
|
||||
initNewBuffer(kl->tag);
|
||||
}
|
||||
rewind();
|
||||
}
|
||||
|
||||
/*
|
||||
ClumpletWriter::ClumpletWriter(MemoryPool& given_pool, Kind k, size_t limit,
|
||||
const UCHAR* buffer, size_t buffLen, UCHAR tag) :
|
||||
ClumpletReader(given_pool, k, NULL, 0), sizeLimit(limit), dynamic_buffer(getPool())
|
||||
@ -105,9 +118,27 @@ ClumpletWriter::ClumpletWriter(MemoryPool& given_pool, Kind k, size_t limit,
|
||||
}
|
||||
rewind();
|
||||
}
|
||||
|
||||
*/
|
||||
void ClumpletWriter::reset(UCHAR tag)
|
||||
{
|
||||
if (kindList)
|
||||
{
|
||||
for (const KindList* kl = kindList; kl->kind != EndOfList; ++kl)
|
||||
{
|
||||
if (tag == kl->tag)
|
||||
{
|
||||
kind = kl->kind;
|
||||
dynamic_buffer.shrink(0);
|
||||
initNewBuffer(tag);
|
||||
rewind();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
invalid_structure("Unknown tag value - missing in the list of possible");
|
||||
}
|
||||
|
||||
dynamic_buffer.shrink(0);
|
||||
initNewBuffer(tag);
|
||||
rewind();
|
||||
@ -218,66 +249,75 @@ void ClumpletWriter::insertBytesLengthCheck(UCHAR tag, const UCHAR* bytes, const
|
||||
return;
|
||||
}
|
||||
|
||||
// Check length according to clumplet type
|
||||
const ClumpletType t = getClumpletType(tag);
|
||||
UCHAR lenSize = 0;
|
||||
switch (t)
|
||||
// Check length according to clumplet type
|
||||
// Perform structure upgrade when needed and possible
|
||||
for(;;)
|
||||
{
|
||||
case Wide:
|
||||
if (length > MAX_ULONG)
|
||||
const ClumpletType t = getClumpletType(tag);
|
||||
string m;
|
||||
|
||||
switch (t)
|
||||
{
|
||||
string m;
|
||||
m.printf("attempt to store %d bytes in a clumplet", length);
|
||||
case Wide:
|
||||
if (length > MAX_ULONG)
|
||||
{
|
||||
m.printf("attempt to store %d bytes in a clumplet", length);
|
||||
break;
|
||||
}
|
||||
lenSize = 4;
|
||||
break;
|
||||
case TraditionalDpb:
|
||||
if (length > MAX_UCHAR)
|
||||
{
|
||||
m.printf("attempt to store %d bytes in a clumplet with maximum size 255 bytes", length);
|
||||
break;
|
||||
}
|
||||
lenSize = 1;
|
||||
break;
|
||||
case SingleTpb:
|
||||
if (length > 0)
|
||||
{
|
||||
m.printf("attempt to store data in dataless clumplet");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case StringSpb:
|
||||
if (length > MAX_USHORT)
|
||||
{
|
||||
m.printf("attempt to store %d bytes in a clumplet", length);
|
||||
break;
|
||||
}
|
||||
lenSize = 2;
|
||||
break;
|
||||
case IntSpb:
|
||||
if (length != 4)
|
||||
{
|
||||
m.printf("attempt to store %d bytes in a clumplet, need 4", length);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ByteSpb:
|
||||
if (length != 1)
|
||||
{
|
||||
m.printf("attempt to store %d bytes in a clumplet, need 1", length);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (m.isEmpty())
|
||||
{
|
||||
// OK, no errors
|
||||
break;
|
||||
}
|
||||
|
||||
if (!upgradeVersion())
|
||||
{
|
||||
// can't uprgade - report failure
|
||||
usage_mistake(m.c_str());
|
||||
return;
|
||||
}
|
||||
lenSize = 4;
|
||||
break;
|
||||
case TraditionalDpb:
|
||||
if (length > MAX_UCHAR)
|
||||
{
|
||||
string m;
|
||||
m.printf("attempt to store %d bytes in a clumplet with maximum size 255 bytes", length);
|
||||
usage_mistake(m.c_str());
|
||||
return;
|
||||
}
|
||||
lenSize = 1;
|
||||
break;
|
||||
case SingleTpb:
|
||||
if (length > 0)
|
||||
{
|
||||
usage_mistake("attempt to store data in dataless clumplet");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case StringSpb:
|
||||
if (length > MAX_USHORT)
|
||||
{
|
||||
string m;
|
||||
m.printf("attempt to store %d bytes in a clumplet", length);
|
||||
usage_mistake(m.c_str());
|
||||
return;
|
||||
}
|
||||
lenSize = 2;
|
||||
break;
|
||||
case IntSpb:
|
||||
if (length != 4)
|
||||
{
|
||||
string m;
|
||||
m.printf("attempt to store %d bytes in a clumplet, need 4", length);
|
||||
usage_mistake(m.c_str());
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case ByteSpb:
|
||||
if (length != 1)
|
||||
{
|
||||
string m;
|
||||
m.printf("attempt to store %d bytes in a clumplet, need 1", length);
|
||||
usage_mistake(m.c_str());
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Check that resulting data doesn't overflow size limit
|
||||
@ -378,4 +418,63 @@ bool ClumpletWriter::deleteWithTag(UCHAR tag)
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool ClumpletWriter::upgradeVersion()
|
||||
{
|
||||
// Sanity check
|
||||
if (!kindList)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for required version - use highmost one
|
||||
const KindList* newest = kindList;
|
||||
for (const KindList* itr = kindList; itr->tag != EndOfList; ++itr)
|
||||
{
|
||||
if (itr->tag > newest->tag)
|
||||
{
|
||||
newest = itr;
|
||||
}
|
||||
}
|
||||
if (getBufferLength() && newest->tag <= getBufferTag())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy data to new clumplet writer
|
||||
size_t newPos = 0;
|
||||
ClumpletWriter newPb(newest->kind, sizeLimit, newest->tag);
|
||||
size_t currentPosition = cur_offset;
|
||||
for(rewind(); !isEof(); moveNext())
|
||||
{
|
||||
if (currentPosition == cur_offset)
|
||||
{
|
||||
newPos = newPb.cur_offset;
|
||||
}
|
||||
newPb.insertClumplet(getClumplet());
|
||||
newPb.moveNext();
|
||||
}
|
||||
|
||||
// Return it to current clumplet writer in new format
|
||||
dynamic_buffer.clear();
|
||||
kind = newest->kind;
|
||||
dynamic_buffer.push(newPb.dynamic_buffer.begin(), newPb.dynamic_buffer.getCount());
|
||||
|
||||
// Set pointer to correct position
|
||||
if (newPos)
|
||||
{
|
||||
cur_offset = newPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
rewind();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClumpletWriter::insertClumplet(const SingleClumplet& clumplet)
|
||||
{
|
||||
insertBytes(clumplet.tag, clumplet.data, clumplet.size);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -49,7 +49,10 @@ public:
|
||||
|
||||
// Create writer from a given buffer
|
||||
ClumpletWriter(Kind k, size_t limit, const UCHAR* buffer, size_t buffLen, UCHAR tag);
|
||||
ClumpletWriter(MemoryPool& pool, Kind k, size_t limit, const UCHAR* buffer, size_t buffLen, UCHAR tag);
|
||||
// ClumpletWriter(MemoryPool& pool, Kind k, size_t limit, const UCHAR* buffer, size_t buffLen, UCHAR tag);
|
||||
|
||||
// Create writer from a given buffer with possibly different clumplet version
|
||||
ClumpletWriter(const KindList* kl, size_t limit, const UCHAR* buffer = NULL, size_t buffLen = 0);
|
||||
|
||||
void reset(UCHAR tag);
|
||||
void reset(const UCHAR* buffer, const size_t buffLen);
|
||||
@ -68,6 +71,7 @@ public:
|
||||
void insertTime(UCHAR tag, ISC_TIME value) { insertInt(tag, value); }
|
||||
void insertDate(UCHAR tag, ISC_DATE value) { insertInt(tag, value); }
|
||||
void insertEndMarker(UCHAR tag);
|
||||
void insertClumplet(const SingleClumplet& clumplet);
|
||||
|
||||
// Delete currently selected clumplet from buffer
|
||||
void deleteClumplet();
|
||||
@ -81,8 +85,11 @@ protected:
|
||||
virtual const UCHAR* getBufferEnd() const;
|
||||
virtual void size_overflow();
|
||||
void insertBytesLengthCheck(UCHAR tag, const UCHAR* bytes, const size_t length);
|
||||
// upgrade clumplet version - obtain newest from kindList
|
||||
bool upgradeVersion();
|
||||
private:
|
||||
size_t sizeLimit;
|
||||
const KindList* kindList;
|
||||
|
||||
// Assignment and copy constructor not implemented.
|
||||
ClumpletWriter(const ClumpletWriter& from);
|
||||
|
@ -31,6 +31,8 @@
|
||||
/**********************************/
|
||||
|
||||
#define isc_dpb_version1 1
|
||||
#define isc_dpb_version2 2
|
||||
|
||||
#define isc_dpb_cdd_pathname 1
|
||||
#define isc_dpb_allocation 2
|
||||
#define isc_dpb_journal 3
|
||||
|
@ -43,7 +43,7 @@ UserManagement::UserManagement(jrd_tra* tra)
|
||||
ISC_STATUS_ARRAY status;
|
||||
Attachment* att = tra->tra_attachment;
|
||||
|
||||
ClumpletWriter dpb(ClumpletReader::Tagged, MAX_DPB_SIZE, isc_dpb_version1);
|
||||
ClumpletWriter dpb(ClumpletReader::dpbList, MAX_DPB_SIZE);
|
||||
dpb.insertByte(isc_dpb_gsec_attach, TRUE);
|
||||
dpb.insertString(isc_dpb_trusted_auth, att->att_user->usr_user_name);
|
||||
if (att->att_user->usr_flags & USR_trole)
|
||||
|
@ -356,7 +356,7 @@ bool Connection::isSameDatabase(thread_db* tdbb, const string& dbName,
|
||||
if (m_dbName != dbName)
|
||||
return false;
|
||||
|
||||
ClumpletWriter dpb(ClumpletReader::Tagged, MAX_DPB_SIZE, isc_dpb_version1);
|
||||
ClumpletWriter dpb(ClumpletReader::dpbList, MAX_DPB_SIZE);
|
||||
generateDPB(tdbb, dpb, user, pwd, role);
|
||||
|
||||
return m_dpb.simpleCompare(dpb);
|
||||
|
@ -4752,6 +4752,13 @@ static void find_intl_charset(thread_db* tdbb, Jrd::Attachment* attachment, cons
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
void dpbErrorRaise()
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_bad_dpb_form) <<
|
||||
Arg::Gds(isc_wrodpbver));
|
||||
}
|
||||
} // anonymous
|
||||
|
||||
void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_client_SQL_dialect)
|
||||
{
|
||||
@ -4788,13 +4795,7 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
|
||||
ERR_post(Arg::Gds(isc_bad_dpb_form));
|
||||
}
|
||||
|
||||
ClumpletReader rdr(ClumpletReader::Tagged, dpb, dpb_length);
|
||||
|
||||
if (rdr.getBufferTag() != isc_dpb_version1)
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_bad_dpb_form) <<
|
||||
Arg::Gds(isc_wrodpbver));
|
||||
}
|
||||
ClumpletReader rdr(ClumpletReader::dpbList, dpb, dpb_length, dpbErrorRaise);
|
||||
|
||||
dpb_utf8_filename = rdr.find(isc_dpb_utf8_filename);
|
||||
|
||||
|
@ -1383,8 +1383,8 @@ ISC_STATUS API_ROUTINE GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
// copy the file name to a temp buffer, since some of the following utilities can modify it
|
||||
|
||||
PathName org_filename(file_name, file_length ? file_length : strlen(file_name));
|
||||
ClumpletWriter newDpb(ClumpletReader::Tagged, MAX_DPB_SIZE,
|
||||
reinterpret_cast<const UCHAR*>(dpb), dpb_length, isc_dpb_version1);
|
||||
ClumpletWriter newDpb(ClumpletReader::dpbList, MAX_DPB_SIZE,
|
||||
reinterpret_cast<const UCHAR*>(dpb), dpb_length);
|
||||
|
||||
bool utfFilename = newDpb.find(isc_dpb_utf8_filename);
|
||||
|
||||
@ -1989,8 +1989,7 @@ ISC_STATUS API_ROUTINE GDS_CREATE_DATABASE(ISC_STATUS* user_status,
|
||||
// copy the file name to a temp buffer, since some of the following utilities can modify it
|
||||
|
||||
PathName org_filename(file_name, file_length ? file_length : strlen(file_name));
|
||||
ClumpletWriter newDpb(ClumpletReader::Tagged, MAX_DPB_SIZE,
|
||||
dpb, dpb_length, isc_dpb_version1);
|
||||
ClumpletWriter newDpb(ClumpletReader::dpbList, MAX_DPB_SIZE, dpb, dpb_length);
|
||||
|
||||
bool utfFilename = newDpb.find(isc_dpb_utf8_filename);
|
||||
|
||||
|
@ -285,8 +285,8 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status,
|
||||
Rdb* rdb = 0;
|
||||
|
||||
try {
|
||||
ClumpletWriter newDpb(ClumpletReader::Tagged, MAX_DPB_SIZE,
|
||||
reinterpret_cast<const UCHAR*>(dpb), dpb_length, isc_dpb_version1);
|
||||
ClumpletWriter newDpb(ClumpletReader::dpbList, MAX_DPB_SIZE,
|
||||
reinterpret_cast<const UCHAR*>(dpb), dpb_length);
|
||||
|
||||
#ifdef UNIX
|
||||
// If single user, return
|
||||
@ -813,8 +813,8 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status,
|
||||
|
||||
try
|
||||
{
|
||||
ClumpletWriter newDpb(ClumpletReader::Tagged, MAX_DPB_SIZE,
|
||||
reinterpret_cast<const UCHAR*>(dpb), dpb_length, isc_dpb_version1);
|
||||
ClumpletWriter newDpb(ClumpletReader::dpbList, MAX_DPB_SIZE,
|
||||
reinterpret_cast<const UCHAR*>(dpb), dpb_length);
|
||||
|
||||
#ifdef UNIX
|
||||
// If single user, return
|
||||
@ -5458,9 +5458,6 @@ static bool get_single_user(ClumpletReader& dpb)
|
||||
* otherwise.
|
||||
*
|
||||
******************************************/
|
||||
if (dpb.getBufferTag() != isc_dpb_version1)
|
||||
return false;
|
||||
|
||||
string su;
|
||||
if (dpb.find(isc_dpb_reserved)) {
|
||||
dpb.getString(su);
|
||||
|
@ -1057,12 +1057,7 @@ static void attach_database(rem_port* port, P_OP operation, P_ATCH* attach, PACK
|
||||
const UCHAR* dpb = attach->p_atch_dpb.cstr_address;
|
||||
const USHORT dl = attach->p_atch_dpb.cstr_length;
|
||||
|
||||
Firebird::ClumpletWriter dpb_buffer(Firebird::ClumpletReader::Tagged, MAX_SSHORT);
|
||||
|
||||
if (dl)
|
||||
dpb_buffer.reset(dpb, dl);
|
||||
else
|
||||
dpb_buffer.reset(isc_dpb_version1);
|
||||
Firebird::ClumpletWriter dpb_buffer(Firebird::ClumpletReader::dpbList, MAX_SSHORT, dpb, dl);
|
||||
|
||||
// remove trusted role if present (security measure)
|
||||
dpb_buffer.deleteWithTag(isc_dpb_trusted_role);
|
||||
@ -1131,11 +1126,7 @@ static void attach_database2(rem_port* port,
|
||||
send->p_operation = op_accept;
|
||||
FB_API_HANDLE handle = 0;
|
||||
|
||||
Firebird::ClumpletWriter dpb_buffer(Firebird::ClumpletReader::Tagged, MAX_SSHORT);
|
||||
if (dl)
|
||||
dpb_buffer.reset(dpb, dl);
|
||||
else
|
||||
dpb_buffer.reset(isc_dpb_version1);
|
||||
Firebird::ClumpletWriter dpb_buffer(Firebird::ClumpletReader::dpbList, MAX_SSHORT, dpb, dl);
|
||||
|
||||
#ifdef TRUSTED_AUTH
|
||||
// If we have trusted authentication, append it to database parameter block
|
||||
|
Loading…
Reference in New Issue
Block a user