[dovecot-cvs] dovecot/src/lib buffer.c,NONE,1.1 buffer.h,NONE,1.1 Makefile.am,1.19,1.20 base64.c,1.6,1.7 base64.h,1.7,1.8 data-stack.c,1.8,1.9 hex-binary.c,1.2,1.3 hex-binary.h,1.4,1.5 lib.h,1.10,1.11

cras at procontrol.fi cras at procontrol.fi
Sun Dec 8 07:23:10 EET 2002


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

Modified Files:
	Makefile.am base64.c base64.h data-stack.c hex-binary.c 
	hex-binary.h lib.h 
Added Files:
	buffer.c buffer.h 
Log Message:
Added buffer API. Point is to hide all buffer writing behind this API which
verifies that nothing overflows. Much better than doing the same checks all
around the code, even if it is slightly slower.

Buffer reading is still mostly done directly, that isn't such a big security
risk and I can't think of a reasonable API for it anyway.



--- NEW FILE: buffer.c ---
/*
    Copyright (c) 2002 Timo Sirainen

    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files (the
    "Software"), to deal in the Software without restriction, including
    without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to
    permit persons to whom the Software is furnished to do so, subject to
    the following conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include "lib.h"
#include "buffer.h"

struct _Buffer {
	Pool pool;

	const unsigned char *r_buffer;
	unsigned char *w_buffer;
	size_t used, alloc, max_alloc, limit, start_pos;

	unsigned int alloced:1;
	unsigned int readonly:1;
	unsigned int hard:1;
};

static void buffer_alloc(Buffer *buf, size_t min_size)
{
	if (min_size == 0)
		return;

	buf->alloc = min_size;
	if (buf->w_buffer == NULL)
		buf->w_buffer = p_malloc(buf->pool, buf->alloc);
	else
		buf->w_buffer = p_realloc(buf->pool, buf->w_buffer, buf->alloc);
	buf->r_buffer = buf->w_buffer;
	buf->alloced = TRUE;
}

static int buffer_check_read(const Buffer *buf, size_t *pos, size_t *data_size)
{
	size_t used_size, max_size;

	used_size = I_MIN(buf->used, buf->limit);
	if (*pos >= used_size - buf->start_pos)
		return FALSE;

	*pos += buf->start_pos;
	max_size = used_size - *pos;
	if (*data_size > max_size)
		*data_size = max_size;
	return TRUE;
}

static int buffer_check_write(Buffer *buf, size_t *pos, size_t *data_size,
			      int accept_partial)
{
	size_t max_size, new_size;

	if (buf->readonly)
		return FALSE;

	/* check that we don't overflow size_t */
	max_size = (size_t)-1 - *pos;
	if (buf->start_pos >= max_size)
		return FALSE;
	*pos += buf->start_pos;

	if (*data_size <= max_size)
		new_size = *pos + *data_size;
	else {
		new_size = *pos + max_size;
		if (new_size <= *pos || !accept_partial)
			return FALSE;
		*data_size = max_size;
	}

	/* see if we need to grow the buffer */
	if (new_size > buf->alloc) {
		if (new_size > buf->limit) {
			if (buf->hard) {
				i_panic("Buffer full (%"PRIuSIZE_T" > "
					"%"PRIuSIZE_T")", new_size, buf->limit);
			}

			if (!accept_partial)
				return FALSE;

			new_size = buf->limit;
			if (new_size == buf->alloc || new_size <= *pos)
				return FALSE;

			*data_size = new_size - *pos;
		}

		buffer_alloc(buf, new_size);
	}

	if (new_size > buf->used)
		buf->used = new_size;
	return TRUE;
}

Buffer *buffer_create_static(Pool pool, size_t size)
{
	Buffer *buf;

	buf = p_new(pool, Buffer, 1);
	buf->pool = pool;
	buf->max_alloc = buf->limit = size;
	buffer_alloc(buf, size);
	return buf;
}

Buffer *buffer_create_static_hard(Pool pool, size_t size)
{
	Buffer *buf;

	buf = buffer_create_static(pool, size);
	buf->hard = TRUE;
	return buf;
}

