[Patches] fix socket module for 64-bits (mostly Win64)

Trent Mick trentm@activestate.com
Fri, 2 Jun 2000 00:50:06 -0700


Discussion:

This patch fixes possible overflows in the socket module for 64-bit platforms
(mainly Win64). The changes are:

- abstract the socket type to SOCKET_T (this is SOCKET on Windows, int on
  Un*x), this is necessary because sizeof(SOCKET) > sizeof(int) on Win64
- use INVALID_SOCKET on Win32/64 for an error return value for accept()
- ensure no overflow of the socket variable for: (1) a PyObject return value
  (use PyLong_FromLongLong if necessary); and (2) printf formatting in repr()


Legal:

I confirm that, to the best of my knowledge and belief, this
contribution is free of any claims of third parties under
copyright, patent or other rights or interests ("claims").  To
the extent that I have any such claims, I hereby grant to CNRI a
nonexclusive, irrevocable, royalty-free, worldwide license to
reproduce, distribute, perform and/or display publicly, prepare
derivative versions, and otherwise use this contribution as part
of the Python software and its related documentation, or any
derivative versions thereof, at no cost to CNRI or its licensed
users, and to authorize others to do so.

I acknowledge that CNRI may, at its sole discretion, decide
whether or not to incorporate this contribution in the Python
software and its related documentation.  I further grant CNRI
permission to use my name and other identifying information
provided to CNRI by me for use in connection with the Python
software and its related documentation.


Patch (use 'patch -p8'):

*** /home/trentm/main/contrib/python/dist/src/Modules/socketmodule.c	Thu Jun  1 00:13:39 2000
--- /home/trentm/main/Apps/Perlium/Python/dist/src/Modules/socketmodule.c	Fri Jun  2 00:31:44 2000
***************
*** 221,226 ****
--- 221,240 ----
  #define FORCE_ANSI_FUNC_DEFS
  #endif
  
+ /* abstract the socket file descriptor type */
+ #ifdef MS_WINDOWS
+ typedef SOCKET SOCKET_T;
+ #	ifdef MS_WIN64
+ #		define SIZEOF_SOCKET_T 8
+ #	else
+ #		define SIZEOF_SOCKET_T 4
+ #	endif
+ #else
+ typedef int SOCKET_T;
+ #	define SIZEOF_SOCKET_T SIZEOF_INT
+ #endif
+ 
+ 
  #if defined(PYOS_OS2)
  #define SOCKETCLOSE soclose
  #define NO_DUP /* Sockets are Not Actual File Handles under OS/2 */
