[Python-checkins] python/dist/src/Objects bufferobject.c,2.22,2.23

nascheme at users.sourceforge.net nascheme at users.sourceforge.net
Wed Mar 10 21:42:47 EST 2004


Update of /cvsroot/python/python/dist/src/Objects
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2948/Objects

Modified Files:
	bufferobject.c 
Log Message:
Make buffer objects based on immutable objects (like array) safe.


Index: bufferobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/bufferobject.c,v
retrieving revision 2.22
retrieving revision 2.23
diff -C2 -d -r2.22 -r2.23
*** bufferobject.c	11 Mar 2004 01:00:44 -0000	2.22
--- bufferobject.c	11 Mar 2004 02:42:45 -0000	2.23
***************
*** 10,13 ****
--- 10,14 ----
  	void *b_ptr;
  	int b_size;
+ 	int b_offset;
  	int b_readonly;
  	long b_hash;
***************
*** 15,24 ****
  
  
  static PyObject *
! buffer_from_memory(PyObject *base, void *ptr, int size, int readonly)
  {
  	PyBufferObject * b;
  
! 	if ( size < 0 ) {
  		PyErr_SetString(PyExc_ValueError,
  				"size must be zero or positive");
--- 16,66 ----
  
  
+ static int
+ get_buf(PyBufferObject *self, void **ptr, int *size)
+ {
+ 	if (self->b_base == NULL) {
+ 		assert (ptr != NULL);
+ 		*ptr = self->b_ptr;
+ 		*size = self->b_size;
+ 	}
+ 	else {
+ 		int count, offset;
+ 		getreadbufferproc proc;
+ 		PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
+ 		if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
+ 			PyErr_SetString(PyExc_TypeError,
+ 				"single-segment buffer object expected");
+ 			return 0;
+ 		}
+ 		if (self->b_readonly)
+ 			proc = bp->bf_getreadbuffer;
+ 		else
+ 			proc = (getreadbufferproc)bp->bf_getwritebuffer;
+ 		if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
+ 			return 0;
+ 		/* apply constraints to the start/end */
+ 		if (self->b_offset > count)
+ 			offset = count;
+ 		else
+ 			offset = self->b_offset;
+ 		(char *)*ptr = (char *)*ptr + offset;
+ 		if (self->b_size == Py_END_OF_BUFFER)
+ 			*size = count;
+ 		else
+ 			*size = self->b_size;
+ 		if (offset + *size > count)
+ 			*size = count - offset;
+ 	}
+ 	return 1;
+ }
+ 
+ 
  static PyObject *
! buffer_from_memory(PyObject *base, int size, int offset, void *ptr,
! 		   int readonly)
  {
  	PyBufferObject * b;
  
! 	if (size < 0 && size != Py_END_OF_BUFFER) {
  		PyErr_SetString(PyExc_ValueError,
  				"size must be zero or positive");
***************
*** 34,37 ****
--- 76,80 ----
  	b->b_ptr = ptr;
  	b->b_size = size;
+ 	b->b_offset = offset;
  	b->b_readonly = readonly;
  	b->b_hash = -1;
***************
*** 41,51 ****
  
  static PyObject *
! buffer_from_object(PyObject *base, int offset, int size,
! 		   getreadbufferproc proc, int readonly)
  {
- 	PyBufferProcs *pb = base->ob_type->tp_as_buffer;
- 	void *p;
- 	int count;
- 
  	if ( offset < 0 ) {
  		PyErr_SetString(PyExc_ValueError,
--- 84,89 ----
  
  static PyObject *
! buffer_from_object(PyObject *base, int size, int offset, int readonly)
  {
  	if ( offset < 0 ) {
  		PyErr_SetString(PyExc_ValueError,
***************
*** 54,81 ****
  	}
  
! 	if ( (*pb->bf_getsegcount)(base, NULL) != 1 )
! 	{
! 		PyErr_SetString(PyExc_TypeError,
! 				"single-segment buffer object expected");
! 		return NULL;
! 	}
! 	if ( (count = (*proc)(base, 0, &p)) < 0 )
! 		return NULL;
! 
! 	/* apply constraints to the start/end */
! 	if ( size == Py_END_OF_BUFFER || size < 0 )
! 		size = count;
! 	if ( offset > count )
! 		offset = count;
! 	if ( offset + size > count )
! 		size = count - offset;
! 	
! 	/* if the base object is another buffer, then "deref" it,
! 	 * except if the base of the other buffer is NULL
  	 */
! 	if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) )
  		base = ((PyBufferObject *)base)->b_base;
  	
! 	return buffer_from_memory(base, (char *)p + offset, size, readonly);
  }
  
--- 92,104 ----
  	}
  
! 	/* if the base object is another buffer, then try to refer to the
! 	 * base object.
  	 */
! 	if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
  		base = ((PyBufferObject *)base)->b_base;
+ 		offset = ((PyBufferObject *)base)->b_offset + offset;
+ 	}
  	
! 	return buffer_from_memory(base, size, offset, NULL, readonly);
  }
  
***************
*** 94,98 ****
  	}
  
! 	return buffer_from_object(base, offset, size, pb->bf_getreadbuffer, 1);
  }
  