Buffer *buffer_create_data(Pool pool, void *data, size_t size)
{
	Buffer *buf;

	buf = p_new(pool, Buffer, 1);
	buf->pool = pool;
	buf->max_alloc = buf->limit = size;
	buf->r_buffer = buf->w_buffer = data;
	return buf;
}

Buffer *buffer_create_const_data(Pool pool, const void *data, size_t size)
{
	Buffer *buf;

	buf = p_new(pool, Buffer, 1);
	buf->pool = pool;
	buf->used = buf->max_alloc = buf->limit = size;
	buf->r_buffer = data;
	buf->readonly = TRUE;
	return buf;
}

Buffer *buffer_create_dynamic(Pool pool, size_t init_size, size_t max_size)
{
	Buffer *buf;

	buf = p_new(pool, Buffer, 1);
	buf->pool = pool;
	buf->max_alloc = buf->limit = max_size;
	buffer_alloc(buf, init_size);
	return buf;
}

void buffer_free(Buffer *buf)
{
	if (buf->alloced)
		p_free(buf->pool, buf->w_buffer);
	p_free(buf->pool, buf);
}

void *buffer_free_without_data(Buffer *buf)
{
	void *data;

	data = buf->w_buffer;
	p_free(buf->pool, buf);
	return data;
}

size_t buffer_write(Buffer *buf, size_t pos,
		    const void *data, size_t data_size)
{
	if (!buffer_check_write(buf, &pos, &data_size, TRUE))
		return 0;

	memcpy(buf->w_buffer + pos, data, data_size);
	return data_size;
}

size_t buffer_append(Buffer *buf, const void *data, size_t data_size)
{
	return buffer_write(buf, buf->used - buf->start_pos, data, data_size);
}

size_t buffer_append_c(Buffer *buf, char chr)
{
	size_t pos, data_size = 1;

	pos = buf->used - buf->start_pos;
	if (!buffer_check_write(buf, &pos, &data_size, TRUE))
		return 0;

	if (data_size == 1)
		buf->w_buffer[pos] = chr;
	return data_size;
}

size_t buffer_copy(Buffer *dest, size_t dest_pos,
		   const Buffer *src, size_t src_pos, size_t copy_size)
{
	if (!buffer_check_read(src, &src_pos, &copy_size))
		return 0;

	if (!buffer_check_write(dest, &dest_pos, &copy_size, TRUE))
		return 0;

	if (src == dest) {
		memmove(dest->w_buffer + dest_pos,
			src->r_buffer + src_pos, copy_size);
	} else {
		memcpy(dest->w_buffer + dest_pos,
		       src->r_buffer + src_pos, copy_size);
	}
	return copy_size;
}

size_t buffer_append_buf(Buffer *dest, const Buffer *src,
			 size_t src_pos, size_t copy_size)
{
	return buffer_copy(dest, dest->used - dest->start_pos,
			   src, src_pos, copy_size);
}

void *buffer_get_space(Buffer *buf, size_t pos, size_t size)
{
	if (!buffer_check_write(buf, &pos, &size, FALSE))
		return 0;

	return buf->w_buffer + pos;
}

void *buffer_append_space(Buffer *buf, size_t size)
{
	return buffer_get_space(buf, buf->used - buf->start_pos, size);
}

const void *buffer_get_data(const Buffer *buf, size_t *used_size)
{
	if (used_size != NULL)
		*used_size = I_MIN(buf->used, buf->limit) - buf->start_pos;
	return buf->r_buffer + buf->start_pos;
}

void *buffer_get_modifyable_data(const Buffer *buf, size_t *used_size)
{
	if (used_size != NULL)
		*used_size = I_MIN(buf->used, buf->limit) - buf->start_pos;
	return buf->w_buffer + buf->start_pos;
}

void buffer_set_used_size(Buffer *buf, size_t used_size)
{
	i_assert(used_size <= I_MIN(buf->alloc, buf->limit) - buf->start_pos);

	buf->used = used_size + buf->start_pos;
}

size_t buffer_get_used_size(const Buffer *buf)
{
	return I_MIN(buf->used, buf->limit) - buf->start_pos;
}

