Mercurial > dovecot > original-hg > dovecot-1.2
changeset 877:7935347f54f1 HEAD
Don't access ImapArg's union members directly - too easy to mess up. Fixes a
crash with feeding non-string parameters to SEARCH/SORT commands.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 02 Jan 2003 10:09:26 +0200 |
parents | ad8f7d2107b4 |
children | cc1cf8161203 |
files | src/imap/cmd-append.c src/imap/cmd-fetch.c src/imap/cmd-search.c src/imap/cmd-sort.c src/imap/cmd-status.c src/imap/cmd-store.c src/imap/commands-util.c src/lib-imap/imap-bodystructure.c src/lib-imap/imap-envelope.c src/lib-imap/imap-parser.c src/lib-imap/imap-parser.h src/lib-storage/mail-search.c |
diffstat | 12 files changed, 131 insertions(+), 64 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/cmd-append.c Sun Dec 29 21:44:37 2002 +0200 +++ b/src/imap/cmd-append.c Thu Jan 02 10:09:26 2003 +0200 @@ -44,16 +44,16 @@ internal_date, msg_size, 4); if (args[1].type == IMAP_ARG_LIST) - *flags = args[1].data.list; + *flags = IMAP_ARG_LIST(&args[1]); else if (args[1].type == IMAP_ARG_STRING) - *internal_date = args[1].data.str; + *internal_date = IMAP_ARG_STR(&args[1]); else return -1; break; case 4: /* we have all parameters */ - *flags = args[1].data.list; - *internal_date = args[2].data.str; + *flags = IMAP_ARG_LIST(&args[1]); + *internal_date = IMAP_ARG_STR(&args[2]); break; default: i_unreached(); @@ -67,7 +67,7 @@ if (args[count-1].type != IMAP_ARG_LITERAL_SIZE) return -1; - *msg_size = args[count-1].data.literal_size; + *msg_size = IMAP_ARG_LITERAL_SIZE(&args[count-1]); return 1; }
--- a/src/imap/cmd-fetch.c Sun Dec 29 21:44:37 2002 +0200 +++ b/src/imap/cmd-fetch.c Thu Jan 02 10:09:26 2003 +0200 @@ -105,8 +105,7 @@ return FALSE; } - item = arg->data.str; - str_ucase(item); + item = str_ucase(IMAP_ARG_STR(arg)); switch (*item) { case 'A': @@ -215,7 +214,7 @@ if (item == NULL) { /* unknown item */ client_send_tagline(client, t_strconcat( - "BAD Invalid item ", arg->data.str, NULL)); + "BAD Invalid item ", IMAP_ARG_STR(arg), NULL)); return FALSE; } @@ -248,7 +247,7 @@ if (!parse_arg(client, &args[1], &data)) return TRUE; } else { - listargs = args[1].data.list->args; + listargs = IMAP_ARG_LIST(&args[1])->args; while (listargs->type != IMAP_ARG_EOL) { if (!parse_arg(client, listargs, &data)) return TRUE;
--- a/src/imap/cmd-search.c Sun Dec 29 21:44:37 2002 +0200 +++ b/src/imap/cmd-search.c Thu Jan 02 10:09:26 2003 +0200 @@ -26,7 +26,7 @@ return TRUE; if (args->type == IMAP_ARG_ATOM && - strcasecmp(args->data.str, "CHARSET") == 0) { + strcasecmp(IMAP_ARG_STR(args), "CHARSET") == 0) { /* CHARSET specified */ args++; if (args->type != IMAP_ARG_ATOM && @@ -36,7 +36,7 @@ return TRUE; } - charset = args->data.str; + charset = IMAP_ARG_STR(args); args++; } else { charset = NULL;
--- a/src/imap/cmd-sort.c Sun Dec 29 21:44:37 2002 +0200 +++ b/src/imap/cmd-sort.c Thu Jan 02 10:09:26 2003 +0200 @@ -34,7 +34,7 @@ (size_t)-1); while (args->type == IMAP_ARG_ATOM || args->type == IMAP_ARG_STRING) { - const char *arg = args->data.str; + const char *arg = IMAP_ARG_STR(args); for (i = 0; sort_names[i].type != MAIL_SORT_END; i++) { if (strcasecmp(arg, sort_names[i].name) == 0) @@ -91,7 +91,7 @@ return TRUE; } - sorting = get_sort_program(client, args->data.list->args); + sorting = get_sort_program(client, IMAP_ARG_LIST(args)->args); if (sorting == NULL) return TRUE; args++; @@ -101,7 +101,7 @@ client_send_command_error(client, "Invalid charset argument."); } - charset = args->data.str; + charset = IMAP_ARG_STR(args); args++; pool = pool_alloconly_create("MailSortArgs", 2048);
--- a/src/imap/cmd-status.c Sun Dec 29 21:44:37 2002 +0200 +++ b/src/imap/cmd-status.c Thu Jan 02 10:09:26 2003 +0200 @@ -19,8 +19,7 @@ return -1; } - str_ucase(args->data.str); - item = args->data.str; + item = str_ucase(IMAP_ARG_STR(args)); if (strcmp(item, "MESSAGES") == 0) items |= STATUS_MESSAGES; @@ -95,7 +94,7 @@ } /* get the items client wants */ - items = get_status_items(client, args[1].data.list->args); + items = get_status_items(client, IMAP_ARG_LIST(&args[1])->args); if (items == (MailboxStatusItems)-1) { /* error */ return TRUE;
--- a/src/imap/cmd-store.c Sun Dec 29 21:44:37 2002 +0200 +++ b/src/imap/cmd-store.c Thu Jan 02 10:09:26 2003 +0200 @@ -60,8 +60,9 @@ return TRUE; if (args[2].type == IMAP_ARG_LIST) { - if (!client_parse_mail_flags(client, args[2].data.list->args, - args[2].data.list->size, + if (!client_parse_mail_flags(client, + IMAP_ARG_LIST(&args[2])->args, + IMAP_ARG_LIST(&args[2])->size, &flags, custflags)) return TRUE; } else {
--- a/src/imap/commands-util.c Sun Dec 29 21:44:37 2002 +0200 +++ b/src/imap/commands-util.c Thu Jan 02 10:09:26 2003 +0200 @@ -129,7 +129,7 @@ return FALSE; } - atom = args[pos].data.str; + atom = IMAP_ARG_STR(&args[pos]); if (*atom == '\\') { /* system flag */ str_ucase(atom);
--- a/src/lib-imap/imap-bodystructure.c Sun Dec 29 21:44:37 2002 +0200 +++ b/src/lib-imap/imap-bodystructure.c Thu Jan 02 10:09:26 2003 +0200 @@ -456,15 +456,15 @@ str_append(str, "NIL"); break; case IMAP_ARG_ATOM: - str_append(str, args->data.str); + str_append(str, IMAP_ARG_STR(args)); break; case IMAP_ARG_STRING: str_append_c(str, '"'); - str_append(str, args->data.str); + str_append(str, IMAP_ARG_STR(args)); str_append_c(str, '"'); break; case IMAP_ARG_LIST: - if (!imap_write_list(args->data.list->args, str)) + if (!imap_write_list(IMAP_ARG_LIST(args)->args, str)) return FALSE; break; default: @@ -482,12 +482,14 @@ static int imap_parse_bodystructure_args(const ImapArg *args, String *str) { ImapArg *subargs; + ImapArgList *list; int i, multipart, text, message_rfc822; multipart = FALSE; while (args->type == IMAP_ARG_LIST) { str_append_c(str, '('); - if (!imap_parse_bodystructure_args(args->data.list->args, str)) + list = IMAP_ARG_LIST(args); + if (!imap_parse_bodystructure_args(list->args, str)) return FALSE; str_append_c(str, ')'); @@ -500,7 +502,7 @@ if (args->type != IMAP_ARG_STRING) return FALSE; - str_printfa(str, " \"%s\"", args->data.str); + str_printfa(str, " \"%s\"", IMAP_ARG_STR(args)); return TRUE; } @@ -508,24 +510,26 @@ if (args[0].type != IMAP_ARG_STRING || args[1].type != IMAP_ARG_STRING) return FALSE; - text = strcasecmp(args[0].data.str, "text") == 0; - message_rfc822 = strcasecmp(args[0].data.str, "message") == 0 && - strcasecmp(args[1].data.str, "rfc822") == 0; + text = strcasecmp(IMAP_ARG_STR(&args[0]), "text") == 0; + message_rfc822 = strcasecmp(IMAP_ARG_STR(&args[0]), "message") == 0 && + strcasecmp(IMAP_ARG_STR(&args[1]), "rfc822") == 0; - str_printfa(str, "\"%s\" \"%s\"", args[0].data.str, args[1].data.str); + str_printfa(str, "\"%s\" \"%s\"", IMAP_ARG_STR(&args[0]), + IMAP_ARG_STR(&args[1])); args += 2; /* ("content type param key" "value" ...) | NIL */ if (args->type == IMAP_ARG_LIST) { str_append(str, " ("); - subargs = args->data.list->args; + subargs = IMAP_ARG_LIST(args)->args; for (; subargs->type != IMAP_ARG_EOL; ) { if (subargs[0].type != IMAP_ARG_STRING || subargs[1].type != IMAP_ARG_STRING) return FALSE; str_printfa(str, "\"%s\" \"%s\"", - subargs[0].data.str, subargs[1].data.str); + IMAP_ARG_STR(&subargs[0]), + IMAP_ARG_STR(&subargs[1])); subargs += 2; if (subargs->type == IMAP_ARG_EOL) @@ -546,9 +550,9 @@ str_append(str, " NIL"); } else if (args->type == IMAP_ARG_ATOM) { str_append_c(str, ' '); - str_append(str, args->data.str); + str_append(str, IMAP_ARG_STR(args)); } else if (args->type == IMAP_ARG_STRING) { - str_printfa(str, " \"%s\"", args->data.str); + str_printfa(str, " \"%s\"", IMAP_ARG_STR(args)); } else { return FALSE; } @@ -560,7 +564,7 @@ return FALSE; str_append_c(str, ' '); - str_append(str, args->data.str); + str_append(str, IMAP_ARG_STR(args)); } else if (message_rfc822) { /* message/rfc822 - envelope + bodystructure + text lines */ if (args[0].type != IMAP_ARG_LIST || @@ -570,17 +574,18 @@ str_append_c(str, ' '); - if (!imap_write_list(args[0].data.list->args, str)) + list = IMAP_ARG_LIST(&args[0]); + if (!imap_write_list(list->args, str)) return FALSE; str_append_c(str, ' '); - if (!imap_parse_bodystructure_args(args[1].data.list->args, - str)) + list = IMAP_ARG_LIST(&args[1]); + if (!imap_parse_bodystructure_args(list->args, str)) return FALSE; str_append_c(str, ' '); - str_append(str, args[2].data.str); + str_append(str, IMAP_ARG_STR(&args[2])); } return TRUE;
--- a/src/lib-imap/imap-envelope.c Sun Dec 29 21:44:37 2002 +0200 +++ b/src/lib-imap/imap-envelope.c Thu Jan 02 10:09:26 2003 +0200 @@ -128,7 +128,7 @@ if (arg->type != IMAP_ARG_LIST) return FALSE; - list = arg->data.list; + list = IMAP_ARG_LIST(arg); /* we require 4 arguments, strings or NILs */ if (list->size < 4) @@ -137,8 +137,9 @@ for (i = 0; i < 4; i++) { if (list->args[i].type == IMAP_ARG_NIL) args[i] = NULL; - else if (list->args[i].type == IMAP_ARG_STRING) - args[i] = list->args[i].data.str; + else if (list->args[i].type == IMAP_ARG_STRING || + list->args[i].type == IMAP_ARG_ATOM) + args[i] = IMAP_ARG_STR(&list->args[i]); else return FALSE; } @@ -200,7 +201,7 @@ in_group = FALSE; str = t_str_new(128); - list = arg->data.list; + list = IMAP_ARG_LIST(arg); for (i = 0; i < list->size; i++) { if (!imap_address_arg_append(&list->args[i], str, &in_group)) return NULL; @@ -211,18 +212,25 @@ static const char *imap_envelope_parse_first_mailbox(ImapArg *arg) { + ImapArgList *list; + /* ((name route mailbox domain) ...) */ if (arg->type != IMAP_ARG_LIST) return NULL; - if (arg->data.list->size == 0) + list = IMAP_ARG_LIST(arg); + if (list->size == 0) return ""; - arg = arg->data.list->args; - if (arg->type != IMAP_ARG_LIST || arg->data.list->size != 4) + arg = IMAP_ARG_LIST(arg)->args; + if (arg->type != IMAP_ARG_LIST) return NULL; - return t_strdup(arg->data.list->args[2].data.str); + list = IMAP_ARG_LIST(arg); + if (list->size != 4) + return NULL; + + return t_strdup(imap_arg_string(&list->args[2])); } static const char * @@ -238,8 +246,8 @@ case IMAP_ENVELOPE_RESULT_STRING: if (field >= IMAP_ENVELOPE_FROM && field <= IMAP_ENVELOPE_BCC) value = imap_envelope_parse_address(arg); - else if (arg->type == IMAP_ARG_STRING || arg->type == IMAP_ARG_ATOM) - value = t_strdup(arg->data.str); + else + value = t_strdup(imap_arg_string(arg)); break; case IMAP_ENVELOPE_RESULT_FIRST_MAILBOX: i_assert(field >= IMAP_ENVELOPE_FROM &&
--- a/src/lib-imap/imap-parser.c Sun Dec 29 21:44:37 2002 +0200 +++ b/src/lib-imap/imap-parser.c Thu Jan 02 10:09:26 2003 +0200 @@ -57,7 +57,7 @@ if (parser->list_arg == NULL) parser->root_list = parser->cur_list; else - parser->list_arg->data.list = parser->cur_list; + parser->list_arg->_data.list = parser->cur_list; } ImapParser *imap_parser_create(IStream *input, OStream *output, @@ -156,7 +156,7 @@ imap_args_realloc(parser, LIST_ALLOC_SIZE); parser->list_arg->type = IMAP_ARG_LIST; - parser->list_arg->data.list = parser->cur_list; + parser->list_arg->_data.list = parser->cur_list; parser->cur_type = ARG_PARSE_NONE; } @@ -179,7 +179,7 @@ if (parser->list_arg == NULL) { parser->cur_list = parser->root_list; } else { - parser->cur_list = parser->list_arg->data.list; + parser->cur_list = parser->list_arg->_data.list; } parser->cur_type = ARG_PARSE_NONE; @@ -201,7 +201,7 @@ } else { /* simply save the string */ arg->type = IMAP_ARG_ATOM; - arg->data.str = p_strndup(parser->pool, data, lastpos); + arg->_data.str = p_strndup(parser->pool, data, lastpos); } break; case ARG_PARSE_STRING: @@ -209,13 +209,13 @@ i_assert(lastpos > 0); arg->type = IMAP_ARG_STRING; - arg->data.str = p_strndup(parser->pool, data+1, lastpos-1); + arg->_data.str = p_strndup(parser->pool, data+1, lastpos-1); /* remove the escapes */ if (parser->str_first_escape >= 0 && (parser->flags & IMAP_PARSE_FLAG_NO_UNESCAPE) == 0) { /* -1 because we skipped the '"' prefix */ - str_remove_escapes(arg->data.str + + str_remove_escapes(arg->_data.str + parser->str_first_escape-1); } break; @@ -223,11 +223,11 @@ if ((parser->flags & IMAP_PARSE_FLAG_LITERAL_SIZE) == 0) { /* simply save the string */ arg->type = IMAP_ARG_STRING; - arg->data.str = p_strndup(parser->pool, data, lastpos); + arg->_data.str = p_strndup(parser->pool, data, lastpos); } else { /* save literal size */ arg->type = IMAP_ARG_LITERAL_SIZE; - arg->data.literal_size = parser->literal_size; + arg->_data.literal_size = parser->literal_size; } break; default: @@ -596,9 +596,27 @@ case IMAP_ARG_ATOM: case IMAP_ARG_STRING: - return arg->data.str; + return arg->_data.str; default: return NULL; } } + +char *_imap_arg_str_error(const ImapArg *arg) +{ + i_panic("Tried to access ImapArg type %d as string", arg->type); + return NULL; +} + +uoff_t _imap_arg_literal_size_error(const ImapArg *arg) +{ + i_panic("Tried to access ImapArg type %d as literal size", arg->type); + return 0; +} + +ImapArgList *_imap_arg_list_error(const ImapArg *arg) +{ + i_panic("Tried to access ImapArg type %d as list", arg->type); + return NULL; +}
--- a/src/lib-imap/imap-parser.h Sun Dec 29 21:44:37 2002 +0200 +++ b/src/lib-imap/imap-parser.h Thu Jan 02 10:09:26 2003 +0200 @@ -33,9 +33,23 @@ char *str; uoff_t literal_size; ImapArgList *list; - } data; + } _data; }; +#define IMAP_ARG_STR(arg) \ + ((arg)->type == IMAP_ARG_NIL ? NULL : \ + (arg)->type == IMAP_ARG_ATOM || (arg)->type == IMAP_ARG_STRING ? \ + (arg)->_data.str : _imap_arg_str_error(arg)) + +#define IMAP_ARG_LITERAL_SIZE(arg) \ + ((arg)->type == IMAP_ARG_LITERAL_SIZE ? \ + (arg)->_data.literal_size : _imap_arg_literal_size_error(arg)) + +#define IMAP_ARG_LIST(arg) \ + ((arg)->type == IMAP_ARG_NIL ? NULL : \ + (arg)->type == IMAP_ARG_LIST ? \ + (arg)->_data.list : _imap_arg_list_error(arg)) + struct _ImapArgList { size_t size, alloc; ImapArg args[1]; /* variable size */ @@ -78,4 +92,9 @@ /* Returns the imap argument as string. NIL returns "" and list returns NULL. */ const char *imap_arg_string(ImapArg *arg); +/* Error functions */ +char *_imap_arg_str_error(const ImapArg *arg); +uoff_t _imap_arg_literal_size_error(const ImapArg *arg); +ImapArgList *_imap_arg_list_error(const ImapArg *arg); + #endif
--- a/src/lib-storage/mail-search.c Sun Dec 29 21:44:37 2002 +0200 +++ b/src/lib-storage/mail-search.c Thu Jan 02 10:09:26 2003 +0200 @@ -36,7 +36,13 @@ return FALSE; } - sarg->value.str = str_ucase((*args)->data.str); + if ((*args)->type != IMAP_ARG_ATOM && + (*args)->type != IMAP_ARG_STRING) { + data->error = "Invalid parameter for argument"; + return FALSE; + } + + sarg->value.str = str_ucase(IMAP_ARG_STR(*args)); *args += 1; /* second arg */ @@ -46,8 +52,14 @@ return FALSE; } + if ((*args)->type != IMAP_ARG_ATOM && + (*args)->type != IMAP_ARG_STRING) { + data->error = "Invalid parameter for argument"; + return FALSE; + } + sarg->hdr_field_name = sarg->value.str; - sarg->value.str = str_ucase((*args)->data.str); + sarg->value.str = str_ucase(IMAP_ARG_STR(*args)); *args += 1; } @@ -75,7 +87,7 @@ } if (arg->type == IMAP_ARG_LIST) { - ImapArg *listargs = arg->data.list->args; + ImapArg *listargs = IMAP_ARG_LIST(arg)->args; *next_sarg = search_arg_new(data->pool, SEARCH_SUB); subargs = &(*next_sarg)->value.subargs; @@ -93,7 +105,7 @@ arg->type == IMAP_ARG_STRING); /* string argument - get the name and jump to next */ - str = arg->data.str; + str = IMAP_ARG_STR(arg); *args += 1; str_ucase(str); @@ -145,7 +157,13 @@ data->error = "Missing parameter for HEADER"; return FALSE; } - key = str_ucase((*args)->data.str); + if ((*args)->type != IMAP_ARG_ATOM && + (*args)->type != IMAP_ARG_STRING) { + data->error = "Invalid parameter for HEADER"; + return FALSE; + } + + key = str_ucase(IMAP_ARG_STR(*args)); if (strcmp(key, "FROM") == 0) { *args += 1; @@ -221,7 +239,7 @@ break; if ((*args)->type != IMAP_ARG_ATOM || - strcasecmp((*args)->data.str, "OR") != 0) + strcasecmp(IMAP_ARG_STR(*args), "OR") != 0) break; *args += 1;