mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 18:43:02 +01:00
Slightly refactored the BLR parser routines to avoid crazy error reporting and protect against NULL pointer dereference. The error handling still sucks, but it was the case before me ;-)
This commit is contained in:
parent
bf8ed546e4
commit
5d3fd3dbe0
@ -1203,9 +1203,8 @@ Firebird::IRequest* Attachment::compileRequest(IStatus* status,
|
|||||||
|
|
||||||
RMessage* message = PARSE_messages(blr, blr_length);
|
RMessage* message = PARSE_messages(blr, blr_length);
|
||||||
USHORT max_msg = 0;
|
USHORT max_msg = 0;
|
||||||
for (next = message; next; next = next->msg_next) {
|
for (next = message; next; next = next->msg_next)
|
||||||
max_msg = MAX(max_msg, next->msg_number);
|
max_msg = MAX(max_msg, next->msg_number);
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate request block
|
// Allocate request block
|
||||||
Rrq* request = new Rrq(max_msg + 1);
|
Rrq* request = new Rrq(max_msg + 1);
|
||||||
@ -1737,14 +1736,7 @@ Firebird::ITransaction* Statement::execute(IStatus* status, Firebird::ITransacti
|
|||||||
// Parse the blr describing the message, if there is any.
|
// Parse the blr describing the message, if there is any.
|
||||||
|
|
||||||
if (in_blr_length)
|
if (in_blr_length)
|
||||||
{
|
statement->rsr_bind_format = PARSE_msg_format(in_blr, in_blr_length);
|
||||||
RMessage* message = PARSE_messages(in_blr, in_blr_length);
|
|
||||||
if (message != (RMessage*) - 1)
|
|
||||||
{
|
|
||||||
statement->rsr_bind_format = (rem_fmt*) message->msg_address;
|
|
||||||
delete message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the blr describing the output message. This is not the fetch
|
// Parse the blr describing the output message. This is not the fetch
|
||||||
// message! That comes later.
|
// message! That comes later.
|
||||||
@ -1754,12 +1746,7 @@ Firebird::ITransaction* Statement::execute(IStatus* status, Firebird::ITransacti
|
|||||||
if (!port->port_statement)
|
if (!port->port_statement)
|
||||||
port->port_statement = new Rsr;
|
port->port_statement = new Rsr;
|
||||||
|
|
||||||
RMessage* message = PARSE_messages(out_blr, out_blr_length);
|
port->port_statement->rsr_select_format = PARSE_msg_format(out_blr, out_blr_length);
|
||||||
if (message != (RMessage*) - 1)
|
|
||||||
{
|
|
||||||
port->port_statement->rsr_select_format = (rem_fmt*) message->msg_address;
|
|
||||||
delete message;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!port->port_statement->rsr_buffer)
|
if (!port->port_statement->rsr_buffer)
|
||||||
{
|
{
|
||||||
@ -1932,14 +1919,7 @@ ResultSet* Statement::openCursor(IStatus* status, Firebird::ITransaction* apiTra
|
|||||||
// Parse the blr describing the message, if there is any.
|
// Parse the blr describing the message, if there is any.
|
||||||
|
|
||||||
if (in_blr_length)
|
if (in_blr_length)
|
||||||
{
|
statement->rsr_bind_format = PARSE_msg_format(in_blr, in_blr_length);
|
||||||
RMessage* message = PARSE_messages(in_blr, in_blr_length);
|
|
||||||
if (message != (RMessage*) -1)
|
|
||||||
{
|
|
||||||
statement->rsr_bind_format = (rem_fmt*) message->msg_address;
|
|
||||||
delete message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RMessage* message = NULL;
|
RMessage* message = NULL;
|
||||||
if (!statement->rsr_buffer)
|
if (!statement->rsr_buffer)
|
||||||
@ -2113,23 +2093,10 @@ ITransaction* Attachment::execute(IStatus* status, ITransaction* apiTra,
|
|||||||
if (in_msg_length || out_msg_length)
|
if (in_msg_length || out_msg_length)
|
||||||
{
|
{
|
||||||
if (in_blr_length)
|
if (in_blr_length)
|
||||||
{
|
statement->rsr_bind_format = PARSE_msg_format(in_blr, in_blr_length);
|
||||||
RMessage* message = PARSE_messages(in_blr, in_blr_length);
|
|
||||||
if (message != (RMessage*) - 1)
|
|
||||||
{
|
|
||||||
statement->rsr_bind_format = (rem_fmt*) message->msg_address;
|
|
||||||
delete message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (out_blr_length)
|
if (out_blr_length)
|
||||||
{
|
statement->rsr_select_format = PARSE_msg_format(out_blr, out_blr_length);
|
||||||
RMessage* message = PARSE_messages(out_blr, out_blr_length);
|
|
||||||
if (message != (RMessage*) - 1)
|
|
||||||
{
|
|
||||||
statement->rsr_select_format = (rem_fmt*) message->msg_address;
|
|
||||||
delete message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RMessage* message = 0;
|
RMessage* message = 0;
|
||||||
@ -2830,14 +2797,9 @@ int ResultSet::fetchNext(IStatus* status, void* buffer)
|
|||||||
{
|
{
|
||||||
delete statement->rsr_user_select_format;
|
delete statement->rsr_user_select_format;
|
||||||
}
|
}
|
||||||
RMessage* message = PARSE_messages(blr, blr_length);
|
|
||||||
if (message != (RMessage*) - 1)
|
statement->rsr_user_select_format = PARSE_msg_format(blr, blr_length);
|
||||||
{
|
|
||||||
statement->rsr_user_select_format = (rem_fmt*) message->msg_address;
|
|
||||||
delete message;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
statement->rsr_user_select_format = NULL;
|
|
||||||
if (statement->rsr_flags.test(Rsr::FETCHED))
|
if (statement->rsr_flags.test(Rsr::FETCHED))
|
||||||
blr_length = 0;
|
blr_length = 0;
|
||||||
else
|
else
|
||||||
@ -5034,36 +4996,31 @@ void Attachment::transactRequest(IStatus* status, ITransaction* apiTra,
|
|||||||
procedure->rpr_out_format = NULL;
|
procedure->rpr_out_format = NULL;
|
||||||
|
|
||||||
RMessage* message = PARSE_messages(blr, blr_length);
|
RMessage* message = PARSE_messages(blr, blr_length);
|
||||||
if (message != (RMessage*) - 1)
|
while (message)
|
||||||
{
|
{
|
||||||
while (message)
|
switch (message->msg_number)
|
||||||
{
|
{
|
||||||
switch (message->msg_number)
|
case 0:
|
||||||
{
|
procedure->rpr_in_msg = message;
|
||||||
case 0:
|
procedure->rpr_in_format = (rem_fmt*) message->msg_address;
|
||||||
procedure->rpr_in_msg = message;
|
message->msg_address = const_cast<unsigned char*>(in_msg);
|
||||||
procedure->rpr_in_format = (rem_fmt*) message->msg_address;
|
message = message->msg_next;
|
||||||
message->msg_address = const_cast<unsigned char*>(in_msg);
|
procedure->rpr_in_msg->msg_next = NULL;
|
||||||
message = message->msg_next;
|
break;
|
||||||
procedure->rpr_in_msg->msg_next = NULL;
|
case 1:
|
||||||
break;
|
procedure->rpr_out_msg = message;
|
||||||
case 1:
|
procedure->rpr_out_format = (rem_fmt*) message->msg_address;
|
||||||
procedure->rpr_out_msg = message;
|
message->msg_address = out_msg;
|
||||||
procedure->rpr_out_format = (rem_fmt*) message->msg_address;
|
message = message->msg_next;
|
||||||
message->msg_address = out_msg;
|
procedure->rpr_out_msg->msg_next = NULL;
|
||||||
message = message->msg_next;
|
break;
|
||||||
procedure->rpr_out_msg->msg_next = NULL;
|
default:
|
||||||
break;
|
RMessage* temp = message;
|
||||||
default:
|
message = message->msg_next;
|
||||||
RMessage* temp = message;
|
delete temp;
|
||||||
message = message->msg_next;
|
break;
|
||||||
delete temp;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//else
|
|
||||||
// error
|
|
||||||
|
|
||||||
|
|
||||||
PACKET* packet = &rdb->rdb_packet;
|
PACKET* packet = &rdb->rdb_packet;
|
||||||
|
@ -25,5 +25,6 @@
|
|||||||
#define REMOTE_PARSE_PROTO_H
|
#define REMOTE_PARSE_PROTO_H
|
||||||
|
|
||||||
struct RMessage* PARSE_messages(const UCHAR*, size_t);
|
struct RMessage* PARSE_messages(const UCHAR*, size_t);
|
||||||
|
struct rem_fmt* PARSE_msg_format(const UCHAR*, size_t);
|
||||||
|
|
||||||
#endif // REMOTE_PARSE_PROTO_H
|
#endif // REMOTE_PARSE_PROTO_H
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static RMessage* parse_error(rem_fmt* format, RMessage* mesage);
|
static rem_fmt* parse_format(const UCHAR*& blr, size_t& blr_length);
|
||||||
|
|
||||||
|
|
||||||
RMessage* PARSE_messages(const UCHAR* blr, size_t blr_length)
|
RMessage* PARSE_messages(const UCHAR* blr, size_t blr_length)
|
||||||
@ -49,252 +49,313 @@ RMessage* PARSE_messages(const UCHAR* blr, size_t blr_length)
|
|||||||
*
|
*
|
||||||
* Functional description
|
* Functional description
|
||||||
* Parse the messages of a blr request. For each message, allocate
|
* Parse the messages of a blr request. For each message, allocate
|
||||||
* a message (msg) and a format (fmt) block. Return the number of
|
* a message (msg) and a format (fmt) block.
|
||||||
* messages found. If an error occurs, return -1;
|
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
|
|
||||||
if (blr_length < 2)
|
if (blr_length < 3)
|
||||||
return (RMessage*) -1;
|
return NULL;
|
||||||
blr_length -= 2;
|
blr_length -= 3;
|
||||||
|
|
||||||
const SSHORT version = *blr++;
|
const SSHORT version = *blr++;
|
||||||
if (version != blr_version4 && version != blr_version5)
|
if (version != blr_version4 && version != blr_version5)
|
||||||
return (RMessage*) -1;
|
return NULL;
|
||||||
|
|
||||||
if (*blr++ != blr_begin)
|
if (*blr++ != blr_begin)
|
||||||
return 0;
|
return NULL;
|
||||||
|
|
||||||
RMessage* message = NULL;
|
RMessage* message = NULL;
|
||||||
ULONG net_length = 0;
|
ULONG net_length = 0;
|
||||||
|
|
||||||
|
bool error = false;
|
||||||
|
|
||||||
while (*blr++ == blr_message)
|
while (*blr++ == blr_message)
|
||||||
{
|
{
|
||||||
if (blr_length < 4)
|
if (blr_length-- == 0)
|
||||||
return parse_error(0, message);
|
{
|
||||||
blr_length -= 4;
|
error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
const USHORT msg_number = *blr++;
|
const USHORT msg_number = *blr++;
|
||||||
USHORT count = *blr++;
|
|
||||||
count += (*blr++) << 8;
|
rem_fmt* const format = parse_format(blr, blr_length);
|
||||||
rem_fmt* const format = new rem_fmt(count);
|
if (!format)
|
||||||
#ifdef DEBUG_REMOTE_MEMORY
|
|
||||||
printf("PARSE_messages allocate format %x\n", format);
|
|
||||||
#endif
|
|
||||||
ULONG offset = 0;
|
|
||||||
for (dsc* desc = format->fmt_desc.begin(); count; --count, ++desc)
|
|
||||||
{
|
{
|
||||||
if (blr_length-- == 0)
|
error = true;
|
||||||
return parse_error(format, message);
|
break;
|
||||||
|
|
||||||
USHORT align = 4;
|
|
||||||
switch (*blr++)
|
|
||||||
{
|
|
||||||
case blr_text:
|
|
||||||
if (blr_length < 2)
|
|
||||||
return parse_error(format, message);
|
|
||||||
blr_length -= 2;
|
|
||||||
desc->dsc_dtype = dtype_text;
|
|
||||||
desc->dsc_length = *blr++;
|
|
||||||
desc->dsc_length += (*blr++) << 8;
|
|
||||||
align = type_alignments[dtype_text];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case blr_varying:
|
|
||||||
if (blr_length < 2)
|
|
||||||
return parse_error(format, message);
|
|
||||||
blr_length -= 2;
|
|
||||||
desc->dsc_dtype = dtype_varying;
|
|
||||||
desc->dsc_length = *blr++ + sizeof(SSHORT);
|
|
||||||
desc->dsc_length += (*blr++) << 8;
|
|
||||||
align = type_alignments[dtype_varying];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case blr_cstring:
|
|
||||||
if (blr_length < 2)
|
|
||||||
return parse_error(format, message);
|
|
||||||
blr_length -= 2;
|
|
||||||
desc->dsc_dtype = dtype_cstring;
|
|
||||||
desc->dsc_length = *blr++;
|
|
||||||
desc->dsc_length += (*blr++) << 8;
|
|
||||||
align = type_alignments[dtype_cstring];
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Parse the tagged blr types correctly
|
|
||||||
|
|
||||||
case blr_text2:
|
|
||||||
if (blr_length < 4)
|
|
||||||
return parse_error(format, message);
|
|
||||||
blr_length -= 4;
|
|
||||||
desc->dsc_dtype = dtype_text;
|
|
||||||
desc->dsc_scale = *blr++;
|
|
||||||
desc->dsc_scale += (*blr++) << 8;
|
|
||||||
desc->dsc_length = *blr++;
|
|
||||||
desc->dsc_length += (*blr++) << 8;
|
|
||||||
align = type_alignments[dtype_text];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case blr_varying2:
|
|
||||||
if (blr_length < 4)
|
|
||||||
return parse_error(format, message);
|
|
||||||
blr_length -= 4;
|
|
||||||
desc->dsc_dtype = dtype_varying;
|
|
||||||
desc->dsc_scale = *blr++;
|
|
||||||
desc->dsc_scale += (*blr++) << 8;
|
|
||||||
desc->dsc_length = *blr++ + sizeof(SSHORT);
|
|
||||||
desc->dsc_length += (*blr++) << 8;
|
|
||||||
align = type_alignments[dtype_varying];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case blr_cstring2:
|
|
||||||
if (blr_length < 4)
|
|
||||||
return parse_error(format, message);
|
|
||||||
blr_length -= 4;
|
|
||||||
desc->dsc_dtype = dtype_cstring;
|
|
||||||
desc->dsc_scale = *blr++;
|
|
||||||
desc->dsc_scale += (*blr++) << 8;
|
|
||||||
desc->dsc_length = *blr++;
|
|
||||||
desc->dsc_length += (*blr++) << 8;
|
|
||||||
align = type_alignments[dtype_cstring];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case blr_short:
|
|
||||||
if (blr_length-- == 0)
|
|
||||||
return parse_error(format, message);
|
|
||||||
desc->dsc_dtype = dtype_short;
|
|
||||||
desc->dsc_length = sizeof(SSHORT);
|
|
||||||
desc->dsc_scale = *blr++;
|
|
||||||
align = type_alignments[dtype_short];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case blr_long:
|
|
||||||
if (blr_length-- == 0)
|
|
||||||
return parse_error(format, message);
|
|
||||||
desc->dsc_dtype = dtype_long;
|
|
||||||
desc->dsc_length = sizeof(SLONG);
|
|
||||||
desc->dsc_scale = *blr++;
|
|
||||||
align = type_alignments[dtype_long];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case blr_int64:
|
|
||||||
if (blr_length-- == 0)
|
|
||||||
return parse_error(format, message);
|
|
||||||
desc->dsc_dtype = dtype_int64;
|
|
||||||
desc->dsc_length = sizeof(SINT64);
|
|
||||||
desc->dsc_scale = *blr++;
|
|
||||||
align = type_alignments[dtype_int64];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case blr_quad:
|
|
||||||
if (blr_length-- == 0)
|
|
||||||
return parse_error(format, message);
|
|
||||||
desc->dsc_dtype = dtype_quad;
|
|
||||||
desc->dsc_length = sizeof(SLONG) * 2;
|
|
||||||
desc->dsc_scale = *blr++;
|
|
||||||
align = type_alignments[dtype_quad];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case blr_float:
|
|
||||||
desc->dsc_dtype = dtype_real;
|
|
||||||
desc->dsc_length = sizeof(float);
|
|
||||||
align = type_alignments[dtype_real];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case blr_double:
|
|
||||||
case blr_d_float:
|
|
||||||
desc->dsc_dtype = dtype_double;
|
|
||||||
desc->dsc_length = sizeof(double);
|
|
||||||
align = type_alignments[dtype_double];
|
|
||||||
break;
|
|
||||||
|
|
||||||
// this case cannot occur as switch paramater is char and blr_blob
|
|
||||||
// is 261. blob_ids are actually passed around as blr_quad.
|
|
||||||
|
|
||||||
//case blr_blob:
|
|
||||||
// desc->dsc_dtype = dtype_blob;
|
|
||||||
// desc->dsc_length = sizeof (SLONG) * 2;
|
|
||||||
// align = type_alignments [dtype_blob];
|
|
||||||
// break;
|
|
||||||
|
|
||||||
case blr_blob2:
|
|
||||||
{
|
|
||||||
if (blr_length < 4)
|
|
||||||
return parse_error(format, message);
|
|
||||||
blr_length -= 4;
|
|
||||||
desc->dsc_dtype = dtype_blob;
|
|
||||||
desc->dsc_length = sizeof(SLONG) * 2;
|
|
||||||
desc->dsc_sub_type = *blr++;
|
|
||||||
desc->dsc_sub_type += (*blr++) << 8;
|
|
||||||
|
|
||||||
USHORT textType = *blr++;
|
|
||||||
textType += (*blr++) << 8;
|
|
||||||
desc->setTextType(textType);
|
|
||||||
|
|
||||||
align = type_alignments[dtype_blob];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case blr_timestamp:
|
|
||||||
desc->dsc_dtype = dtype_timestamp;
|
|
||||||
desc->dsc_length = sizeof(SLONG) * 2;
|
|
||||||
align = type_alignments[dtype_timestamp];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case blr_sql_date:
|
|
||||||
desc->dsc_dtype = dtype_sql_date;
|
|
||||||
desc->dsc_length = sizeof(SLONG);
|
|
||||||
align = type_alignments[dtype_sql_date];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case blr_sql_time:
|
|
||||||
desc->dsc_dtype = dtype_sql_time;
|
|
||||||
desc->dsc_length = sizeof(ULONG);
|
|
||||||
align = type_alignments[dtype_sql_time];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case blr_bool:
|
|
||||||
desc->dsc_dtype = dtype_boolean;
|
|
||||||
desc->dsc_length = sizeof(UCHAR);
|
|
||||||
align = type_alignments[dtype_boolean];
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
fb_assert(FALSE);
|
|
||||||
return parse_error(format, message);
|
|
||||||
}
|
|
||||||
if (desc->dsc_dtype == dtype_varying)
|
|
||||||
net_length += 4 + ((desc->dsc_length - 2 + 3) & ~3);
|
|
||||||
else
|
|
||||||
net_length += (desc->dsc_length + 3) & ~3;
|
|
||||||
if (align > 1)
|
|
||||||
offset = FB_ALIGN(offset, align);
|
|
||||||
desc->dsc_address = (UCHAR*) (IPTR) offset;
|
|
||||||
offset += desc->dsc_length;
|
|
||||||
}
|
}
|
||||||
format->fmt_length = offset;
|
|
||||||
format->fmt_net_length = net_length;
|
|
||||||
RMessage* next = new RMessage(format->fmt_length);
|
RMessage* next = new RMessage(format->fmt_length);
|
||||||
#ifdef DEBUG_REMOTE_MEMORY
|
|
||||||
printf("PARSE_messages allocate message %x\n", next);
|
|
||||||
#endif
|
|
||||||
next->msg_next = message;
|
next->msg_next = message;
|
||||||
message = next;
|
message = next;
|
||||||
message->msg_address = reinterpret_cast<UCHAR*>(format);
|
message->msg_address = reinterpret_cast<UCHAR*>(format);
|
||||||
message->msg_number = msg_number;
|
message->msg_number = msg_number;
|
||||||
|
|
||||||
|
if (blr_length-- == 0)
|
||||||
|
{
|
||||||
|
error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
for (RMessage* next = message; next; next = message)
|
||||||
|
{
|
||||||
|
message = message->msg_next;
|
||||||
|
delete next->msg_address;
|
||||||
|
delete next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static RMessage* parse_error(rem_fmt* format, RMessage* message)
|
rem_fmt* PARSE_msg_format(const UCHAR* blr, size_t blr_length)
|
||||||
{
|
{
|
||||||
delete format;
|
/**************************************
|
||||||
for (RMessage* next = message; next; next = message)
|
*
|
||||||
{
|
* P A R S E _ m s g _ f o r m a t
|
||||||
message = message->msg_next;
|
*
|
||||||
delete next->msg_address;
|
**************************************
|
||||||
delete next;
|
*
|
||||||
}
|
* Functional description
|
||||||
return (RMessage*) -1;
|
* Parse the message of a blr request and return its format.
|
||||||
|
*
|
||||||
|
**************************************/
|
||||||
|
|
||||||
|
if (blr_length < 4)
|
||||||
|
return NULL;
|
||||||
|
blr_length -= 4;
|
||||||
|
|
||||||
|
const SSHORT version = *blr++;
|
||||||
|
if (version != blr_version4 && version != blr_version5)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (*blr++ != blr_begin)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (*blr++ != blr_message)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
blr++; // skip message number
|
||||||
|
|
||||||
|
return parse_format(blr, blr_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static rem_fmt* parse_format(const UCHAR*& blr, size_t& blr_length)
|
||||||
|
{
|
||||||
|
if (blr_length < 2)
|
||||||
|
return NULL;
|
||||||
|
blr_length -= 2;
|
||||||
|
|
||||||
|
USHORT count = *blr++;
|
||||||
|
count += (*blr++) << 8;
|
||||||
|
|
||||||
|
Firebird::AutoPtr<rem_fmt> format(new rem_fmt(count));
|
||||||
|
|
||||||
|
ULONG net_length = 0;
|
||||||
|
ULONG offset = 0;
|
||||||
|
|
||||||
|
for (dsc* desc = format->fmt_desc.begin(); count; --count, ++desc)
|
||||||
|
{
|
||||||
|
if (blr_length-- == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
USHORT align = 4;
|
||||||
|
switch (*blr++)
|
||||||
|
{
|
||||||
|
case blr_text:
|
||||||
|
if (blr_length < 2)
|
||||||
|
return NULL;
|
||||||
|
blr_length -= 2;
|
||||||
|
desc->dsc_dtype = dtype_text;
|
||||||
|
desc->dsc_length = *blr++;
|
||||||
|
desc->dsc_length += (*blr++) << 8;
|
||||||
|
align = type_alignments[dtype_text];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case blr_varying:
|
||||||
|
if (blr_length < 2)
|
||||||
|
return NULL;
|
||||||
|
blr_length -= 2;
|
||||||
|
desc->dsc_dtype = dtype_varying;
|
||||||
|
desc->dsc_length = *blr++ + sizeof(SSHORT);
|
||||||
|
desc->dsc_length += (*blr++) << 8;
|
||||||
|
align = type_alignments[dtype_varying];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case blr_cstring:
|
||||||
|
if (blr_length < 2)
|
||||||
|
return NULL;
|
||||||
|
blr_length -= 2;
|
||||||
|
desc->dsc_dtype = dtype_cstring;
|
||||||
|
desc->dsc_length = *blr++;
|
||||||
|
desc->dsc_length += (*blr++) << 8;
|
||||||
|
align = type_alignments[dtype_cstring];
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Parse the tagged blr types correctly
|
||||||
|
|
||||||
|
case blr_text2:
|
||||||
|
if (blr_length < 4)
|
||||||
|
return NULL;
|
||||||
|
blr_length -= 4;
|
||||||
|
desc->dsc_dtype = dtype_text;
|
||||||
|
desc->dsc_scale = *blr++;
|
||||||
|
desc->dsc_scale += (*blr++) << 8;
|
||||||
|
desc->dsc_length = *blr++;
|
||||||
|
desc->dsc_length += (*blr++) << 8;
|
||||||
|
align = type_alignments[dtype_text];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case blr_varying2:
|
||||||
|
if (blr_length < 4)
|
||||||
|
return NULL;
|
||||||
|
blr_length -= 4;
|
||||||
|
desc->dsc_dtype = dtype_varying;
|
||||||
|
desc->dsc_scale = *blr++;
|
||||||
|
desc->dsc_scale += (*blr++) << 8;
|
||||||
|
desc->dsc_length = *blr++ + sizeof(SSHORT);
|
||||||
|
desc->dsc_length += (*blr++) << 8;
|
||||||
|
align = type_alignments[dtype_varying];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case blr_cstring2:
|
||||||
|
if (blr_length < 4)
|
||||||
|
return NULL;
|
||||||
|
blr_length -= 4;
|
||||||
|
desc->dsc_dtype = dtype_cstring;
|
||||||
|
desc->dsc_scale = *blr++;
|
||||||
|
desc->dsc_scale += (*blr++) << 8;
|
||||||
|
desc->dsc_length = *blr++;
|
||||||
|
desc->dsc_length += (*blr++) << 8;
|
||||||
|
align = type_alignments[dtype_cstring];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case blr_short:
|
||||||
|
if (blr_length-- == 0)
|
||||||
|
return NULL;
|
||||||
|
desc->dsc_dtype = dtype_short;
|
||||||
|
desc->dsc_length = sizeof(SSHORT);
|
||||||
|
desc->dsc_scale = *blr++;
|
||||||
|
align = type_alignments[dtype_short];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case blr_long:
|
||||||
|
if (blr_length-- == 0)
|
||||||
|
return NULL;
|
||||||
|
desc->dsc_dtype = dtype_long;
|
||||||
|
desc->dsc_length = sizeof(SLONG);
|
||||||
|
desc->dsc_scale = *blr++;
|
||||||
|
align = type_alignments[dtype_long];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case blr_int64:
|
||||||
|
if (blr_length-- == 0)
|
||||||
|
return NULL;
|
||||||
|
desc->dsc_dtype = dtype_int64;
|
||||||
|
desc->dsc_length = sizeof(SINT64);
|
||||||
|
desc->dsc_scale = *blr++;
|
||||||
|
align = type_alignments[dtype_int64];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case blr_quad:
|
||||||
|
if (blr_length-- == 0)
|
||||||
|
return NULL;
|
||||||
|
desc->dsc_dtype = dtype_quad;
|
||||||
|
desc->dsc_length = sizeof(SLONG) * 2;
|
||||||
|
desc->dsc_scale = *blr++;
|
||||||
|
align = type_alignments[dtype_quad];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case blr_float:
|
||||||
|
desc->dsc_dtype = dtype_real;
|
||||||
|
desc->dsc_length = sizeof(float);
|
||||||
|
align = type_alignments[dtype_real];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case blr_double:
|
||||||
|
case blr_d_float:
|
||||||
|
desc->dsc_dtype = dtype_double;
|
||||||
|
desc->dsc_length = sizeof(double);
|
||||||
|
align = type_alignments[dtype_double];
|
||||||
|
break;
|
||||||
|
|
||||||
|
// this case cannot occur as switch paramater is char and blr_blob
|
||||||
|
// is 261. blob_ids are actually passed around as blr_quad.
|
||||||
|
|
||||||
|
//case blr_blob:
|
||||||
|
// desc->dsc_dtype = dtype_blob;
|
||||||
|
// desc->dsc_length = sizeof (SLONG) * 2;
|
||||||
|
// align = type_alignments [dtype_blob];
|
||||||
|
// break;
|
||||||
|
|
||||||
|
case blr_blob2:
|
||||||
|
{
|
||||||
|
if (blr_length < 4)
|
||||||
|
return NULL;
|
||||||
|
blr_length -= 4;
|
||||||
|
desc->dsc_dtype = dtype_blob;
|
||||||
|
desc->dsc_length = sizeof(SLONG) * 2;
|
||||||
|
desc->dsc_sub_type = *blr++;
|
||||||
|
desc->dsc_sub_type += (*blr++) << 8;
|
||||||
|
|
||||||
|
USHORT textType = *blr++;
|
||||||
|
textType += (*blr++) << 8;
|
||||||
|
desc->setTextType(textType);
|
||||||
|
|
||||||
|
align = type_alignments[dtype_blob];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case blr_timestamp:
|
||||||
|
desc->dsc_dtype = dtype_timestamp;
|
||||||
|
desc->dsc_length = sizeof(SLONG) * 2;
|
||||||
|
align = type_alignments[dtype_timestamp];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case blr_sql_date:
|
||||||
|
desc->dsc_dtype = dtype_sql_date;
|
||||||
|
desc->dsc_length = sizeof(SLONG);
|
||||||
|
align = type_alignments[dtype_sql_date];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case blr_sql_time:
|
||||||
|
desc->dsc_dtype = dtype_sql_time;
|
||||||
|
desc->dsc_length = sizeof(ULONG);
|
||||||
|
align = type_alignments[dtype_sql_time];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case blr_bool:
|
||||||
|
desc->dsc_dtype = dtype_boolean;
|
||||||
|
desc->dsc_length = sizeof(UCHAR);
|
||||||
|
align = type_alignments[dtype_boolean];
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fb_assert(false);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desc->dsc_dtype == dtype_varying)
|
||||||
|
net_length += 4 + ((desc->dsc_length - 2 + 3) & ~3);
|
||||||
|
else
|
||||||
|
net_length += (desc->dsc_length + 3) & ~3;
|
||||||
|
|
||||||
|
if (align > 1)
|
||||||
|
offset = FB_ALIGN(offset, align);
|
||||||
|
|
||||||
|
desc->dsc_address = (UCHAR*) (IPTR) offset;
|
||||||
|
offset += desc->dsc_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
format->fmt_length = offset;
|
||||||
|
format->fmt_net_length = net_length;
|
||||||
|
|
||||||
|
return format.release();
|
||||||
}
|
}
|
||||||
|
@ -1544,14 +1544,7 @@ static bool_t xdr_sql_blr(XDR* xdrs,
|
|||||||
// setting up a format
|
// setting up a format
|
||||||
|
|
||||||
if (blr->cstr_length)
|
if (blr->cstr_length)
|
||||||
{
|
*fmt_ptr = PARSE_msg_format(blr->cstr_address, blr->cstr_length);
|
||||||
RMessage* temp_msg = (RMessage*) PARSE_messages(blr->cstr_address, blr->cstr_length);
|
|
||||||
if (temp_msg != (RMessage*) -1)
|
|
||||||
{
|
|
||||||
*fmt_ptr = (rem_fmt*) temp_msg->msg_address;
|
|
||||||
delete temp_msg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we know the length of the message, make sure there is a buffer
|
// If we know the length of the message, make sure there is a buffer
|
||||||
@ -1781,38 +1774,33 @@ static bool_t xdr_trrq_blr(XDR* xdrs, CSTRING* blr)
|
|||||||
procedure->rpr_out_format = NULL;
|
procedure->rpr_out_format = NULL;
|
||||||
|
|
||||||
RMessage* message = PARSE_messages(blr->cstr_address, blr->cstr_length);
|
RMessage* message = PARSE_messages(blr->cstr_address, blr->cstr_length);
|
||||||
if (message != (RMessage*) -1)
|
while (message)
|
||||||
{
|
{
|
||||||
while (message)
|
switch (message->msg_number)
|
||||||
{
|
{
|
||||||
switch (message->msg_number)
|
case 0:
|
||||||
|
procedure->rpr_in_msg = message;
|
||||||
|
procedure->rpr_in_format = (rem_fmt*) message->msg_address;
|
||||||
|
message->msg_address = message->msg_buffer;
|
||||||
|
message = message->msg_next;
|
||||||
|
procedure->rpr_in_msg->msg_next = NULL;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
procedure->rpr_out_msg = message;
|
||||||
|
procedure->rpr_out_format = (rem_fmt*) message->msg_address;
|
||||||
|
message->msg_address = message->msg_buffer;
|
||||||
|
message = message->msg_next;
|
||||||
|
procedure->rpr_out_msg->msg_next = NULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
{
|
{
|
||||||
case 0:
|
RMessage* temp = message;
|
||||||
procedure->rpr_in_msg = message;
|
|
||||||
procedure->rpr_in_format = (rem_fmt*) message->msg_address;
|
|
||||||
message->msg_address = message->msg_buffer;
|
|
||||||
message = message->msg_next;
|
message = message->msg_next;
|
||||||
procedure->rpr_in_msg->msg_next = NULL;
|
delete temp;
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
procedure->rpr_out_msg = message;
|
|
||||||
procedure->rpr_out_format = (rem_fmt*) message->msg_address;
|
|
||||||
message->msg_address = message->msg_buffer;
|
|
||||||
message = message->msg_next;
|
|
||||||
procedure->rpr_out_msg->msg_next = NULL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
RMessage* temp = message;
|
|
||||||
message = message->msg_next;
|
|
||||||
delete temp;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
fb_assert(FALSE);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user