size_t buffer_set_start_pos(Buffer *buf, size_t abs_pos)
{
	size_t old = buf->start_pos;

	i_assert(abs_pos <= I_MIN(buf->used, buf->limit));

	buf->start_pos = abs_pos;
	return old;
}

size_t buffer_get_start_pos(const Buffer *buf)
{
	return buf->start_pos;
}

size_t buffer_set_limit(Buffer *buf, size_t limit)
{
	size_t old = buf->limit;

	if (limit > (size_t)-1 - buf->start_pos)
		limit = (size_t)-1;
	else
		limit += buf->start_pos;

	buf->limit = I_MIN(limit, buf->max_alloc);
	return old;
}

size_t buffer_get_limit(const Buffer *buf)
{
	return buf->limit - buf->start_pos;
}

size_t buffer_get_size(const Buffer *buf)
{
	return buf->alloc - buf->start_pos;
}

--- NEW FILE: buffer.h ---
#ifndef __BUFFER_H
#define __BUFFER_H

/* Create a static sized buffer. Writes past this size will simply not
   succeed. */
Buffer *buffer_create_static(Pool pool, size_t size);
/* Create a static sized buffer. Writes past this size will kill the program. */
Buffer *buffer_create_static_hard(Pool pool, size_t size);
/* Create a modifyable buffer from given data. */
Buffer *buffer_create_data(Pool pool, void *data, size_t size);
/* Create a non-modifyable buffer from given data. */
Buffer *buffer_create_const_data(Pool pool, const void *data, size_t size);
/* Creates a dynamically growing buffer. Whenever write would exceed the
   current size it's grown. */
Buffer *buffer_create_dynamic(Pool pool, size_t init_size, size_t max_size);
/* Free the memory used by buffer. Not needed if the memory is free'd
   directly from the memory pool. */
void buffer_free(Buffer *buf);
/* Free the memory used by buffer structure, but return the buffer data
   unfree'd.*/
void *buffer_free_without_data(Buffer *buf);

/* Write data to buffer at specified position, returns number of bytes
   written. */
size_t buffer_write(Buffer *buf, size_t pos,
		    const void *data, size_t data_size);
/* Append data to buffer, returns number of bytes written. */
size_t buffer_append(Buffer *buf, const void *data, size_t data_size);
/* Append character to buffer, returns 1 if written, 0 if not. */
size_t buffer_append_c(Buffer *buf, char chr);

/* Copy data from buffer to another. The buffers may be same in which case
   it's internal copying, possibly with overlapping positions (ie. memmove()
   like functionality). copy_size may be set to (size_t)-1 to copy the rest of
   the used data in buffer. Returns the number of bytes actually copied. */
size_t buffer_copy(Buffer *dest, size_t dest_pos,
		   const Buffer *src, size_t src_pos, size_t copy_size);
/* Append data to buffer from another. copy_size may be set to (size_t)-1 to
   copy the rest of the used data in buffer. */
size_t buffer_append_buf(Buffer *dest, const Buffer *src,
			 size_t src_pos, size_t copy_size);

/* Returns pointer to specified position in buffer, or NULL if there's not
   enough space. */
void *buffer_get_space(Buffer *buf, size_t pos, size_t size);
/* Increase the buffer usage by given size, and return a pointer to beginning
   of it, or NULL if there's not enough space in buffer. */
void *buffer_append_space(Buffer *buf, size_t size);

/* Returns pointer to beginning of buffer data. Current used size of buffer is
   stored in used_size if it's non-NULL. */
const void *buffer_get_data(const Buffer *buf, size_t *used_size);
/* Like buffer_get_data(), but don't return it as const. Returns NULL if the
   buffer is non-modifyable. */
void *buffer_get_modifyable_data(const Buffer *buf, size_t *used_size);

/* Set the "used size" of buffer, ie. 0 would set the buffer empty.
   Must not be used to grow buffer. */
void buffer_set_used_size(Buffer *buf, size_t used_size);
/* Returns the current used buffer size. */
size_t buffer_get_used_size(const Buffer *buf);

/* Change the buffer start position. The buffer acts as if data was removed or
   inserted to beginning. Returns the old start position. */
