8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 18:43:02 +01:00

Fixed CORE-6367: Segfault when receiving malformed packet from network

This commit is contained in:
AlexPeshkoff 2020-07-23 20:12:48 +03:00
parent 8132256a3a
commit 5a7c0c7e3b
10 changed files with 78 additions and 105 deletions

View File

@ -48,8 +48,8 @@
using Firebird::FbLocalStatus;
static bool_t burp_getbytes(XDR*, SCHAR *, u_int);
static bool_t burp_putbytes(XDR*, const SCHAR*, u_int);
static bool_t burp_getbytes(XDR*, SCHAR *, unsigned);
static bool_t burp_putbytes(XDR*, const SCHAR*, unsigned);
static bool_t expand_buffer(XDR*);
static int xdr_init(XDR*, lstring*, enum xdr_op);
static bool_t xdr_slice(XDR*, lstring*, /*USHORT,*/ const UCHAR*);
@ -60,7 +60,7 @@ static xdr_t::xdr_ops burp_ops =
burp_putbytes
};
const int increment = 1024;
const unsigned increment = 1024;
ULONG CAN_encode_decode(burp_rel* relation, lstring* buffer, UCHAR* data, bool direction, bool useMissingOffset)
@ -279,7 +279,7 @@ ULONG CAN_slice(lstring* buffer, lstring* slice, bool direction, UCHAR* sdl)
}
static bool_t burp_getbytes(XDR* xdrs, SCHAR* buff, u_int bytecount)
static bool_t burp_getbytes(XDR* xdrs, SCHAR* buff, unsigned bytecount)
{
/**************************************
*
@ -292,29 +292,29 @@ static bool_t burp_getbytes(XDR* xdrs, SCHAR* buff, u_int bytecount)
*
**************************************/
if (bytecount && xdrs->x_handy >= (int) bytecount)
if (bytecount && xdrs->x_handy >= bytecount)
{
memcpy(buff, xdrs->x_private, bytecount);
xdrs->x_private += bytecount;
xdrs->x_handy -= bytecount;
do {
*buff++ = *xdrs->x_private++;
} while (--bytecount);
return TRUE;
}
while (bytecount)
while (bytecount--)
{
if (!xdrs->x_handy && !expand_buffer(xdrs))
if (xdrs->x_handy == 0 && !expand_buffer(xdrs))
return FALSE;
*buff++ = *xdrs->x_private++;
--xdrs->x_handy;
--bytecount;
}
return TRUE;
}
static bool_t burp_putbytes(XDR* xdrs, const SCHAR* buff, u_int bytecount)
static bool_t burp_putbytes(XDR* xdrs, const SCHAR* buff, unsigned bytecount)
{
/**************************************
*
@ -327,24 +327,22 @@ static bool_t burp_putbytes(XDR* xdrs, const SCHAR* buff, u_int bytecount)
*
**************************************/
if (bytecount && xdrs->x_handy >= (int) bytecount)
if (bytecount && xdrs->x_handy >= bytecount)
{
memcpy(xdrs->x_private, buff, bytecount);
xdrs->x_private += bytecount;
xdrs->x_handy -= bytecount;
do {
*xdrs->x_private++ = *buff++;
} while (--bytecount);
return TRUE;
}
while (bytecount)
while (bytecount--)
{
if (xdrs->x_handy <= 0 && !expand_buffer(xdrs))
{
if (xdrs->x_handy == 0 && !expand_buffer(xdrs))
return FALSE;
}
--xdrs->x_handy;
*xdrs->x_private++ = *buff++;
--bytecount;
--xdrs->x_handy;
}
return TRUE;
@ -366,23 +364,21 @@ static bool_t expand_buffer(XDR* xdrs)
*
**************************************/
lstring* buffer = (lstring*) xdrs->x_public;
const SSHORT length = (xdrs->x_private - xdrs->x_base) + xdrs->x_handy + increment;
buffer->lstr_allocated = buffer->lstr_length = length;
const unsigned usedLength = xdrs->x_private - xdrs->x_base;
const unsigned length = usedLength + xdrs->x_handy + increment;
caddr_t new_buf = (caddr_t) BURP_alloc(length);
caddr_t p = new_buf;
for (caddr_t q = xdrs->x_base; q < xdrs->x_private; *p++ = *q++)
;
buffer->lstr_allocated = buffer->lstr_length = length;
buffer->lstr_address = (UCHAR *) new_buf;
memcpy(new_buf, xdrs->x_base, usedLength);
BURP_free(xdrs->x_base);
xdrs->x_private = new_buf + usedLength;
xdrs->x_base = new_buf;
xdrs->x_private = p;
xdrs->x_handy += increment;
buffer->lstr_address = (UCHAR *) new_buf;
return TRUE;
}

