[Python-checkins] CVS: python/dist/src/Objects fileobject.c,2.125,2.126

Tim Peters tim_one@users.sourceforge.net
Thu, 13 Sep 2001 20:26:10 -0700


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv9095/python/Objects

Modified Files:
	fileobject.c 
Log Message:
The end of [#460467] file objects should be subclassable.
A surprising number of changes to split tp_new into tp_new and tp_init.
Turned out the older PyFile_FromFile() didn't initialize the memory it
allocated in all (error) cases, which caused new sanity asserts
elsewhere to fail left & right (and could have, e.g., caused file_dealloc
to try decrefing random addresses).


Index: fileobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/fileobject.c,v
retrieving revision 2.125
retrieving revision 2.126
diff -C2 -d -r2.125 -r2.126
*** fileobject.c	2001/09/13 21:49:44	2.125
--- fileobject.c	2001/09/14 03:26:08	2.126
***************
*** 73,82 ****
  	assert(f != NULL);
  	assert(PyFile_Check(f));
! 	f->f_fp = NULL;
  	f->f_name = PyString_FromString(name);
  	f->f_mode = PyString_FromString(mode);
  	f->f_close = close;
  	f->f_softspace = 0;
  	f->f_binary = strchr(mode,'b') != NULL;
  	if (f->f_name == NULL || f->f_mode == NULL)
  		return NULL;
--- 73,87 ----
  	assert(f != NULL);
  	assert(PyFile_Check(f));
! 	assert(f->f_fp == NULL);
! 
! 	Py_DECREF(f->f_name);
! 	Py_DECREF(f->f_mode);
  	f->f_name = PyString_FromString(name);
  	f->f_mode = PyString_FromString(mode);
+ 
  	f->f_close = close;
  	f->f_softspace = 0;
  	f->f_binary = strchr(mode,'b') != NULL;
+ 
  	if (f->f_name == NULL || f->f_mode == NULL)
  		return NULL;
***************
*** 92,95 ****
--- 97,101 ----
  	assert(name != NULL);
  	assert(mode != NULL);
+ 	assert(f->f_fp == NULL);
  
  	/* rexec.py can't stop a user from getting the file() constructor --
***************
*** 131,135 ****
  PyFile_FromFile(FILE *fp, char *name, char *mode, int (*close)(FILE *))
  {
! 	PyFileObject *f = PyObject_NEW(PyFileObject, &PyFile_Type);
  	if (f != NULL) {
  		if (fill_file_fields(f, fp, name, mode, close) == NULL) {
--- 137,142 ----
  PyFile_FromFile(FILE *fp, char *name, char *mode, int (*close)(FILE *))
  {
! 	PyFileObject *f = (PyFileObject *)PyFile_Type.tp_new(&PyFile_Type,
! 							     NULL, NULL);
  	if (f != NULL) {
  		if (fill_file_fields(f, fp, name, mode, close) == NULL) {
***************
*** 199,209 ****
  		(*f->f_close)(f->f_fp);
  		Py_END_ALLOW_THREADS
- 	}
- 	if (f->f_name != NULL) {
- 		Py_DECREF(f->f_name);
- 	}
- 	if (f->f_mode != NULL) {
- 		Py_DECREF(f->f_mode);
  	}
  	PyObject_DEL(f);
  }
--- 206,212 ----
  		(*f->f_close)(f->f_fp);
  		Py_END_ALLOW_THREADS
  	}
+ 	Py_XDECREF(f->f_name);
+ 	Py_XDECREF(f->f_mode);
  	PyObject_DEL(f);
  }
***************
*** 1329,1361 ****
  file_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  {
! 	/* XXX As for all XXX_new functions, file_new is called
! 	   with kwds=NULL by type_call(), so the kwlist is impotent. */
  	static char *kwlist[] = {"name", "mode", "buffering", 0};
  	char *name = NULL;
  	char *mode = "r";
  	int bufsize = -1;
- 	PyObject *f;
- 	extern int fclose(FILE *);
  
  	if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:file", kwlist,
  					 Py_FileSystemDefaultEncoding, &name,
  					 &mode, &bufsize))
! 		return NULL;
! 	f = PyType_GenericAlloc(type, 0);
! 	if (f != NULL) {
! 		PyFileObject *g = (PyFileObject *)f;
! 		if (fill_file_fields(g, NULL, name, mode, fclose) == NULL) {
! 			Py_DECREF(f);
! 			f = NULL;
! 		}
! 		if (f != NULL && open_the_file(g, name, mode) == NULL) {
! 			Py_DECREF(f);
! 			f = NULL;
! 		}
! 		if (f != NULL)
! 			PyFile_SetBufSize(f, bufsize);
! 	}
  	PyMem_Free(name); /* free the encoded string */
! 	return f;
  }
  
--- 1332,1394 ----
  file_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  {
! 	PyObject *self;
! 	static PyObject *not_yet_string;
! 
! 	assert(type != NULL && type->tp_alloc != NULL);
! 
! 	if (not_yet_string == NULL) {
! 		not_yet_string = PyString_FromString("<uninitialized file>");
! 		if (not_yet_string == NULL)
! 			return NULL;
! 	}
! 
! 	self = type->tp_alloc(type, 0);
! 	if (self != NULL) {
! 		/* Always fill in the name and mode, so that nobody else
! 		   needs to special-case NULLs there. */
! 		Py_INCREF(not_yet_string);
! 		((PyFileObject *)self)->f_name = not_yet_string;
! 		Py_INCREF(not_yet_string);
! 		((PyFileObject *)self)->f_mode = not_yet_string;
! 	}
! 	return self;
! }
! 
! static int
! file_init(PyObject *self, PyObject *args, PyObject *kwds)
! {
! 	PyFileObject *foself = (PyFileObject *)self;
! 	int ret = 0;
  	static char *kwlist[] = {"name", "mode", "buffering", 0};
  	char *name = NULL;
  	char *mode = "r";
  	int bufsize = -1;
  
+ 	assert(PyFile_Check(self));
+ 	if (foself->f_fp != NULL) {
+ 		/* Have to close the existing file first. */
+ 		PyObject *closeresult = file_close(foself);
+ 		if (closeresult == NULL)
+ 			return -1;
+ 		Py_DECREF(closeresult);
+ 	}
+ 
  	if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:file", kwlist,
  					 Py_FileSystemDefaultEncoding, &name,
  					 &mode, &bufsize))
! 		return -1;
! 	if (fill_file_fields(foself, NULL, name, mode, fclose) == NULL)
! 		goto Error;
! 	if (open_the_file(foself, name, mode) == NULL)
! 		goto Error;
! 	PyFile_SetBufSize(self, bufsize);
! 	goto Done;
! 
! Error:
! 	ret = -1;
! 	/* fall through */
! Done:
  	PyMem_Free(name); /* free the encoded string */
! 	return ret;
  }
  
***************
*** 1410,1415 ****
  	0,					/* tp_descr_set */
  	0,					/* tp_dictoffset */
! 	0,					/* tp_init */
! 	0,					/* tp_alloc */
  	file_new,				/* tp_new */
  };
--- 1443,1448 ----
  	0,					/* tp_descr_set */
  	0,					/* tp_dictoffset */
! 	(initproc)file_init,			/* tp_init */
! 	PyType_GenericAlloc,			/* tp_alloc */
  	file_new,				/* tp_new */
  };