size_t buffer_set_start_pos(Buffer *buf, size_t abs_pos);
/* Returns the current start position. */
size_t buffer_get_start_pos(const Buffer *buf);

/* Limit buffer size temporarily. All handling is treated as if this is the
   current allocated memory size, except dynamic buffer won't be grown.
   Setting the limit to (size_t)-1 removes it. Returns the old limit. */
size_t buffer_set_limit(Buffer *buf, size_t limit);
/* Returns the current buffer limit, or (size_t)-1 if there's none. */
size_t buffer_get_limit(const Buffer *buf);

/* Returns the current buffer size. */
size_t buffer_get_size(const Buffer *buf);

#endif

Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/lib/Makefile.am,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- Makefile.am	6 Dec 2002 01:09:22 -0000	1.19
+++ Makefile.am	8 Dec 2002 05:23:07 -0000	1.20
@@ -3,6 +3,7 @@
 liblib_a_SOURCES = \
 	alarm-hup.c \
 	base64.c \
+	buffer.c \
 	compat.c \
 	data-stack.c \
 	env-util.c \
@@ -52,6 +53,7 @@
 noinst_HEADERS = \
 	alarm-hup.h \
 	base64.h \
+	buffer.h \
 	compat.h \
 	data-stack.h \
 	env-util.h \

Index: base64.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/base64.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- base64.c	13 Nov 2002 11:08:18 -0000	1.6
+++ base64.c	8 Dec 2002 05:23:07 -0000	1.7
@@ -41,41 +41,48 @@
 
 #include "lib.h"
 #include "base64.h"
