Blame src/misc.c.IceRead-use-after-free

Packit 5a8ca9
/******************************************************************************
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9
Copyright 1993, 1998  The Open Group
Packit 5a8ca9
Packit 5a8ca9
Permission to use, copy, modify, distribute, and sell this software and its
Packit 5a8ca9
documentation for any purpose is hereby granted without fee, provided that
Packit 5a8ca9
the above copyright notice appear in all copies and that both that
Packit 5a8ca9
copyright notice and this permission notice appear in supporting
Packit 5a8ca9
documentation.
Packit 5a8ca9
Packit 5a8ca9
The above copyright notice and this permission notice shall be included in
Packit 5a8ca9
all copies or substantial portions of the Software.
Packit 5a8ca9
Packit 5a8ca9
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit 5a8ca9
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit 5a8ca9
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
Packit 5a8ca9
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
Packit 5a8ca9
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit 5a8ca9
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit 5a8ca9
Packit 5a8ca9
Except as contained in this notice, the name of The Open Group shall not be
Packit 5a8ca9
used in advertising or otherwise to promote the sale, use or other dealings
Packit 5a8ca9
in this Software without prior written authorization from The Open Group.
Packit 5a8ca9
Packit 5a8ca9
Author: Ralph Mor, X Consortium
Packit 5a8ca9
******************************************************************************/
Packit 5a8ca9
Packit 5a8ca9
#ifdef WIN32
Packit 5a8ca9
#define _WILLWINSOCK_
Packit 5a8ca9
#endif
Packit 5a8ca9
#ifdef HAVE_CONFIG_H
Packit 5a8ca9
#include <config.h>
Packit 5a8ca9
#endif
Packit 5a8ca9
#include <X11/ICE/ICElib.h>
Packit 5a8ca9
#include "ICElibint.h"
Packit 5a8ca9
#include <X11/Xtrans/Xtrans.h>
Packit 5a8ca9
#include <stdio.h>
Packit 5a8ca9
#ifdef WIN32
Packit 5a8ca9
#include <X11/Xwinsock.h>
Packit 5a8ca9
#include <X11/Xw32defs.h>
Packit 5a8ca9
#endif
Packit 5a8ca9
Packit 5a8ca9

Packit 5a8ca9
/*
Packit 5a8ca9
 * scratch buffer
Packit 5a8ca9
 */
