[dovecot-cvs] dovecot/src/lib-mail message-part-serialize.c,1.11,1.12 message-part-serialize.h,1.6,1.7
cras at procontrol.fi
cras at procontrol.fi
Mon Jan 6 20:54:38 EET 2003
Update of /home/cvs/dovecot/src/lib-mail
In directory danu:/tmp/cvs-serv9576/lib-mail
Modified Files:
message-part-serialize.c message-part-serialize.h
Log Message:
message_part_deserialize() now verifies that the data is valid so we don't
later crash to some assert.
Index: message-part-serialize.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/message-part-serialize.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- message-part-serialize.c 5 Jan 2003 13:09:52 -0000 1.11
+++ message-part-serialize.c 6 Jan 2003 18:54:36 -0000 1.12
@@ -33,11 +33,21 @@
unsigned int flags;
};
+struct deserialize_context {
+ pool_t pool;
+
+ const struct serialized_message_part *spart;
+ unsigned int sparts_left;
+
+ uoff_t pos;
+ const char *error;
+};
+
static unsigned int
_message_part_serialize(struct message_part *part, buffer_t *dest)
{
struct serialized_message_part *spart;
- unsigned int count = 1;
+ unsigned int count = 0;
while (part != NULL) {
/* create serialized part */
@@ -74,39 +84,87 @@
_message_part_serialize(part, dest);
}
-static struct message_part *
-message_part_deserialize_part(pool_t pool, struct message_part *parent,
- const struct serialized_message_part **spart_pos,
- size_t *count, unsigned int child_count)
+static int message_part_deserialize_part(struct deserialize_context *ctx,
+ struct message_part *parent,
+ unsigned int child_count,
+ struct message_part **part_r)
{
const struct serialized_message_part *spart;
struct message_part *part, *first_part, **next_part;
- unsigned int i;
+ uoff_t pos;
first_part = NULL;
next_part = NULL;
- for (i = 0; i < child_count && *count > 0; i++) {
- spart = *spart_pos;
- (*spart_pos)++;
- (*count)--;
+ while (child_count > 0) {
+ child_count--;
+ if (ctx->sparts_left == 0) {
+ ctx->error = "Not enough data for all parts";
+ return FALSE;
+ }
- part = p_new(pool, struct message_part, 1);
+ spart = ctx->spart;
+ ctx->spart++;
+ ctx->sparts_left--;
+
+ part = p_new(ctx->pool, struct message_part, 1);
part->physical_pos = spart->physical_pos;
+ if (part->physical_pos < ctx->pos) {
+ ctx->error = "physical_pos less than expected";
+ return FALSE;
+ }
+
part->header_size.physical_size = spart->header_physical_size;
part->header_size.virtual_size = spart->header_virtual_size;
part->header_size.lines = spart->header_lines;
+ if (spart->header_virtual_size < spart->header_physical_size) {
+ ctx->error = "header_virtual_size too small";
+ return FALSE;
+ }
+
part->body_size.physical_size = spart->body_physical_size;
part->body_size.virtual_size = spart->body_virtual_size;
part->body_size.lines = spart->body_lines;
- part->flags = spart->flags;
+ if (spart->body_virtual_size < spart->body_physical_size) {
+ ctx->error = "body_virtual_size too small";
+ return FALSE;
+ }
+ part->flags = spart->flags;
part->parent = parent;
- part->children = message_part_deserialize_part(pool, part,
- spart_pos, count,
- spart->children_count);
+
+ /* our children must be after our physical_pos and the last
+ child must be within our size. */
+ ctx->pos = part->physical_pos;
+ pos = part->physical_pos + spart->header_physical_size +
+ spart->body_physical_size;
+
+ if (!message_part_deserialize_part(ctx, part,
+ spart->children_count,
+ &part->children))
+ return FALSE;
+
+ if (ctx->pos > pos) {
+ ctx->error = "child part location exceeds our size";
+ return FALSE;
+ }
+ ctx->pos = pos; /* save it for above check for parent */
+
+ if (part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) {
+ /* Only one child is possible */
+ if (part->children == NULL) {
+ ctx->error =
+ "message/rfc822 part has no children";
+ return FALSE;
+ }
+ if (part->children->next != NULL) {
+ ctx->error = "message/rfc822 part "
+ "has multiple children";
+ return FALSE;
+ }
+ }
if (first_part == NULL)
first_part = part;
@@ -115,26 +173,49 @@
next_part = &part->next;
}
- return first_part;
+ *part_r = first_part;
+ return TRUE;
}
struct message_part *message_part_deserialize(pool_t pool, const void *data,
- size_t size)
+ size_t size, const char **error)
{
- const struct serialized_message_part *spart;
- size_t count;
+ struct deserialize_context ctx;
+ struct message_part *part;
/* make sure it looks valid */
- if (size < sizeof(struct serialized_message_part))
+ if (size < sizeof(struct serialized_message_part)) {
+ *error = "Not enough data for root";
return NULL;
+ }
- spart = data;
- count = size / sizeof(struct serialized_message_part);
- if (count > UINT_MAX)
+ if ((size % sizeof(struct serialized_message_part)) != 0) {
+ *error = "Incorrect data size";
+ return NULL;
+ }
+
+ if (size / sizeof(struct serialized_message_part) > UINT_MAX) {
+ *error = "Insane amount of data";
return NULL;
+ }
- return message_part_deserialize_part(pool, NULL, &spart, &count,
- (unsigned int)count);
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.pool = pool;
+ ctx.spart = data;
+ ctx.sparts_left =
+ (unsigned int) (size / sizeof(struct serialized_message_part));
+
+ if (!message_part_deserialize_part(&ctx, NULL, 1, &part)) {
+ *error = ctx.error;
+ return NULL;
+ }
+
+ if (ctx.sparts_left > 0) {
+ *error = "Too much data";
+ return NULL;
+ }
+
+ return part;
}
int message_part_serialize_update_header(void *data, size_t size,
Index: message-part-serialize.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-mail/message-part-serialize.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- message-part-serialize.h 5 Jan 2003 13:09:52 -0000 1.6
+++ message-part-serialize.h 6 Jan 2003 18:54:36 -0000 1.7
@@ -7,9 +7,10 @@
/* Serialize message part. */
void message_part_serialize(struct message_part *part, buffer_t *dest);
-/* Generate struct message_part from serialized data. */
+/* Generate struct message_part from serialized data. Returns NULL and sets
+ error if any problems are detected. */
struct message_part *message_part_deserialize(pool_t pool, const void *data,
- size_t size);
+ size_t size, const char **error);
/* Update header size in serialized struct message_part. */
int message_part_serialize_update_header(void *data, size_t size,
More information about the dovecot-cvs
mailing list