***************
*** 337,343 ****
  
  typedef struct {
  	PyObject_HEAD
! 	int sock_fd;		/* Socket file descriptor */
  	int sock_family;	/* Address family, e.g., AF_INET */
  	int sock_type;		/* Socket type, e.g., SOCK_STREAM */
  	int sock_proto;		/* Protocol type, usually 0 */
--- 351,357 ----
  
  typedef struct {
  	PyObject_HEAD
! 	SOCKET_T sock_fd;		/* Socket file descriptor */
  	int sock_family;	/* Address family, e.g., AF_INET */
  	int sock_type;		/* Socket type, e.g., SOCK_STREAM */
  	int sock_proto;		/* Protocol type, usually 0 */
***************
*** 387,393 ****
     in NEWOBJ()). */
  
  static PySocketSockObject *
! BUILD_FUNC_DEF_4(PySocketSock_New,int,fd, int,family, int,type, int,proto)
  {
  	PySocketSockObject *s;
  	PySocketSock_Type.ob_type = &PyType_Type;
--- 401,407 ----
     in NEWOBJ()). */
  
  static PySocketSockObject *
! BUILD_FUNC_DEF_4(PySocketSock_New,SOCKET_T,fd, int,family, int,type, int,proto)
  {
  	PySocketSockObject *s;
  	PySocketSock_Type.ob_type = &PyType_Type;
***************
*** 666,672 ****
  BUILD_FUNC_DEF_2(PySocketSock_accept,PySocketSockObject *,s, PyObject *,args)
  {
  	char addrbuf[256];
! 	int newfd;
  	socklen_t addrlen;
  	PyObject *sock = NULL;
  	PyObject *addr = NULL;
--- 680,686 ----
  BUILD_FUNC_DEF_2(PySocketSock_accept,PySocketSockObject *,s, PyObject *,args)
  {
  	char addrbuf[256];
! 	SOCKET_T newfd;
  	socklen_t addrlen;
  	PyObject *sock = NULL;
  	PyObject *addr = NULL;
***************
*** 679,685 ****
--- 693,703 ----
  	Py_BEGIN_ALLOW_THREADS
  	newfd = accept(s->sock_fd, (struct sockaddr *) addrbuf, &addrlen);
  	Py_END_ALLOW_THREADS
+ #ifdef MS_WINDOWS
+ 	if (newfd == INVALID_SOCKET)
+ #else
  	if (newfd < 0)
+ #endif
  		return PySocket_Err();
  
  	/* Create the new object with unspecified family,
***************
*** 968,974 ****
--- 986,996 ----
  {
  	if (!PyArg_ParseTuple(args, ":fileno"))
  		return NULL;
+ #if SIZEOF_SOCKET_T <= SIZEOF_LONG
  	return PyInt_FromLong((long) s->sock_fd);
+ #else
+ 	return PyLong_FromLongLong((LONG_LONG)s->sock_fd);
+ #endif
  }
  
  static char fileno_doc[] =
***************
*** 983,989 ****
  static PyObject *
  BUILD_FUNC_DEF_2(PySocketSock_dup,PySocketSockObject *,s, PyObject *,args)
  {
! 	int newfd;
  	PyObject *sock;
  	if (!PyArg_ParseTuple(args, ":dup"))
  		return NULL;
--- 1005,1011 ----
  static PyObject *
  BUILD_FUNC_DEF_2(PySocketSock_dup,PySocketSockObject *,s, PyObject *,args)
  {
! 	SOCKET_T newfd;
  	PyObject *sock;
  	if (!PyArg_ParseTuple(args, ":dup"))
  		return NULL;
***************
*** 1109,1115 ****
--- 1131,1141 ----
  	extern int fclose Py_PROTO((FILE *));
  	char *mode = "r";
  	int bufsize = -1;
+ #ifdef MS_WIN32
+ 	intptr_t fd;
+ #else
  	int fd;
+ #endif	
  	FILE *fp;
  	PyObject *f;
  
***************
*** 1387,1395 ****
  BUILD_FUNC_DEF_1(PySocketSock_repr,PySocketSockObject *,s)
  {
  	char buf[512];
  	sprintf(buf, 
! 		"<socket object, fd=%d, family=%d, type=%d, protocol=%d>", 
! 		s->sock_fd, s->sock_family, s->sock_type, s->sock_proto);
  	return PyString_FromString(buf);
  }
  
--- 1413,1431 ----
  BUILD_FUNC_DEF_1(PySocketSock_repr,PySocketSockObject *,s)
  {
  	char buf[512];
+ #if SIZEOF_SOCKET_T > SIZEOF_LONG
+ 	if (s->sock_fd > LONG_MAX) {
+ 		/* this can occur on Win64, and actually there is a special
+ 		   ugly printf formatter for decimal pointer length integer
+ 		   printing, only bother if necessary*/
+ 		PyErr_SetString(PyExc_OverflowError,
+ 			"no printf formatter to display the socket descriptor in decimal");
+ 		return NULL;
+ 	}
+ #endif
  	sprintf(buf, 
! 		"<socket object, fd=%ld, family=%d, type=%d, protocol=%d>", 
! 		(long)s->sock_fd, s->sock_family, s->sock_type, s->sock_proto);
  	return PyString_FromString(buf);
  }
  
***************
*** 1716,1726 ****
  BUILD_FUNC_DEF_2(PySocket_socket,PyObject *,self, PyObject *,args)
  {
  	PySocketSockObject *s;
! #ifdef MS_WINDOWS
! 	SOCKET fd;
! #else
! 	int fd;
! #endif
  	int family, type, proto = 0;
  	if (!PyArg_ParseTuple(args, "ii|i:socket", &family, &type, &proto))
  		return NULL;
--- 1752,1758 ----
  BUILD_FUNC_DEF_2(PySocket_socket,PyObject *,self, PyObject *,args)
  {
  	PySocketSockObject *s;
! 	SOCKET_T fd;
  	int family, type, proto = 0;
  	if (!PyArg_ParseTuple(args, "ii|i:socket", &family, &type, &proto))
  		return NULL;
***************
*** 1766,1772 ****
  BUILD_FUNC_DEF_2(PySocket_fromfd,PyObject *,self, PyObject *,args)
  {
  	PySocketSockObject *s;
! 	int fd, family, type, proto = 0;
  	if (!PyArg_ParseTuple(args, "iii|i:fromfd",
  			      &fd, &family, &type, &proto))
  		return NULL;
--- 1798,1805 ----
  BUILD_FUNC_DEF_2(PySocket_fromfd,PyObject *,self, PyObject *,args)
  {
  	PySocketSockObject *s;
! 	SOCKET_T fd;
! 	int family, type, proto = 0;
  	if (!PyArg_ParseTuple(args, "iii|i:fromfd",
  			      &fd, &family, &type, &proto))
  		return NULL;
***************
*** 2113,2119 ****
  static PyObject *SSL_SSLwrite(SSLObject *self, PyObject *args)
  {
  	char *data;
! 	int len = 0;
    
  	if (!PyArg_ParseTuple(args, "s|i:write", &data, &len))
  		return NULL;
--- 2146,2152 ----
  static PyObject *SSL_SSLwrite(SSLObject *self, PyObject *args)
  {
  	char *data;
! 	size_t len = 0;
    
  	if (!PyArg_ParseTuple(args, "s|i:write", &data, &len))
  		return NULL;


-- 
Trent Mick
trentm@activestate.com