View File

@ -65,11 +65,11 @@ inline void DEBUG_XDR_FREE(XDR*, const void*, const void*, ULONG)
// sufficient.
// This setting may be related to our max DSQL statement size.
const u_int MAXSTRING_FOR_WRAPSTRING = 65535;
const unsigned MAXSTRING_FOR_WRAPSTRING = 65535;
static bool_t mem_getbytes(XDR*, SCHAR*, u_int);
static bool_t mem_putbytes(XDR*, const SCHAR*, u_int);
static bool_t mem_getbytes(XDR*, SCHAR*, unsigned);
static bool_t mem_putbytes(XDR*, const SCHAR*, unsigned);
static const XDR::xdr_ops mem_ops =
@ -549,7 +549,7 @@ bool_t xdr_long(XDR* xdrs, SLONG* ip)
}
bool_t xdr_opaque(XDR* xdrs, SCHAR* p, u_int len)
bool_t xdr_opaque(XDR* xdrs, SCHAR* p, unsigned len)
{
/**************************************
*
@ -664,7 +664,7 @@ bool_t xdr_short(XDR* xdrs, SSHORT* ip)
}
bool_t xdr_string(XDR* xdrs, SCHAR** sp, u_int maxlength)
bool_t xdr_string(XDR* xdrs, SCHAR** sp, unsigned maxlength)
{
/**************************************
*
@ -727,7 +727,7 @@ bool_t xdr_string(XDR* xdrs, SCHAR** sp, u_int maxlength)
}
bool_t xdr_u_int(XDR* xdrs, u_int* ip)
bool_t xdr_u_int(XDR* xdrs, unsigned* ip)
{
/**************************************
*
@ -816,7 +816,7 @@ bool_t xdr_u_short(XDR* xdrs, u_short* ip)
case XDR_DECODE:
if (!GETLONG(xdrs, &temp))
return FALSE;
*ip = (u_int) temp;
*ip = (unsigned) temp;
return TRUE;
case XDR_FREE:
@ -844,7 +844,7 @@ bool_t xdr_wrapstring(XDR* xdrs, SCHAR** strp)
}
int xdrmem_create( XDR* xdrs, SCHAR* addr, u_int len, xdr_op x_op)
int xdrmem_create( XDR* xdrs, SCHAR* addr, unsigned len, xdr_op x_op)
{
/**************************************
*
@ -866,7 +866,7 @@ int xdrmem_create( XDR* xdrs, SCHAR* addr, u_int len, xdr_op x_op)
}
static bool_t mem_getbytes( XDR* xdrs, SCHAR* buff, u_int count)
static bool_t mem_getbytes( XDR* xdrs, SCHAR* buff, unsigned bytecount)
{
/**************************************
*
@ -878,18 +878,14 @@ static bool_t mem_getbytes( XDR* xdrs, SCHAR* buff, u_int count)
* Get a bunch of bytes from a memory stream if it fits.
*
**************************************/
const SLONG bytecount = count;
if ((xdrs->x_handy -= bytecount) < 0)
{
xdrs->x_handy += bytecount;
if (xdrs->x_handy < bytecount)
return FALSE;
}
if (bytecount)
{
memcpy(buff, xdrs->x_private, bytecount);
xdrs->x_private += bytecount;
xdrs->x_handy -= bytecount;
}
return TRUE;
@ -917,7 +913,7 @@ SLONG xdr_peek_long(const XDR* xdrs, const void* data, size_t size)
}
static bool_t mem_putbytes(XDR* xdrs, const SCHAR* buff, u_int count)
static bool_t mem_putbytes(XDR* xdrs, const SCHAR* buff, unsigned bytecount)
{
/**************************************
*
@ -929,18 +925,14 @@ static bool_t mem_putbytes(XDR* xdrs, const SCHAR* buff, u_int count)
* Put a bunch of bytes to a memory stream if it fits.
*
**************************************/
const SLONG bytecount = count;
if ((xdrs->x_handy -= bytecount) < 0)
{
xdrs->x_handy += bytecount;
if (xdrs->x_handy < bytecount)
return FALSE;
}
if (bytecount)
{
memcpy(xdrs->x_private, buff, bytecount);
xdrs->x_private += bytecount;
xdrs->x_handy -= bytecount;
}
return TRUE;

View File

@ -54,13 +54,13 @@ typedef struct xdr_t
xdr_op x_op; // operation; fast additional param
struct xdr_ops
{
bool_t (*x_getbytes)(struct xdr_t*, SCHAR *, u_int); // get some bytes from "
bool_t (*x_putbytes)(struct xdr_t*, const SCHAR*, u_int); // put some bytes to "
bool_t (*x_getbytes)(struct xdr_t*, SCHAR *, unsigned); // get some bytes from "
bool_t (*x_putbytes)(struct xdr_t*, const SCHAR*, unsigned); // put some bytes to "
} const *x_ops;
caddr_t x_public; // Users' data
caddr_t x_private; // pointer to private data
caddr_t x_base; // private used for position info
int x_handy; // extra private word
unsigned x_handy; // extra private word
bool x_local; // transmission is known to be local (bytes are in the host order)
#ifdef DEV_BUILD
bool x_client; // set this flag to true if this is client port

View File

@ -36,16 +36,16 @@ bool_t xdr_enum(XDR*, xdr_op*);
bool_t xdr_float(XDR*, float*);
bool_t xdr_int(XDR*, int*);
bool_t xdr_long(XDR*, SLONG*);
bool_t xdr_opaque(XDR*, SCHAR*, u_int);
bool_t xdr_opaque(XDR*, SCHAR*, unsigned);
bool_t xdr_quad(XDR*, SQUAD*);
bool_t xdr_short(XDR*, SSHORT*);
bool_t xdr_string(XDR*, SCHAR**, u_int);
bool_t xdr_u_int(XDR*, u_int*);
bool_t xdr_string(XDR*, SCHAR**, unsigned);
bool_t xdr_u_int(XDR*, unsigned*);
bool_t xdr_u_long(XDR*, ULONG*);
bool_t xdr_u_short(XDR*, u_short*);
bool_t xdr_wrapstring(XDR*, SCHAR**);
bool_t xdr_hyper(XDR*, void*);
bool_t xdrmem_create(XDR*, SCHAR*, u_int, xdr_op);
bool_t xdrmem_create(XDR*, SCHAR*, unsigned, xdr_op);
SLONG xdr_peek_long(const XDR*, const void* data, size_t size);
#endif // REMOTE_XDR_PROTO_H

View File

@ -542,9 +542,9 @@ static SocketsArray* forkSockets;
static void get_peer_info(rem_port*);
static void inet_gen_error(bool, rem_port*, const Arg::StatusVector& v);
static bool_t inet_getbytes(XDR*, SCHAR *, u_int);
static bool_t inet_getbytes(XDR*, SCHAR *, unsigned);
static void inet_error(bool, rem_port*, const TEXT*, ISC_STATUS, int);
static bool_t inet_putbytes(XDR*, const SCHAR*, u_int);
static bool_t inet_putbytes(XDR*, const SCHAR*, unsigned);
static bool inet_read(XDR*);
static rem_port* inet_try_connect( PACKET*,
Rdb*,
@ -2584,7 +2584,7 @@ static void inet_gen_error(bool releasePort, rem_port* port, const Arg::StatusVe
}
static bool_t inet_getbytes( XDR* xdrs, SCHAR* buff, u_int count)
static bool_t inet_getbytes( XDR* xdrs, SCHAR* buff, unsigned bytecount)
{
/**************************************
*
@ -2598,15 +2598,11 @@ static bool_t inet_getbytes( XDR* xdrs, SCHAR* buff, u_int count)
**************************************/
const rem_port* port = (rem_port*) xdrs->x_public;
if (port->port_flags & PORT_server)
{
return REMOTE_getbytes(xdrs, buff, count);
}
SLONG bytecount = count;
return REMOTE_getbytes(xdrs, buff, bytecount);
// Use memcpy to optimize bulk transfers.
while (bytecount > (SLONG) sizeof(ISC_QUAD))
while (bytecount > sizeof(ISC_QUAD))
{
if (xdrs->x_handy >= bytecount)
{
@ -2644,9 +2640,9 @@ static bool_t inet_getbytes( XDR* xdrs, SCHAR* buff, u_int count)
return TRUE;
}
while (--bytecount >= 0)
while (bytecount--)
{
if (!xdrs->x_handy && !inet_read(xdrs))
if (xdrs->x_handy == 0 && !inet_read(xdrs))
return FALSE;
*buff++ = *xdrs->x_private++;
--xdrs->x_handy;
@ -2718,7 +2714,7 @@ static void inet_error(bool releasePort, rem_port* port, const TEXT* function, I
}
}
static bool_t inet_putbytes( XDR* xdrs, const SCHAR* buff, u_int count)
static bool_t inet_putbytes( XDR* xdrs, const SCHAR* buff, unsigned bytecount)
{
/**************************************
*
@ -2730,11 +2726,10 @@ static bool_t inet_putbytes( XDR* xdrs, const SCHAR* buff, u_int count)
* Put a bunch of bytes to a memory stream if it fits.
*
**************************************/
SLONG bytecount = count;
// Use memcpy to optimize bulk transfers.
while (bytecount > (SLONG) sizeof(ISC_QUAD))
while (bytecount > sizeof(ISC_QUAD))
{
if (xdrs->x_handy >= bytecount)
{
@ -2774,9 +2769,9 @@ static bool_t inet_putbytes( XDR* xdrs, const SCHAR* buff, u_int count)
return TRUE;
}
while (--bytecount >= 0)
while (bytecount--)
{
if (xdrs->x_handy <= 0 && !REMOTE_deflate(xdrs, inet_write, packet_send, false))
if (xdrs->x_handy == 0 && !REMOTE_deflate(xdrs, inet_write, packet_send, false))
return FALSE;
--xdrs->x_handy;
*xdrs->x_private++ = *buff++;
@ -2818,7 +2813,7 @@ static bool inet_read( XDR* xdrs)
return false;
p += length;
xdrs->x_handy = (int) ((SCHAR *) p - xdrs->x_base);
xdrs->x_handy = (SCHAR *) p - xdrs->x_base;
xdrs->x_private = xdrs->x_base;
return true;

View File

@ -80,8 +80,8 @@ static int xdrwnet_create(XDR*, rem_port*, UCHAR*, USHORT, xdr_op);
static bool_t xdrwnet_endofrecord(XDR*);//, int);
static bool wnet_error(rem_port*, const TEXT*, ISC_STATUS, int);
static void wnet_gen_error(rem_port*, const Arg::StatusVector& v);
static bool_t wnet_getbytes(XDR*, SCHAR*, u_int);
static bool_t wnet_putbytes(XDR*, const SCHAR*, u_int);
static bool_t wnet_getbytes(XDR*, SCHAR*, unsigned);
static bool_t wnet_putbytes(XDR*, const SCHAR*, unsigned);
static bool_t wnet_read(XDR*);
static bool_t wnet_write(XDR*); //, int);
#ifdef DEBUG
@ -1056,7 +1056,7 @@ static void wnet_gen_error (rem_port* port, const Arg::StatusVector& v)
}
static bool_t wnet_getbytes( XDR* xdrs, SCHAR* buff, u_int count)
static bool_t wnet_getbytes( XDR* xdrs, SCHAR* buff, unsigned bytecount)
{
/**************************************
*
@ -1068,8 +1068,6 @@ static bool_t wnet_getbytes( XDR* xdrs, SCHAR* buff, u_int count)
* Get a bunch of bytes from a memory stream if it fits.
*
**************************************/
SLONG bytecount = count;
// Use memcpy to optimize bulk transfers.
while (bytecount > (SLONG) sizeof(ISC_QUAD))
@ -1108,9 +1106,9 @@ static bool_t wnet_getbytes( XDR* xdrs, SCHAR* buff, u_int count)
return TRUE;
}
while (--bytecount >= 0)
while (bytecount--)
{
if (!xdrs->x_handy && !wnet_read(xdrs))
if (xdrs->x_handy == 0 && !wnet_read(xdrs))
return FALSE;
*buff++ = *xdrs->x_private++;
--xdrs->x_handy;
@ -1120,7 +1118,7 @@ static bool_t wnet_getbytes( XDR* xdrs, SCHAR* buff, u_int count)
}
static bool_t wnet_putbytes( XDR* xdrs, const SCHAR* buff, u_int count)
static bool_t wnet_putbytes( XDR* xdrs, const SCHAR* buff, unsigned count)
{
/**************************************
*
@ -1172,9 +1170,9 @@ static bool_t wnet_putbytes( XDR* xdrs, const SCHAR* buff, u_int count)
return TRUE;
}
while (--bytecount >= 0)
while (bytecount--)
{
if (xdrs->x_handy <= 0 && !wnet_write(xdrs /*, 0*/))
if (xdrs->x_handy == 0 && !wnet_write(xdrs /*, 0*/))
return FALSE;
--xdrs->x_handy;
*xdrs->x_private++ = *buff++;
@ -1228,7 +1226,7 @@ static bool_t wnet_read( XDR* xdrs)
return FALSE;
}
xdrs->x_handy = (int) (p - xdrs->x_base);
xdrs->x_handy = p - xdrs->x_base;
xdrs->x_private = xdrs->x_base;
return TRUE;

View File

@ -70,8 +70,8 @@ static int send_partial(rem_port*, PACKET*);
static int xdrxnet_create(XDR*, rem_port*, UCHAR*, USHORT, xdr_op);
static bool_t xnet_getbytes(XDR*, SCHAR*, u_int);
static bool_t xnet_putbytes(XDR*, const SCHAR*, u_int);
static bool_t xnet_getbytes(XDR*, SCHAR*, unsigned);
static bool_t xnet_putbytes(XDR*, const SCHAR*, unsigned);
static bool_t xnet_read(XDR* xdrs);
static bool_t xnet_write(XDR* xdrs);
@ -1779,7 +1779,7 @@ static void xnet_error(rem_port* port, ISC_STATUS operation, int status)
}
static bool_t xnet_getbytes(XDR* xdrs, SCHAR* buff, u_int count)
static bool_t xnet_getbytes(XDR* xdrs, SCHAR* buff, unsigned bytecount)
{
/**************************************
*
@ -1791,9 +1791,6 @@ static bool_t xnet_getbytes(XDR* xdrs, SCHAR* buff, u_int count)
* Fetch a bunch of bytes from remote interface.
*
**************************************/
SLONG bytecount = count;
rem_port* port = (rem_port*) xdrs->x_public;
const bool portServer = (port->port_flags & PORT_server);
XCC xcc = port->port_xcc;
@ -1844,7 +1841,7 @@ static bool_t xnet_getbytes(XDR* xdrs, SCHAR* buff, u_int count)
}
static bool_t xnet_putbytes(XDR* xdrs, const SCHAR* buff, u_int count)
static bool_t xnet_putbytes(XDR* xdrs, const SCHAR* buff, unsigned bytecount)
{
/**************************************
*
@ -1856,8 +1853,6 @@ static bool_t xnet_putbytes(XDR* xdrs, const SCHAR* buff, u_int count)
* Put a bunch of bytes into a memory stream.
*
**************************************/
SLONG bytecount = count;
rem_port* port = (rem_port*)xdrs->x_public;
const bool portServer = (port->port_flags & PORT_server);
XCC xcc = port->port_xcc;
@ -1885,8 +1880,7 @@ static bool_t xnet_putbytes(XDR* xdrs, const SCHAR* buff, u_int count)
if (xdrs->x_handy)
{
if ((ULONG) xdrs->x_handy == xch->xch_size)
if (xdrs->x_handy == xch->xch_size)
{
while (!xnet_shutdown)
{

View File

@ -54,7 +54,7 @@ void REMOTE_release_messages (struct RMessage*);
void REMOTE_release_request (struct Rrq *);
void REMOTE_reset_request (struct Rrq *, struct RMessage*);
void REMOTE_reset_statement (struct Rsr *);
bool_t REMOTE_getbytes (XDR*, SCHAR*, u_int);
bool_t REMOTE_getbytes (XDR*, SCHAR*, unsigned);
LegacyPlugin REMOTE_legacy_auth(const char* nm, int protocol);
Firebird::RefPtr<const Config> REMOTE_get_config(const Firebird::PathName* dbName,
const Firebird::string* dpb_config = NULL);

View File

@ -711,7 +711,7 @@ void rem_port::auxAcceptError(PACKET* packet)
}
}
bool_t REMOTE_getbytes (XDR* xdrs, SCHAR* buff, u_int count)
bool_t REMOTE_getbytes (XDR* xdrs, SCHAR* buff, unsigned bytecount)
{
/**************************************
*
@ -723,9 +723,6 @@ bool_t REMOTE_getbytes (XDR* xdrs, SCHAR* buff, u_int count)
* Get a bunch of bytes from a port buffer
*
**************************************/
SLONG bytecount = count;
// Use memcpy to optimize bulk transfers.
while (bytecount > 0)
{
@ -745,6 +742,7 @@ bool_t REMOTE_getbytes (XDR* xdrs, SCHAR* buff, u_int count)
bytecount -= xdrs->x_handy;
xdrs->x_handy = 0;
}
rem_port* port = (rem_port*) xdrs->x_public;
Firebird::RefMutexGuard queGuard(*port->port_que_sync, FB_FUNCTION);
if (port->port_qoffset >= port->port_queue.getCount())
@ -753,7 +751,7 @@ bool_t REMOTE_getbytes (XDR* xdrs, SCHAR* buff, u_int count)
return FALSE;
}
xdrs->x_handy = (int) port->port_queue[port->port_qoffset].getCount();
xdrs->x_handy = port->port_queue[port->port_qoffset].getCount();
fb_assert(xdrs->x_handy <= port->port_buff_size);
memcpy(xdrs->x_base, port->port_queue[port->port_qoffset].begin(), xdrs->x_handy);
++port->port_qoffset;

View File

@ -1287,7 +1287,7 @@ public:
class RecvQueState
{
public:
int save_handy;
unsigned save_handy;
FB_SIZE_T save_private;
FB_SIZE_T save_qoffset;