[dovecot-cvs] dovecot/src/lib buffer.c,1.5,1.6

cras at procontrol.fi cras at procontrol.fi
Sun Dec 22 18:46:18 EET 2002


Update of /home/cvs/dovecot/src/lib
In directory danu:/tmp/cvs-serv10695

Modified Files:
	buffer.c 
Log Message:
Several fixes. I think it's beginning to look safe.



Index: buffer.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/buffer.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- buffer.c	21 Dec 2002 22:02:20 -0000	1.5
+++ buffer.c	22 Dec 2002 16:46:16 -0000	1.6
@@ -31,21 +31,30 @@
 
 	const unsigned char *r_buffer;
 	unsigned char *w_buffer;
-	size_t used, alloc, max_alloc, limit, start_pos;
+
+	/* buffer_set_start_pos() modifies start_pos, but internally we deal
+	   only with absolute positions. buffer_check_read|write modifies
+	   given position to absolute one.
+
+	   start_pos <= used <= alloc <= max_alloc.
+	   start_pos <= limit <= max_alloc */
+	size_t start_pos, used, alloc, max_alloc, limit;
 
 	unsigned int alloced:1;
 	unsigned int readonly:1;
 	unsigned int hard:1;
 };
 
-static void buffer_alloc(Buffer *buf, size_t min_size)
+static void buffer_alloc(Buffer *buf, size_t size)
 {
-	if (min_size == 0)
+	i_assert(buf->w_buffer == NULL || buf->alloced);
+
+	if (size == buf->alloc)
 		return;
 
-	i_assert(buf->w_buffer == NULL || buf->alloced);
+	i_assert(size > buf->alloc);
 
-	buf->alloc = min_size;
+	buf->alloc = size;
 	if (buf->w_buffer == NULL)
 		buf->w_buffer = p_malloc(buf->pool, buf->alloc);
 	else
@@ -78,42 +87,41 @@
 		return FALSE;
 
 	/* check that we don't overflow size_t */
-	max_size = (size_t)-1 - *pos;
-	if (buf->start_pos >= max_size)
+	if (*pos >= (size_t)-1 - buf->start_pos)
 		return FALSE;
 	*pos += buf->start_pos;
 
+	max_size = (size_t)-1 - *pos;
 	if (*data_size <= max_size)
 		new_size = *pos + *data_size;
 	else {
-		new_size = *pos + max_size;
-		if (new_size <= *pos || !accept_partial)
+		if (max_size == 0 || !accept_partial)
 			return FALSE;
+
+		new_size = *pos + max_size;
 		*data_size = max_size;
 	}
 
+	/* make sure we're within our limits */
+	if (new_size > buf->limit) {
+		if (buf->hard) {
+			i_panic("Buffer full (%"PRIuSIZE_T" > "
+				"%"PRIuSIZE_T")",
+				new_size, buf->limit);
+		}
+
+		if (!accept_partial || *pos >= buf->limit)
+			return FALSE;
+
+		new_size = buf->limit;
+		*data_size = new_size - *pos;
+	}
+
 	/* see if we need to grow the buffer */
 	if (new_size > buf->alloc) {
 		alloc_size = nearest_power(new_size);
-		if (alloc_size > buf->limit) {
-			if (buf->hard) {
-				i_panic("Buffer full (%"PRIuSIZE_T" > "
-					"%"PRIuSIZE_T")",
-					alloc_size, buf->limit);
-			}
-
-			if (!accept_partial)
-				return FALSE;
-
+		if (alloc_size > buf->limit)
 			alloc_size = buf->limit;
-			if (*pos >= alloc_size)
-				return FALSE;
-
-			*data_size = alloc_size - *pos;
-		}
-
-		if (new_size > alloc_size)
-			new_size = alloc_size;
 
 		if (alloc_size != buf->alloc)
 			buffer_alloc(buf, alloc_size);
@@ -227,10 +235,13 @@
 {
 	size_t move_size, size;
 
-	move_size = buf->used - buf->start_pos;
-	i_assert(pos <= move_size);
+	/* move_size == number of bytes we have to move forward to make space */
+	move_size = I_MIN(buf->used, buf->limit) - buf->start_pos;
+	if (pos >= move_size)
+		return 0;
 	move_size -= pos;
 
+	/* size == number of bytes we want to modify after pos */
 	if (data_size < (size_t)-1 - move_size)
 		size = data_size + move_size;
 	else
@@ -241,6 +252,7 @@
 
 	i_assert(size >= move_size);
 	size -= move_size;
+	/* size == number of bytes we actually inserted. data_size usually. */
 
 	memmove(buf->w_buffer + pos + size, buf->w_buffer + pos, move_size);
 	memcpy(buf->w_buffer + pos, data, size);
@@ -254,8 +266,9 @@
 	if (buf->readonly)
 		return 0;
 
-	end_size = buf->used - buf->start_pos;
-	i_assert(pos <= end_size);
+	end_size = I_MIN(buf->used, buf->limit) - buf->start_pos;
+	if (pos >= end_size)
+		return 0;
 	end_size -= pos;
 
 	if (size < end_size) {
@@ -302,7 +315,7 @@
 void *buffer_get_space(Buffer *buf, size_t pos, size_t size)
 {
 	if (!buffer_check_write(buf, &pos, &size, FALSE))
-		return 0;
+		return NULL;
 
 	return buf->w_buffer + pos;
 }
@@ -363,7 +376,7 @@
 		limit += buf->start_pos;
 
 	buf->limit = I_MIN(limit, buf->max_alloc);
-	return old;
+	return old - buf->start_pos;
 }
 
 size_t buffer_get_limit(const Buffer *buf)
@@ -377,13 +390,15 @@
 }
 
 #ifdef BUFFER_TEST
-/* gcc buffer.c -o buffer liblib.a -Wall -DHAVE_CONFIG_H -DBUFFER_TEST -g */
+/* gcc buffer.c -o testbuffer liblib.a -Wall -DHAVE_CONFIG_H -DBUFFER_TEST -g */
 int main(void)
 {
 	Buffer *buf;
 	char data[12], *bufdata;
 	size_t bufsize;
 
+	lib_init();
+
 	memset(data, '!', sizeof(data));
 	bufdata = data + 1;
 	bufsize = sizeof(data)-2;
@@ -406,17 +421,20 @@
 	i_assert(buffer_append(buf, "123456", 6) == 5);
 	i_assert(buf->used == 10);
 
-	buf = buffer_create_data(system_pool, bufdata, bufsize);
+	buf = buffer_create_data(system_pool, data, sizeof(data));
+	buffer_set_used_size(buf, 1);
+	buffer_set_start_pos(buf, 1);
+	buffer_set_limit(buf, sizeof(data)-2);
 	i_assert(buffer_append(buf, "12345", 5) == 5);
 	i_assert(buffer_insert(buf, 2, "123456", 6) == 5);
-	i_assert(buf->used == 10);
-	i_assert(memcmp(buf->r_buffer, "1212345345", 10) == 0);
+	i_assert(buf->used == 11);
+	i_assert(memcmp(buf->r_buffer, "!1212345345", 11) == 0);
 	i_assert(buffer_delete(buf, 2, 5) == 5);
-	i_assert(buf->used == 5);
-	i_assert(memcmp(buf->r_buffer, "12345", 5) == 0);
+	i_assert(buf->used == 6);
+	i_assert(memcmp(buf->r_buffer, "!12345", 6) == 0);
 	i_assert(buffer_delete(buf, 3, 5) == 2);
-	i_assert(buf->used == 3);
-	i_assert(memcmp(buf->r_buffer, "123", 3) == 0);
+	i_assert(buf->used == 4);
+	i_assert(memcmp(buf->r_buffer, "!123", 4) == 0);
 
 	i_assert(data[0] == '!');
 	i_assert(data[sizeof(data)-1] == '!');




More information about the dovecot-cvs mailing list