+#include "buffer.h"
 
 static const char basis_64[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
-const char *base64_encode(const unsigned char *data, size_t size)
+int base64_encode(const unsigned char *src, size_t src_size, Buffer *dest)
 {
-	char *buffer, *p;
+	size_t src_pos;
 	int c1, c2, c3;
 
-	/* + rounding errors + "==" + '\0' */
-	buffer = p = t_malloc(size/3*4 + 2+2+1);
-	while (size > 0) {
-		c1 = *data++; size--;
-		*p++ = basis_64[c1 >> 2];
+	for (src_pos = 0; src_pos < src_size; ) {
+		c1 = src[src_pos++];
+		if (buffer_append_c(dest, basis_64[c1 >> 2]) != 1)
+			return 0;
 
-		c2 = size == 0 ? 0 : *data++;
-		*p++ = basis_64[((c1 & 0x03) << 4) | ((c2 & 0xf0) >> 4)];
-		if (size-- == 0) {
-			*p++ = '=';
-			*p++ = '=';
+		c2 = src_pos == src_size ? 0 : src[src_pos++];
+		if (buffer_append_c(dest, basis_64[((c1 & 0x03) << 4) |
+						   ((c2 & 0xf0) >> 4)]) != 1)
+			return 0;
+
+		if (src_pos++ == src_size) {
+			if (buffer_append(dest, "==", 2) != 2)
+				return 0;
 			break;
 		}
 
-		c3 = size == 0 ? 0 : *data++;
-		*p++ = basis_64[((c2 & 0x0f) << 2) | ((c3 & 0xc0) >> 6)];
-		if (size-- == 0) {
-			*p++ = '=';
+		c3 = src_pos == src_size ? 0 : src[src_pos++];
+		if (buffer_append_c(dest, basis_64[((c2 & 0x0f) << 2) |
+						   ((c3 & 0xc0) >> 6)]) != 1)
+			return 0;
+
+		if (src_pos++ == src_size) {
+			if (buffer_append_c(dest, '=') != 1)
+				return 0;
 			break;
 		}
 
-		*p++ = basis_64[c3 & 0x3f];
+		if (buffer_append_c(dest, basis_64[c3 & 0x3f]) != 1)
+			return 0;
 	}
 
-	*p = '\0';
-	return buffer;
+	return 1;
 }
 
 #define XX 127
@@ -99,54 +106,73 @@
     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
 };
-#define CHAR64(c)  (index_64[(int)(unsigned char)(c)])
 
-ssize_t base64_decode(const char *src, size_t *size, unsigned char *dest)
+int base64_decode(const unsigned char *src, size_t src_size,
+		  size_t *src_pos_r, Buffer *dest)
 {
-	unsigned char *p;
-	size_t left;
+	size_t src_pos;
+	unsigned char buf[4];
 	int c1, c2, c3, c4;
+	size_t ret, size;
 
-	p = dest; left = *size;
-	while (left >= 4) {
-		c1 = *src++;
+	for (src_pos = 0; src_pos+3 < src_size; ) {
+		c1 = src[src_pos++];
 
-		if (c1 == '\n' || c1 == '\r' || c1 == ' ' || c1 == '\t') {
-			left--;
+		if (c1 == '\n' || c1 == '\r' || c1 == ' ' || c1 == '\t')
 			continue;
-		}
 
-		if (CHAR64(c1) == XX)
+		if (index_64[c1] == XX)
 			return -1;
 
-		c2 = *src++;
-		if (CHAR64(c2) == XX)
+		c2 = src[src_pos++];
+		if (index_64[c2] == XX)
 			return -1;
 
-		c3 = *src++;
-		if (c3 != '=' && CHAR64(c3) == XX)
+		c3 = src[src_pos++];
+		if (c3 != '=' && index_64[c3] == XX)
 			return -1;
 
-		c4 = *src++;
-		if (c4 != '=' && CHAR64(c4) == XX)
+		c4 = src[src_pos++];
+		if (c4 != '=' && index_64[c4] == XX)
 			return -1;
 
-		left -= 4;
-
-		*p++ = ((CHAR64(c1) << 2) | ((CHAR64(c2) & 0x30) >> 4));
-
+		buf[0] = (index_64[c1] << 2) | ((index_64[c2] & 0x30) >> 4);
 		if (c3 == '=') {
 			if (c4 != '=')
 				return -1;
-			break;
+			size = 1;
+		} else {
+			buf[1] = ((index_64[c2] & 0xf) << 4) |
+				((index_64[c3] & 0x3c) >> 2);
+
+			if (c4 == '=')
+				size = 2;
+			else {
+				buf[2] = ((index_64[c3] & 0x3) << 6) |
+					index_64[c4];
+				size = 3;
+			}
 		}
 
-		*p++ = (((CHAR64(c2) & 0xf) << 4) | ((CHAR64(c3) & 0x3c) >> 2));
-		if (c4 == '=')
+		ret = buffer_append(dest, buf, size);
+		if (ret != size) {
+			/* buffer full */
+			if (src_pos_r != NULL) {
+				*src_pos_r = src_pos-4;
+                                ret = buffer_get_used_size(dest) - (size-ret);
+				buffer_set_used_size(dest, ret);
+			}
+			return 0;
+		}
+
+		if (size < 3) {
+			/* end of base64 data */
 			break;
-		*p++ = (((CHAR64(c3) & 0x3) << 6) | CHAR64(c4));
+		}
 	}
 
-	*size -= left;
-	return (ssize_t) (p-dest);
+	if (src_pos_r != NULL)
+		*src_pos_r = src_pos;
+
+	return 1;
 }

Index: base64.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/base64.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- base64.h	13 Nov 2002 11:08:18 -0000	1.7
+++ base64.h	8 Dec 2002 05:23:07 -0000	1.8
@@ -1,21 +1,25 @@
 #ifndef __BASE64_H
 #define __BASE64_H
 
-/* Translates binary data into base64. Allocates memory from data stack. */
-const char *base64_encode(const unsigned char *data, size_t size);
+/* Translates binary data into base64. The src must not point to dest buffer.
+   Returns 1 if all ok, 0 if dest buffer got full. */
+int base64_encode(const unsigned char *src, size_t src_size, Buffer *dest);
 
-/* Translates base64 data into binary. dest must be large enough, and may be
-   same as src. Returns size of the binary data, or -1 if error occured.
-   Any CR, LF characters are ignored, as well as whitespace at beginning or
-   end of line.
+/* Translates base64 data into binary and appends it to dest buffer. dest may
+   point to same buffer as src. Returns 1 if all ok, 0 if dest buffer got full
+   or -1 if data is invalid. Any CR, LF characters are ignored, as well as
+   whitespace at beginning or end of line.
 
-   This function may be called multiple times for parsing same base64 stream.
-   The *size is updated at return to contain the amount of data actually
-   parsed - the rest of the data should be passed again to this function. */
-ssize_t base64_decode(const char *src, size_t *size, unsigned char *dest);
+   This function may be called multiple times for parsing the same stream.
+   If src_pos is non-NULL, it's updated to first non-translated character in
+   src. */
+int base64_decode(const unsigned char *src, size_t src_size,
+		  size_t *src_pos_r, Buffer *dest);
 
-/* max. buffer size required for base64_decode(), not including trailing \0 */
+/* max. buffer size required for base64_encode() */
+#define MAX_BASE64_ENCODED_SIZE(size) \
+	((size) / 3 * 4 + 2+2)
+/* max. buffer size required for base64_decode() */
 #define MAX_BASE64_DECODED_SIZE(size) \
 	((size) / 4 * 3 + 3)
-
 #endif

Index: data-stack.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/data-stack.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- data-stack.c	3 Dec 2002 13:20:33 -0000	1.8
+++ data-stack.c	8 Dec 2002 05:23:07 -0000	1.9
@@ -41,7 +41,11 @@
 
 /* Initial stack size - this should be kept in a size that doesn't exceed
    in a normal use to avoid extra malloc()ing. */
-#define INITIAL_STACK_SIZE (1024*32)
+#ifdef DEBUG
+#  define INITIAL_STACK_SIZE (1024*8)
+#else
+#  define INITIAL_STACK_SIZE (1024*32)
+#endif
 
 typedef struct _StackBlock StackBlock;
 typedef struct _StackFrameBlock StackFrameBlock;

Index: hex-binary.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/hex-binary.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- hex-binary.c	8 Sep 2002 13:20:28 -0000	1.2
+++ hex-binary.c	8 Dec 2002 05:23:07 -0000	1.3
@@ -24,6 +24,7 @@
 */
 
 #include "lib.h"
+#include "buffer.h"
 #include "hex-binary.h"
 
 const char *binary_to_hex(const unsigned char *data, size_t size)
@@ -45,12 +46,10 @@
 	return buf;
 }
 
-ssize_t hex_to_binary(const char *data, unsigned char *dest)
+int hex_to_binary(const char *data, Buffer *dest)
 {
-	size_t size;
 	int value;
 
-	size = 0;
 	while (*data != '\0') {
 		if (*data >= '0' && *data <= '9')
 			value = (*data - '0') << 4;
@@ -71,9 +70,10 @@
 		else
 			return -1;
 
-		dest[size++] = value;
+		if (buffer_append_c(dest, value) != 1)
+			return 0;
 		data++;
 	}
 
-	return (ssize_t)size;
+	return 1;
 }

Index: hex-binary.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/hex-binary.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- hex-binary.h	9 Oct 2002 17:49:41 -0000	1.4
+++ hex-binary.h	8 Dec 2002 05:23:07 -0000	1.5
@@ -6,9 +6,8 @@
 const char *binary_to_hex(const unsigned char *data, size_t size);
 
 /* Convert hex to binary. data and dest may point to same value.
-   Returns TRUE if successful. Returns number of bytes written to dest,
-   or -1 if error occured. Make sure dest is at least half the size of
-   strlen(data). */
-ssize_t hex_to_binary(const char *data, unsigned char *dest);
+   Returns TRUE if successful. Returns 1 if all ok, 0 if dest buffer got full
+   or -1 if data is invalid. */
+int hex_to_binary(const char *data, Buffer *dest);
 
 #endif

Index: lib.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/lib.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- lib.h	6 Dec 2002 01:09:22 -0000	1.10
+++ lib.h	8 Dec 2002 05:23:07 -0000	1.11
@@ -24,6 +24,7 @@
 typedef struct _IPADDR IPADDR;
 typedef struct _IStream IStream;
 typedef struct _OStream OStream;
+typedef struct _Buffer Buffer;
 typedef struct _TempString TempString;
 
 #include "compat.h"




More information about the dovecot-cvs mailing list