--- 117,121 ----
  	}
  
! 	return buffer_from_object(base, size, offset, 1);
  }
  
***************
*** 110,116 ****
  	}
  
! 	return buffer_from_object(base, offset, size,
! 				  (getreadbufferproc)pb->bf_getwritebuffer,
! 				  0);
  }
  
--- 133,137 ----
  	}
  
! 	return buffer_from_object(base, size,  offset, 0);
  }
  
***************
*** 118,122 ****
  PyBuffer_FromMemory(void *ptr, int size)
  {
! 	return buffer_from_memory(NULL, ptr, size, 1);
  }
  
--- 139,143 ----
  PyBuffer_FromMemory(void *ptr, int size)
  {
! 	return buffer_from_memory(NULL, size, 0, ptr, 1);
  }
  
***************
*** 124,128 ****
  PyBuffer_FromReadWriteMemory(void *ptr, int size)
  {
! 	return buffer_from_memory(NULL, ptr, size, 0);
  }
  
--- 145,149 ----
  PyBuffer_FromReadWriteMemory(void *ptr, int size)
  {
! 	return buffer_from_memory(NULL, size, 0, ptr, 0);
  }
  
***************
*** 147,150 ****
--- 168,172 ----
  	b->b_ptr = (void *)(b + 1);
  	b->b_size = size;
+ 	b->b_offset = 0;
  	b->b_readonly = 0;
  	b->b_hash = -1;
***************
*** 186,195 ****
  buffer_compare(PyBufferObject *self, PyBufferObject *other)
  {
! 	int len_self = self->b_size;
! 	int len_other = other->b_size;
! 	int min_len = (len_self < len_other) ? len_self : len_other;
! 	int cmp;
  	if (min_len > 0) {
! 		cmp = memcmp(self->b_ptr, other->b_ptr, min_len);
  		if (cmp != 0)
  			return cmp;
--- 208,221 ----
  buffer_compare(PyBufferObject *self, PyBufferObject *other)
  {
! 	void *p1, *p2;
! 	int len_self, len_other, min_len, cmp;
! 
! 	if (!get_buf(self, &p1, &len_self))
! 		return -1;
! 	if (!get_buf(other, &p2, &len_other))
! 		return -1;
! 	min_len = (len_self < len_other) ? len_self : len_other;
  	if (min_len > 0) {
! 		cmp = memcmp(p1, p2, min_len);
  		if (cmp != 0)
  			return cmp;
***************
*** 211,219 ****
  	else
  		return PyString_FromFormat(
! 			"<%s buffer for %p, ptr %p, size %d at %p>",
  			status,
  			self->b_base,
- 			self->b_ptr,
  			self->b_size,
  			self);
  }
--- 237,245 ----
  	else
  		return PyString_FromFormat(
! 			"<%s buffer for %p, size %d, offset %d at %p>",
  			status,
  			self->b_base,
  			self->b_size,
+ 			self->b_offset,
  			self);
  }
***************
*** 222,225 ****
--- 248,253 ----
  buffer_hash(PyBufferObject *self)
  {
+ 	void *ptr;
+ 	int size;
  	register int len;
  	register unsigned char *p;
***************
*** 243,252 ****
  	}
  
! 	len = self->b_size;
! 	p = (unsigned char *) self->b_ptr;
  	x = *p << 7;
  	while (--len >= 0)
  		x = (1000003*x) ^ *p++;
! 	x ^= self->b_size;
  	if (x == -1)
  		x = -2;
--- 271,282 ----
  	}
  
! 	if (!get_buf(self, &ptr, &size))
! 		return -1;
! 	p = (unsigned char *) ptr;
! 	len = size;
  	x = *p << 7;
  	while (--len >= 0)
  		x = (1000003*x) ^ *p++;
! 	x ^= size;
  	if (x == -1)
  		x = -2;
***************
*** 258,262 ****
  buffer_str(PyBufferObject *self)
  {
! 	return PyString_FromStringAndSize(self->b_ptr, self->b_size);
  }
  
--- 288,296 ----
  buffer_str(PyBufferObject *self)
  {
! 	void *ptr;
! 	int size;
! 	if (!get_buf(self, &ptr, &size))
! 		return NULL;
! 	return PyString_FromStringAndSize(ptr, size);
  }
  
***************
*** 266,270 ****
  buffer_length(PyBufferObject *self)
  {
! 	return self->b_size;
  }
  
--- 300,308 ----
  buffer_length(PyBufferObject *self)
  {
! 	void *ptr;
! 	int size;
! 	if (!get_buf(self, &ptr, &size))
! 		return -1;
! 	return size;
  }
  
***************
*** 273,280 ****
  {
  	PyBufferProcs *pb = other->ob_type->tp_as_buffer;
! 	char *p1;
! 	void *p2;
  	PyObject *ob;
! 	int count;
  
  	if ( pb == NULL ||
--- 311,318 ----
  {
  	PyBufferProcs *pb = other->ob_type->tp_as_buffer;
! 	void *ptr1, *ptr2;
! 	char *p;
  	PyObject *ob;
! 	int size, count;
  
  	if ( pb == NULL ||
***************
*** 293,298 ****
  	}
  
  	/* optimize special case */
! 	if ( self->b_size == 0 )
  	{
  	    Py_INCREF(other);
--- 331,339 ----
  	}
  
+  	if (!get_buf(self, &ptr1, &size))
+  		return NULL;
+  
  	/* optimize special case */
! 	if ( size == 0 )
  	{
  	    Py_INCREF(other);
***************
*** 300,313 ****
  	}
  
! 	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p2)) < 0 )
  		return NULL;
  
! 	ob = PyString_FromStringAndSize(NULL, self->b_size + count);
! 	p1 = PyString_AS_STRING(ob);
! 	memcpy(p1, self->b_ptr, self->b_size);
! 	memcpy(p1 + self->b_size, p2, count);
  
  	/* there is an extra byte in the string object, so this is safe */
! 	p1[self->b_size + count] = '\0';
  
  	return ob;
--- 341,354 ----
  	}
  
