mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 03:23:04 +01:00
Fixed CORE-6432: Possible buffer overflow in client library in Attachment::getInfo() call
This commit is contained in:
parent
ca77a37910
commit
f88c95acb6
@ -86,7 +86,8 @@ void ClumpletReader::dump() const
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
ClumpletDump d(kind, getBuffer(), getBufferLength());
|
ClumpletDump d(kind, getBuffer(), getBufferLength());
|
||||||
int t = (kind == SpbStart || kind == UnTagged || kind == WideUnTagged || kind == SpbResponse) ? -1 : d.getBufferTag();
|
int t = (kind == SpbStart || kind == UnTagged || kind == WideUnTagged || kind == SpbResponse || kind == InfoResponse) ?
|
||||||
|
-1 : d.getBufferTag();
|
||||||
gds__log("Tag=%d Offset=%d Length=%d Eof=%d\n", t, getCurOffset(), getBufferLength(), isEof());
|
gds__log("Tag=%d Offset=%d Length=%d Eof=%d\n", t, getCurOffset(), getBufferLength(), isEof());
|
||||||
for (d.rewind(); !(d.isEof()); d.moveNext())
|
for (d.rewind(); !(d.isEof()); d.moveNext())
|
||||||
{
|
{
|
||||||
@ -240,6 +241,7 @@ UCHAR ClumpletReader::getBufferTag() const
|
|||||||
case SpbSendItems:
|
case SpbSendItems:
|
||||||
case SpbReceiveItems:
|
case SpbReceiveItems:
|
||||||
case SpbResponse:
|
case SpbResponse:
|
||||||
|
case InfoResponse:
|
||||||
usage_mistake("buffer is not tagged");
|
usage_mistake("buffer is not tagged");
|
||||||
return 0;
|
return 0;
|
||||||
case SpbAttach:
|
case SpbAttach:
|
||||||
@ -535,6 +537,16 @@ ClumpletReader::ClumpletType ClumpletReader::getClumpletType(UCHAR tag) const
|
|||||||
}
|
}
|
||||||
invalid_structure("unrecognized service response tag", tag);
|
invalid_structure("unrecognized service response tag", tag);
|
||||||
break;
|
break;
|
||||||
|
case InfoResponse:
|
||||||
|
switch (tag)
|
||||||
|
{
|
||||||
|
case isc_info_end:
|
||||||
|
case isc_info_truncated:
|
||||||
|
case isc_info_data_not_ready:
|
||||||
|
case isc_info_flag_end:
|
||||||
|
return SingleTpb;
|
||||||
|
}
|
||||||
|
return StringSpb;
|
||||||
}
|
}
|
||||||
invalid_structure("unknown clumplet kind", kind);
|
invalid_structure("unknown clumplet kind", kind);
|
||||||
return SingleTpb;
|
return SingleTpb;
|
||||||
@ -688,6 +700,7 @@ void ClumpletReader::rewind()
|
|||||||
case SpbSendItems:
|
case SpbSendItems:
|
||||||
case SpbReceiveItems:
|
case SpbReceiveItems:
|
||||||
case SpbResponse:
|
case SpbResponse:
|
||||||
|
case InfoResponse:
|
||||||
cur_offset = 0;
|
cur_offset = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -57,7 +57,8 @@ public:
|
|||||||
WideUnTagged,
|
WideUnTagged,
|
||||||
SpbSendItems,
|
SpbSendItems,
|
||||||
SpbReceiveItems,
|
SpbReceiveItems,
|
||||||
SpbResponse
|
SpbResponse,
|
||||||
|
InfoResponse
|
||||||
};
|
};
|
||||||
|
|
||||||
struct KindList
|
struct KindList
|
||||||
@ -130,7 +131,8 @@ public:
|
|||||||
FB_SIZE_T rc = getBufferEnd() - getBuffer();
|
FB_SIZE_T rc = getBufferEnd() - getBuffer();
|
||||||
if (rc == 1 && kind != UnTagged && kind != SpbStart &&
|
if (rc == 1 && kind != UnTagged && kind != SpbStart &&
|
||||||
kind != WideUnTagged && kind != SpbSendItems &&
|
kind != WideUnTagged && kind != SpbSendItems &&
|
||||||
kind != SpbReceiveItems && kind != SpbResponse)
|
kind != SpbReceiveItems && kind != SpbResponse &&
|
||||||
|
kind != InfoResponse)
|
||||||
{
|
{
|
||||||
rc = 0;
|
rc = 0;
|
||||||
}
|
}
|
||||||
|
@ -37,12 +37,12 @@ inline void PUT_WORD(UCHAR*& ptr, USHORT value)
|
|||||||
|
|
||||||
#define PUT(ptr, value) *(ptr)++ = value;
|
#define PUT(ptr, value) *(ptr)++ = value;
|
||||||
|
|
||||||
static ISC_STATUS merge_setup(const UCHAR**, UCHAR**, const UCHAR* const, USHORT);
|
static ISC_STATUS merge_setup(const Firebird::ClumpletReader&, UCHAR**, const UCHAR* const, FB_SIZE_T);
|
||||||
|
|
||||||
|
|
||||||
USHORT MERGE_database_info(const UCHAR* in,
|
USHORT MERGE_database_info(const UCHAR* const in,
|
||||||
UCHAR* out,
|
UCHAR* out,
|
||||||
USHORT out_length,
|
USHORT buf_length,
|
||||||
USHORT impl,
|
USHORT impl,
|
||||||
USHORT class_,
|
USHORT class_,
|
||||||
USHORT base_level,
|
USHORT base_level,
|
||||||
@ -65,22 +65,37 @@ USHORT MERGE_database_info(const UCHAR* in,
|
|||||||
const UCHAR* p;
|
const UCHAR* p;
|
||||||
|
|
||||||
UCHAR* start = out;
|
UCHAR* start = out;
|
||||||
const UCHAR* const end = out + out_length;
|
const UCHAR* const end = out + buf_length;
|
||||||
|
|
||||||
UCHAR mergeLevel = 0;
|
UCHAR mergeLevel = 0;
|
||||||
for (const UCHAR* getMergeLevel = in;
|
Firebird::ClumpletReader input(Firebird::ClumpletReader::InfoResponse, in, buf_length);
|
||||||
*getMergeLevel != isc_info_end && *getMergeLevel != isc_info_truncated;
|
while (!input.isEof())
|
||||||
getMergeLevel += (3 + gds__vax_integer(getMergeLevel + 1, 2)))
|
|
||||||
{
|
{
|
||||||
if (*getMergeLevel == isc_info_implementation)
|
bool flStop = true;
|
||||||
|
switch(input.getClumpTag())
|
||||||
{
|
{
|
||||||
mergeLevel = getMergeLevel[3];
|
case isc_info_implementation:
|
||||||
|
mergeLevel = input.getBytes()[0];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case isc_info_end:
|
||||||
|
case isc_info_truncated:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
flStop = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flStop)
|
||||||
|
break;
|
||||||
|
input.moveNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;)
|
for (input.rewind(); !input.isEof(); input.moveNext())
|
||||||
switch (*out++ = *in++)
|
{
|
||||||
|
*out++ = input.getClumpTag();
|
||||||
|
switch (input.getClumpTag())
|
||||||
{
|
{
|
||||||
case isc_info_end:
|
case isc_info_end:
|
||||||
case isc_info_truncated:
|
case isc_info_truncated:
|
||||||
@ -90,7 +105,7 @@ USHORT MERGE_database_info(const UCHAR* in,
|
|||||||
l = static_cast<SSHORT>(strlen((char *) (p = version)));
|
l = static_cast<SSHORT>(strlen((char *) (p = version)));
|
||||||
if (l > MAX_UCHAR)
|
if (l > MAX_UCHAR)
|
||||||
l = MAX_UCHAR;
|
l = MAX_UCHAR;
|
||||||
if (merge_setup(&in, &out, end, l + 1))
|
if (merge_setup(input, &out, end, l + 1))
|
||||||
return 0;
|
return 0;
|
||||||
for (*out++ = (UCHAR) l; l; --l)
|
for (*out++ = (UCHAR) l; l; --l)
|
||||||
*out++ = *p++;
|
*out++ = *p++;
|
||||||
@ -100,21 +115,21 @@ USHORT MERGE_database_info(const UCHAR* in,
|
|||||||
l = static_cast<SSHORT>(strlen((SCHAR *) (p = id)));
|
l = static_cast<SSHORT>(strlen((SCHAR *) (p = id)));
|
||||||
if (l > MAX_UCHAR)
|
if (l > MAX_UCHAR)
|
||||||
l = MAX_UCHAR;
|
l = MAX_UCHAR;
|
||||||
if (merge_setup(&in, &out, end, l + 1))
|
if (merge_setup(input, &out, end, l + 1))
|
||||||
return 0;
|
return 0;
|
||||||
for (*out++ = (UCHAR) l; l; --l)
|
for (*out++ = (UCHAR) l; l; --l)
|
||||||
*out++ = *p++;
|
*out++ = *p++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case isc_info_implementation:
|
case isc_info_implementation:
|
||||||
if (merge_setup(&in, &out, end, 2))
|
if (merge_setup(input, &out, end, 2))
|
||||||
return 0;
|
return 0;
|
||||||
PUT(out, (UCHAR) impl);
|
PUT(out, (UCHAR) impl);
|
||||||
PUT(out, (UCHAR) class_);
|
PUT(out, (UCHAR) class_);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case fb_info_implementation:
|
case fb_info_implementation:
|
||||||
if (merge_setup(&in, &out, end, 6))
|
if (merge_setup(input, &out, end, 6))
|
||||||
return 0;
|
return 0;
|
||||||
Firebird::DbImplementation::current.stuff(&out);
|
Firebird::DbImplementation::current.stuff(&out);
|
||||||
PUT(out, (UCHAR) class_);
|
PUT(out, (UCHAR) class_);
|
||||||
@ -122,30 +137,32 @@ USHORT MERGE_database_info(const UCHAR* in,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case isc_info_base_level:
|
case isc_info_base_level:
|
||||||
if (merge_setup(&in, &out, end, 1))
|
if (merge_setup(input, &out, end, 1))
|
||||||
return 0;
|
return 0;
|
||||||
PUT(out, (UCHAR) base_level);
|
PUT(out, (UCHAR) base_level);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
USHORT length = (USHORT) gds__vax_integer(in, 2);
|
USHORT length = input.getClumpLength();
|
||||||
in += 2;
|
|
||||||
if (out + length + 2 >= end)
|
if (out + length + 2 >= end)
|
||||||
{
|
{
|
||||||
out[-1] = isc_info_truncated;
|
out[-1] = isc_info_truncated;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
PUT_WORD(out, length);
|
PUT_WORD(out, length);
|
||||||
while (length--)
|
memcpy(out, input.getBytes(), length);
|
||||||
*out++ = *in++;
|
out += length;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; // error - missing isc_info_end item
|
||||||
}
|
}
|
||||||
|
|
||||||
static ISC_STATUS merge_setup(const UCHAR** in, UCHAR** out, const UCHAR* const end,
|
static ISC_STATUS merge_setup(const Firebird::ClumpletReader& input, UCHAR** out, const UCHAR* const end,
|
||||||
USHORT delta_length)
|
FB_SIZE_T delta_length)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
@ -159,17 +176,16 @@ static ISC_STATUS merge_setup(const UCHAR** in, UCHAR** out, const UCHAR* const
|
|||||||
* already there.
|
* already there.
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
USHORT length = (USHORT) gds__vax_integer(*in, 2);
|
FB_SIZE_T length = input.getClumpLength();
|
||||||
const USHORT new_length = length + delta_length;
|
const FB_SIZE_T new_length = length + delta_length;
|
||||||
|
|
||||||
if (*out + new_length + 2 >= end)
|
if (new_length > MAX_USHORT || *out + new_length + 2 >= end)
|
||||||
{
|
{
|
||||||
(*out)[-1] = isc_info_truncated;
|
(*out)[-1] = isc_info_truncated;
|
||||||
return FB_FAILURE;
|
return FB_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*in += 2;
|
const USHORT count = 1 + *(input.getBytes());
|
||||||
const USHORT count = 1 + *(*in)++;
|
|
||||||
PUT_WORD(*out, new_length);
|
PUT_WORD(*out, new_length);
|
||||||
PUT(*out, (UCHAR) count);
|
PUT(*out, (UCHAR) count);
|
||||||
|
|
||||||
@ -177,9 +193,8 @@ static ISC_STATUS merge_setup(const UCHAR** in, UCHAR** out, const UCHAR* const
|
|||||||
|
|
||||||
if (--length)
|
if (--length)
|
||||||
{
|
{
|
||||||
memcpy(*out, *in, length);
|
memcpy(*out, input.getBytes() + 1, length);
|
||||||
*out += length;
|
*out += length;
|
||||||
*in += length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return FB_SUCCESS;
|
return FB_SUCCESS;
|
||||||
|
Loading…
Reference in New Issue
Block a user