Packit 5a8ca9
Packit 5a8ca9
char *
Packit 5a8ca9
IceAllocScratch (
Packit 5a8ca9
	IceConn		iceConn,
Packit 5a8ca9
	unsigned long	size
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    if (!iceConn->scratch || size > iceConn->scratch_size)
Packit 5a8ca9
    {
Packit 5a8ca9
	if (iceConn->scratch)
Packit 5a8ca9
	    free (iceConn->scratch);
Packit 5a8ca9
Packit 5a8ca9
	iceConn->scratch = malloc (size);
Packit 5a8ca9
	iceConn->scratch_size = size;
Packit 5a8ca9
    }
Packit 5a8ca9
Packit 5a8ca9
    return (iceConn->scratch);
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9

Packit 5a8ca9
/*
Packit 5a8ca9
 * Output/Input buffer functions
Packit 5a8ca9
 */
Packit 5a8ca9
Packit 5a8ca9
int
Packit 5a8ca9
IceFlush (
Packit 5a8ca9
	IceConn iceConn
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    _IceWrite (iceConn,
Packit 5a8ca9
	(unsigned long) (iceConn->outbufptr - iceConn->outbuf),
Packit 5a8ca9
	iceConn->outbuf);
Packit 5a8ca9
Packit 5a8ca9
    iceConn->outbufptr = iceConn->outbuf;
Packit 5a8ca9
    return 1;
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9
int
Packit 5a8ca9
IceGetOutBufSize (
Packit 5a8ca9
	IceConn iceConn
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    return (iceConn->outbufmax - iceConn->outbuf);
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9
int
Packit 5a8ca9
IceGetInBufSize (
Packit 5a8ca9
	IceConn iceConn
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    return (iceConn->inbufmax - iceConn->inbuf);
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9

Packit 5a8ca9
/*
Packit 5a8ca9
 * informational functions
Packit 5a8ca9
 */
Packit 5a8ca9
Packit 5a8ca9
IceConnectStatus
Packit 5a8ca9
IceConnectionStatus (
Packit 5a8ca9
	IceConn iceConn
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    return (iceConn->connection_status);
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9
char *
Packit 5a8ca9
IceVendor (
Packit 5a8ca9
	IceConn iceConn
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    return strdup(iceConn->vendor);
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9
char *
Packit 5a8ca9
IceRelease (
Packit 5a8ca9
	IceConn iceConn
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    return strdup(iceConn->release);
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9
int
Packit 5a8ca9
IceProtocolVersion (
Packit 5a8ca9
	IceConn iceConn
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    return (_IceVersions[iceConn->my_ice_version_index].major_version);
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9
int
Packit 5a8ca9
IceProtocolRevision (
Packit 5a8ca9
	IceConn iceConn
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    return (_IceVersions[iceConn->my_ice_version_index].minor_version);
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9
int
Packit 5a8ca9
IceConnectionNumber (
Packit 5a8ca9
	IceConn iceConn
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    return (_IceTransGetConnectionNumber (iceConn->trans_conn));
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9
char *
Packit 5a8ca9
IceConnectionString (
Packit 5a8ca9
	IceConn iceConn
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    if (iceConn->connection_string)
Packit 5a8ca9
    {
Packit 5a8ca9
	return strdup(iceConn->connection_string);
Packit 5a8ca9
    }
Packit 5a8ca9
    else
Packit 5a8ca9
	return (NULL);
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9
unsigned long
Packit 5a8ca9
IceLastSentSequenceNumber (
Packit 5a8ca9
	IceConn iceConn
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    return (iceConn->send_sequence);
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9
unsigned long
Packit 5a8ca9
IceLastReceivedSequenceNumber (
Packit 5a8ca9
	IceConn iceConn
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    return (iceConn->receive_sequence);
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9
Bool
Packit 5a8ca9
IceSwapping (
Packit 5a8ca9
	IceConn iceConn
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    return (iceConn->swap);
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9

Packit 5a8ca9
/*
Packit 5a8ca9
 * Read "n" bytes from a connection.
Packit 5a8ca9
 *
Packit 5a8ca9
 * Return Status 0 if we detected an EXPECTED closed connection.
Packit 5a8ca9
 *
Packit 5a8ca9
 */
Packit 5a8ca9
Packit 5a8ca9
Status
Packit 5a8ca9
_IceRead (
Packit 5a8ca9
	register IceConn iceConn,
Packit 5a8ca9
	unsigned long	 nbytes,
Packit 5a8ca9
	register char	 *ptr
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    register unsigned long nleft;
Packit 5a8ca9
Packit 5a8ca9
    nleft = nbytes;
Packit 5a8ca9
    while (nleft > 0)
Packit 5a8ca9
    {
Packit 5a8ca9
	int nread;
Packit 5a8ca9
Packit 5a8ca9
	if (iceConn->io_ok)
Packit 5a8ca9
	    nread = _IceTransRead (iceConn->trans_conn, ptr, (int) nleft);
Packit 5a8ca9
	else
Packit 5a8ca9
	    return (1);
Packit 5a8ca9
Packit 5a8ca9
	if (nread <= 0)
Packit 5a8ca9
	{
Packit 5a8ca9
#ifdef WIN32
Packit 5a8ca9
	    errno = WSAGetLastError();
Packit 5a8ca9
#endif
Packit 5a8ca9
	    if (iceConn->want_to_close)
Packit 5a8ca9
	    {
Packit 5a8ca9
		/*
Packit 5a8ca9
		 * We sent a WantToClose message and now we detected that
Packit 5a8ca9
		 * the other side closed the connection.
Packit 5a8ca9
		 */
Packit 5a8ca9
Packit 5a8ca9
		_IceConnectionClosed (iceConn);	    /* invoke watch procs */
Packit 5a8ca9
		_IceFreeConnection (iceConn);
Packit 5a8ca9
Packit 5a8ca9
		return (0);
Packit 5a8ca9
	    }
Packit 5a8ca9
	    else
Packit 5a8ca9
	    {
Packit 5a8ca9
		/*
Packit 5a8ca9
		 * Fatal IO error.  First notify each protocol's IceIOErrorProc
Packit 5a8ca9
		 * callback, then invoke the application IO error handler.
Packit 5a8ca9
		 */
Packit 5a8ca9
Packit 5a8ca9
		iceConn->io_ok = False;
Packit 5a8ca9
Packit 5a8ca9
		if (iceConn->connection_status == IceConnectPending)
Packit 5a8ca9
		{
Packit 5a8ca9
		    /*
Packit 5a8ca9
		     * Don't invoke IO error handler if we are in the
Packit 5a8ca9
		     * middle of a connection setup.
Packit 5a8ca9
		     */
Packit 5a8ca9
Packit 5a8ca9
		    return (1);
Packit 5a8ca9
		}
Packit 5a8ca9
Packit 5a8ca9
		if (iceConn->process_msg_info)
Packit 5a8ca9
		{
Packit 5a8ca9
		    int i;
Packit 5a8ca9
Packit 5a8ca9
		    for (i = iceConn->his_min_opcode;
Packit 5a8ca9
			i <= iceConn->his_max_opcode; i++)
Packit 5a8ca9
		    {
Packit 5a8ca9
			_IceProcessMsgInfo *process;
Packit 5a8ca9
Packit 5a8ca9
			process = &iceConn->process_msg_info[
Packit 5a8ca9
			    i - iceConn->his_min_opcode];
Packit 5a8ca9
Packit 5a8ca9
			if ((process != NULL) && process->in_use)
Packit 5a8ca9
			{
Packit 5a8ca9
			    IceIOErrorProc IOErrProc = process->accept_flag ?
Packit 5a8ca9
			      process->protocol->accept_client->io_error_proc :
Packit 5a8ca9
			      process->protocol->orig_client->io_error_proc;
Packit 5a8ca9
Packit 5a8ca9
			    if (IOErrProc)
Packit 5a8ca9
				(*IOErrProc) (iceConn);
Packit 5a8ca9
			}
Packit 5a8ca9
		    }
Packit 5a8ca9
		}
Packit 5a8ca9
Packit 5a8ca9
		(*_IceIOErrorHandler) (iceConn);
Packit 5a8ca9
		return (1);
Packit 5a8ca9
	    }
Packit 5a8ca9
	}
Packit 5a8ca9
Packit 5a8ca9
	nleft -= nread;
Packit 5a8ca9
	ptr   += nread;
Packit 5a8ca9
    }
Packit 5a8ca9
Packit 5a8ca9
    return (1);
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9

Packit 5a8ca9
/*
Packit 5a8ca9
 * If we read a message header with a bad major or minor opcode,
Packit 5a8ca9
 * we need to advance to the end of the message.  This way, the next
Packit 5a8ca9
 * message can be processed correctly.
Packit 5a8ca9
 */
Packit 5a8ca9
Packit 5a8ca9
void
Packit 5a8ca9
_IceReadSkip (
Packit 5a8ca9
	register IceConn	iceConn,
Packit 5a8ca9
	register unsigned long	nbytes
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    char temp[512];
Packit 5a8ca9
Packit 5a8ca9
    while (nbytes > 0)
Packit 5a8ca9
    {
Packit 5a8ca9
	unsigned long rbytes = nbytes > 512 ? 512 : nbytes;
Packit 5a8ca9
Packit 5a8ca9
	_IceRead (iceConn, rbytes, temp);
Packit 5a8ca9
	nbytes -= rbytes;
Packit 5a8ca9
    }
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9

Packit 5a8ca9
/*
Packit 5a8ca9
 * Write "n" bytes to a connection.
Packit 5a8ca9
 */
Packit 5a8ca9
Packit 5a8ca9
void
Packit 5a8ca9
_IceWrite (
Packit 5a8ca9
	register IceConn iceConn,
Packit 5a8ca9
	unsigned long	 nbytes,
Packit 5a8ca9
	register char	 *ptr
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    register unsigned long nleft;
Packit 5a8ca9
Packit 5a8ca9
    nleft = nbytes;
Packit 5a8ca9
    while (nleft > 0)
Packit 5a8ca9
    {
Packit 5a8ca9
	int nwritten;
Packit 5a8ca9
Packit 5a8ca9
	if (iceConn->io_ok)
Packit 5a8ca9
	    nwritten = _IceTransWrite (iceConn->trans_conn, ptr, (int) nleft);
Packit 5a8ca9
	else
Packit 5a8ca9
	    return;
Packit 5a8ca9
Packit 5a8ca9
	if (nwritten <= 0)
Packit 5a8ca9
	{
Packit 5a8ca9
#ifdef WIN32
Packit 5a8ca9
	    errno = WSAGetLastError();
Packit 5a8ca9
#endif
Packit 5a8ca9
	    /*
Packit 5a8ca9
	     * Fatal IO error.  First notify each protocol's IceIOErrorProc
Packit 5a8ca9
	     * callback, then invoke the application IO error handler.
Packit 5a8ca9
	     */
Packit 5a8ca9
Packit 5a8ca9
	    iceConn->io_ok = False;
Packit 5a8ca9
Packit 5a8ca9
	    if (iceConn->connection_status == IceConnectPending)
Packit 5a8ca9
	    {
Packit 5a8ca9
		/*
Packit 5a8ca9
		 * Don't invoke IO error handler if we are in the
Packit 5a8ca9
		 * middle of a connection setup.
Packit 5a8ca9
		 */
Packit 5a8ca9
Packit 5a8ca9
		return;
Packit 5a8ca9
	    }
Packit 5a8ca9
Packit 5a8ca9
	    if (iceConn->process_msg_info)
Packit 5a8ca9
	    {
Packit 5a8ca9
		int i;
Packit 5a8ca9
Packit 5a8ca9
		for (i = iceConn->his_min_opcode;
Packit 5a8ca9
		     i <= iceConn->his_max_opcode; i++)
Packit 5a8ca9
		{
Packit 5a8ca9
		    _IceProcessMsgInfo *process;
Packit 5a8ca9
Packit 5a8ca9
		    process = &iceConn->process_msg_info[
Packit 5a8ca9
			i - iceConn->his_min_opcode];
Packit 5a8ca9
Packit 5a8ca9
		    if (process->in_use)
Packit 5a8ca9
		    {
Packit 5a8ca9
			IceIOErrorProc IOErrProc = process->accept_flag ?
Packit 5a8ca9
			    process->protocol->accept_client->io_error_proc :
Packit 5a8ca9
			    process->protocol->orig_client->io_error_proc;
Packit 5a8ca9
Packit 5a8ca9
			if (IOErrProc)
Packit 5a8ca9
			    (*IOErrProc) (iceConn);
Packit 5a8ca9
		    }
Packit 5a8ca9
		}
Packit 5a8ca9
	    }
Packit 5a8ca9
Packit 5a8ca9
	    (*_IceIOErrorHandler) (iceConn);
Packit 5a8ca9
	    return;
Packit 5a8ca9
	}
Packit 5a8ca9
Packit 5a8ca9
	nleft -= nwritten;
Packit 5a8ca9
	ptr   += nwritten;
Packit 5a8ca9
    }
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9

Packit 5a8ca9
void
Packit 5a8ca9
_IceAddOpcodeMapping (
Packit 5a8ca9
	IceConn	iceConn,
Packit 5a8ca9
	int 	hisOpcode,
Packit 5a8ca9
	int 	myOpcode
Packit 5a8ca9
)
Packit 5a8ca9
{
Packit 5a8ca9
    if (hisOpcode <= 0 || hisOpcode > 255)
Packit 5a8ca9
    {
Packit 5a8ca9
	return;
Packit 5a8ca9
    }
Packit 5a8ca9
    else if (iceConn->process_msg_info == NULL)
Packit 5a8ca9
    {
Packit 5a8ca9
	iceConn->process_msg_info = malloc (sizeof (_IceProcessMsgInfo));
Packit 5a8ca9
	iceConn->his_min_opcode = iceConn->his_max_opcode = hisOpcode;
Packit 5a8ca9
    }
Packit 5a8ca9
    else if (hisOpcode < iceConn->his_min_opcode)
Packit 5a8ca9
    {
Packit 5a8ca9
	_IceProcessMsgInfo *oldVec = iceConn->process_msg_info;
Packit 5a8ca9
	int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1;
Packit 5a8ca9
	int newsize = iceConn->his_max_opcode - hisOpcode + 1;
Packit 5a8ca9
	int i;
Packit 5a8ca9
Packit 5a8ca9
	iceConn->process_msg_info = malloc (
Packit 5a8ca9
	    newsize * sizeof (_IceProcessMsgInfo));
Packit 5a8ca9
Packit 5a8ca9
	memcpy (&iceConn->process_msg_info[
Packit 5a8ca9
	    iceConn->his_min_opcode - hisOpcode], oldVec,
Packit 5a8ca9
	    oldsize * sizeof (_IceProcessMsgInfo));
Packit 5a8ca9
Packit 5a8ca9
	free (oldVec);
Packit 5a8ca9
Packit 5a8ca9
	for (i = hisOpcode + 1; i < iceConn->his_min_opcode; i++)
Packit 5a8ca9
	{
Packit 5a8ca9
	    iceConn->process_msg_info[i -
Packit 5a8ca9
		iceConn->his_min_opcode].in_use = False;
Packit 5a8ca9
Packit 5a8ca9
	    iceConn->process_msg_info[i -
Packit 5a8ca9
		iceConn->his_min_opcode].protocol = NULL;
Packit 5a8ca9
	}
Packit 5a8ca9
Packit 5a8ca9
	iceConn->his_min_opcode = hisOpcode;
Packit 5a8ca9
    }
Packit 5a8ca9
    else if (hisOpcode > iceConn->his_max_opcode)
Packit 5a8ca9
    {
Packit 5a8ca9
	_IceProcessMsgInfo *oldVec = iceConn->process_msg_info;
Packit 5a8ca9
	int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1;
Packit 5a8ca9
	int newsize = hisOpcode - iceConn->his_min_opcode + 1;
Packit 5a8ca9
	int i;
Packit 5a8ca9
Packit 5a8ca9
	iceConn->process_msg_info = malloc (
Packit 5a8ca9
	    newsize * sizeof (_IceProcessMsgInfo));
Packit 5a8ca9
Packit 5a8ca9
	memcpy (iceConn->process_msg_info, oldVec,
Packit 5a8ca9
	    oldsize * sizeof (_IceProcessMsgInfo));
Packit 5a8ca9
Packit 5a8ca9
	free (oldVec);
Packit 5a8ca9
Packit 5a8ca9
	for (i = iceConn->his_max_opcode + 1; i < hisOpcode; i++)
Packit 5a8ca9
	{
Packit 5a8ca9
	    iceConn->process_msg_info[i -
Packit 5a8ca9
		iceConn->his_min_opcode].in_use = False;
Packit 5a8ca9
Packit 5a8ca9
	    iceConn->process_msg_info[i -
Packit 5a8ca9
		iceConn->his_min_opcode].protocol = NULL;
Packit 5a8ca9
	}
Packit 5a8ca9
Packit 5a8ca9
	iceConn->his_max_opcode = hisOpcode;
Packit 5a8ca9
    }
Packit 5a8ca9
Packit 5a8ca9
    iceConn->process_msg_info[hisOpcode -
Packit 5a8ca9
	iceConn->his_min_opcode].in_use = True;
Packit 5a8ca9
Packit 5a8ca9
    iceConn->process_msg_info[hisOpcode -
Packit 5a8ca9
	iceConn->his_min_opcode].my_opcode = myOpcode;
Packit 5a8ca9
Packit 5a8ca9
    iceConn->process_msg_info[hisOpcode -
Packit 5a8ca9
	iceConn->his_min_opcode].protocol = &_IceProtocols[myOpcode - 1];
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9
Packit 5a8ca9

Packit 5a8ca9
char *
Packit 5a8ca9
IceGetPeerName (IceConn iceConn)
Packit 5a8ca9
{
Packit 5a8ca9
    return (_IceTransGetPeerNetworkId (iceConn->trans_conn));
Packit 5a8ca9
}
Packit 5a8ca9
Packit 5a8ca9

Packit 5a8ca9
char *
Packit 5a8ca9
_IceGetPeerName (IceConn iceConn)
Packit 5a8ca9
{
Packit 5a8ca9
    return (IceGetPeerName(iceConn));
Packit 5a8ca9
}