! 	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
  		return NULL;
  
!  	ob = PyString_FromStringAndSize(NULL, size + count);
!  	p = PyString_AS_STRING(ob);
!  	memcpy(p, ptr1, size);
!  	memcpy(p + size, ptr2, count);
  
  	/* there is an extra byte in the string object, so this is safe */
! 	p[size + count] = '\0';
  
  	return ob;
***************
*** 319,327 ****
  	PyObject *ob;
  	register char *p;
! 	void *ptr = self->b_ptr;
! 	int size = self->b_size;
  
  	if ( count < 0 )
  		count = 0;
  	ob = PyString_FromStringAndSize(NULL, size * count);
  	if ( ob == NULL )
--- 360,370 ----
  	PyObject *ob;
  	register char *p;
! 	void *ptr;
! 	int size;
  
  	if ( count < 0 )
  		count = 0;
+ 	if (!get_buf(self, &ptr, &size))
+ 		return NULL;
  	ob = PyString_FromStringAndSize(NULL, size * count);
  	if ( ob == NULL )
***************
*** 344,353 ****
  buffer_item(PyBufferObject *self, int idx)
  {
! 	if ( idx < 0 || idx >= self->b_size )
! 	{
  		PyErr_SetString(PyExc_IndexError, "buffer index out of range");
  		return NULL;
  	}
! 	return PyString_FromStringAndSize((char *)self->b_ptr + idx, 1);
  }
  
--- 387,399 ----
  buffer_item(PyBufferObject *self, int idx)
  {
! 	void *ptr;
! 	int size;
! 	if (!get_buf(self, &ptr, &size))
! 		return NULL;
! 	if ( idx < 0 || idx >= size ) {
  		PyErr_SetString(PyExc_IndexError, "buffer index out of range");
  		return NULL;
  	}
! 	return PyString_FromStringAndSize((char *)ptr + idx, 1);
  }
  
***************
*** 355,367 ****
  buffer_slice(PyBufferObject *self, int left, int right)
  {
  	if ( left < 0 )
  		left = 0;
  	if ( right < 0 )
  		right = 0;
! 	if ( right > self->b_size )
! 		right = self->b_size;
  	if ( right < left )
  		right = left;
! 	return PyString_FromStringAndSize((char *)self->b_ptr + left,
  					  right - left);
  }
--- 401,417 ----
  buffer_slice(PyBufferObject *self, int left, int right)
  {
+ 	void *ptr;
+ 	int size;
+ 	if (!get_buf(self, &ptr, &size))
+ 		return NULL;
  	if ( left < 0 )
  		left = 0;
  	if ( right < 0 )
  		right = 0;
! 	if ( right > size )
! 		right = size;
  	if ( right < left )
  		right = left;
! 	return PyString_FromStringAndSize((char *)ptr + left,
  					  right - left);
  }
***************
*** 371,375 ****
  {
  	PyBufferProcs *pb;
! 	void *p;
  	int count;
  
--- 421,426 ----
  {
  	PyBufferProcs *pb;
! 	void *ptr1, *ptr2;
! 	int size;
  	int count;
  
***************
*** 380,384 ****
  	}
  
! 	if (idx < 0 || idx >= self->b_size) {
  		PyErr_SetString(PyExc_IndexError,
  				"buffer assignment index out of range");
--- 431,438 ----
  	}
  
! 	if (!get_buf(self, &ptr1, &size))
! 		return -1;
! 
! 	if (idx < 0 || idx >= size) {
  		PyErr_SetString(PyExc_IndexError,
  				"buffer assignment index out of range");
***************
*** 402,406 ****
  	}
  
! 	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
  		return -1;
  	if ( count != 1 ) {
--- 456,460 ----
  	}
  
! 	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
  		return -1;
  	if ( count != 1 ) {
***************
*** 410,414 ****
  	}
  
! 	((char *)self->b_ptr)[idx] = *(char *)p;
  	return 0;
  }
--- 464,468 ----
  	}
  
! 	((char *)ptr1)[idx] = *(char *)ptr2;
  	return 0;
  }
***************
*** 418,422 ****
  {
  	PyBufferProcs *pb;
! 	void *p;
  	int slice_len;
  	int count;
--- 472,477 ----
  {
  	PyBufferProcs *pb;
! 	void *ptr1, *ptr2;
! 	int size;
  	int slice_len;
  	int count;
***************
*** 443,457 ****
  		return -1;
  	}
! 	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &p)) < 0 )
  		return -1;
  
  	if ( left < 0 )
  		left = 0;
! 	else if ( left > self->b_size )
! 		left = self->b_size;
  	if ( right < left )
  		right = left;
! 	else if ( right > self->b_size )
! 		right = self->b_size;
  	slice_len = right - left;
  
--- 498,514 ----
  		return -1;
  	}
! 	if (!get_buf(self, &ptr1, &size))
! 		return -1;
! 	if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
  		return -1;
  
  	if ( left < 0 )
  		left = 0;
! 	else if ( left > size )
! 		left = size;
  	if ( right < left )
  		right = left;
! 	else if ( right > size )
! 		right = size;
  	slice_len = right - left;
  
***************
*** 464,468 ****
  
  	if ( slice_len )
! 	    memcpy((char *)self->b_ptr + left, p, slice_len);
  
  	return 0;
--- 521,525 ----
  
  	if ( slice_len )
! 	    memcpy((char *)ptr1 + left, ptr2, slice_len);
  
  	return 0;
***************
*** 474,477 ****
--- 531,535 ----
  buffer_getreadbuf(PyBufferObject *self, int idx, void **pp)
  {
+ 	int size;
  	if ( idx != 0 ) {
  		PyErr_SetString(PyExc_SystemError,
***************
*** 479,484 ****
  		return -1;
  	}
! 	*pp = self->b_ptr;
! 	return self->b_size;
  }
  
--- 537,543 ----
  		return -1;
  	}
! 	if (!get_buf(self, pp, &size))
! 		return -1;
! 	return size;
  }
  
***************
*** 497,502 ****
  buffer_getsegcount(PyBufferObject *self, int *lenp)
  {
! 	if ( lenp )
! 		*lenp = self->b_size;
  	return 1;
  }
--- 556,565 ----
  buffer_getsegcount(PyBufferObject *self, int *lenp)
  {
! 	void *ptr;
! 	int size;
! 	if (!get_buf(self, &ptr, &size))
! 		return -1;
! 	if (lenp)
! 		*lenp = size;
  	return 1;
  }
***************
*** 505,508 ****
--- 568,573 ----
  buffer_getcharbuf(PyBufferObject *self, int idx, const char **pp)
  {
+ 	void *ptr;
+ 	int size;
  	if ( idx != 0 ) {
  		PyErr_SetString(PyExc_SystemError,
***************
*** 510,515 ****
  		return -1;
  	}
! 	*pp = (const char *)self->b_ptr;
! 	return self->b_size;
  }
  
--- 575,582 ----
  		return -1;
  	}
! 	if (!get_buf(self, &ptr, &size))
! 		return -1;
! 	*pp = (const char *)ptr;
! 	return size;
  }
  




More information about the Python-checkins mailing list