struct imap_parser *parser)
{
const char *msg;
- bool fatal;
+ enum imap_parser_error parse_error;
- msg = imap_parser_get_error(parser, &fatal);
- if (fatal) {
+ msg = imap_parser_get_error(parser, &parse_error);
+ switch (parse_error) {
+ case IMAP_PARSE_ERROR_NONE:
+ i_unreached();
+ case IMAP_PARSE_ERROR_LITERAL_TOO_BIG:
client_send_reply(&client->common,
IMAP_CMD_REPLY_BYE, msg);
client_destroy(&client->common,
t_strconcat("Disconnected: ", msg, NULL));
return FALSE;
+ default:
+ break;
}
client_send_reply(&client->common, IMAP_CMD_REPLY_BAD, msg);
struct cmd_append_context *ctx = cmd->context;
const struct imap_arg *args;
const char *msg;
- bool fatal, nonsync = FALSE;
+ enum imap_parser_error parse_error;
+ bool nonsync = FALSE;
int ret;
if (cmd->cancel) {
IMAP_PARSE_FLAG_INSIDE_LIST, &args);
} while (ret > 0 && !catenate_args_can_stop(ctx, args));
if (ret == -1) {
- msg = imap_parser_get_error(ctx->save_parser, &fatal);
- if (fatal)
+ msg = imap_parser_get_error(ctx->save_parser, &parse_error);
+ switch (parse_error) {
+ case IMAP_PARSE_ERROR_NONE:
+ i_unreached();
+ case IMAP_PARSE_ERROR_LITERAL_TOO_BIG:
client_disconnect_with_error(client, msg);
- else if (!ctx->failed)
- client_send_command_error(cmd, msg);
+ break;
+ default:
+ if (!ctx->failed)
+ client_send_command_error(cmd, msg);
+ }
client->input_skip_line = TRUE;
cmd_append_finish(ctx);
return TRUE;
struct cmd_append_context *ctx = cmd->context;
const struct imap_arg *args;
const char *msg;
+ enum imap_parser_error parse_error;
unsigned int arg_min_count;
- bool fatal, nonsync, last_literal;
+ bool nonsync, last_literal;
int ret;
/* this function gets called 1) after parsing APPEND <mailbox> and
!cmd_append_args_can_stop(ctx, args, &last_literal));
if (ret == -1) {
if (!ctx->failed) {
- msg = imap_parser_get_error(ctx->save_parser, &fatal);
- if (fatal)
+ msg = imap_parser_get_error(ctx->save_parser, &parse_error);
+ switch (parse_error) {
+ case IMAP_PARSE_ERROR_NONE:
+ i_unreached();
+ case IMAP_PARSE_ERROR_LITERAL_TOO_BIG:
client_disconnect_with_error(client, msg);
- else
+ break;
+ default:
client_send_command_error(cmd, msg);
+ }
}
cmd_append_finish(ctx);
return TRUE;
{
const struct imap_arg *args;
const char *name, *error;
+ enum imap_parser_error parse_error;
int ret;
- bool fatal;
/* parse the entry name */
ret = imap_parser_read_args(ctx->parser, 1,
if (ret < 0) {
if (ret == -2)
return 0;
- error = imap_parser_get_error(ctx->parser, &fatal);
- if (fatal) {
+ error = imap_parser_get_error(ctx->parser, &parse_error);
+ switch (parse_error) {
+ case IMAP_PARSE_ERROR_NONE:
+ i_unreached();
+ case IMAP_PARSE_ERROR_LITERAL_TOO_BIG:
client_disconnect_with_error(ctx->cmd->client, error);
- return -1;
+ break;
+ default:
+ client_send_command_error(ctx->cmd, error);
+ break;
}
- client_send_command_error(ctx->cmd, error);
return -1;
}
if (args[1].type == IMAP_ARG_EOL) {
{
struct client *client = cmd->client;
const char *error, *cmd_name;
- bool fatal;
+ enum imap_parser_error parse_error;
if (msg == NULL) {
- msg = imap_parser_get_error(cmd->parser, &fatal);
- if (fatal) {
+ msg = imap_parser_get_error(cmd->parser, &parse_error);
+ switch (parse_error) {
+ case IMAP_PARSE_ERROR_NONE:
+ i_unreached();
+ case IMAP_PARSE_ERROR_LITERAL_TOO_BIG:
client_disconnect_with_error(client, msg);
return;
+ default:
+ break;
}
}
int str_first_escape; /* ARG_PARSE_STRING: index to first '\' */
uoff_t literal_size; /* ARG_PARSE_LITERAL: string size */
+ enum imap_parser_error error;
const char *error_msg;
unsigned int literal_skip_crlf:1;
parser->str_first_escape = 0;
parser->literal_size = 0;
+ parser->error = IMAP_PARSE_ERROR_NONE;
parser->error_msg = NULL;
parser->literal_skip_crlf = FALSE;
parser->output = output;
}
-const char *imap_parser_get_error(struct imap_parser *parser, bool *fatal)
+const char *imap_parser_get_error(struct imap_parser *parser,
+ enum imap_parser_error *error_r)
{
- if (fatal != NULL)
- *fatal = parser->fatal_error;
+ if (error_r != NULL)
+ *error_r = parser->error;
return parser->error_msg;
}
return TRUE;
}
parser->error_msg = "Unexpected ')'";
+ parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX;
return FALSE;
}
if ((parser->flags & IMAP_PARSE_FLAG_ATOM_ALLCHARS) != 0)
return TRUE;
+ parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX;
parser->error_msg = error_msg;
return FALSE;
}
break;
} else if ((parser->flags &
IMAP_PARSE_FLAG_ATOM_ALLCHARS) == 0) {
+ parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX;
parser->error_msg = "Unexpected ')'";
return FALSE;
}
a linebreak.. */
if (is_linebreak(data[i]) &&
(parser->flags & IMAP_PARSE_FLAG_MULTILINE_STR) == 0) {
+ parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX;
parser->error_msg = "Missing '\"'";
return FALSE;
}
parser->literal_size >
parser->max_line_size - parser->line_size) {
/* too long string, abort. */
+ parser->error = IMAP_PARSE_ERROR_LITERAL_TOO_BIG;
parser->error_msg = "Literal size too large";
- parser->fatal_error = TRUE;
return FALSE;
}
}
if (parser->literal_nonsync) {
+ parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX;
parser->error_msg = "Expecting '}' after '+'";
return FALSE;
}
}
if (data[i] < '0' || data[i] > '9') {
+ parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX;
parser->error_msg = "Invalid literal size";
return FALSE;
}
if (parser->literal_size < prev_size) {
/* wrapped around, abort. */
+ parser->error = IMAP_PARSE_ERROR_LITERAL_TOO_BIG;
parser->error_msg = "Literal size too large";
return FALSE;
}
}
if (*data != '\n') {
+ parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX;
parser->error_msg = "Missing LF after literal size";
return FALSE;
}
return FALSE;
}
if (data[1] != '\n') {
+ parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX;
parser->error_msg = "CR sent without LF";
return FALSE;
}
case '\n':
/* unexpected end of line */
if ((parser->flags & IMAP_PARSE_FLAG_INSIDE_LIST) != 0) {
+ parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX;
parser->error_msg = "Missing ')'";
return FALSE;
}
break;
}
if ((parser->flags & IMAP_PARSE_FLAG_LITERAL8) == 0) {
+ parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX;
parser->error_msg = "literal8 not allowed here";
return FALSE;
}
if (parser->cur_pos == data_size)
return FALSE;
if (data[parser->cur_pos] != '{') {
+ parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX;
parser->error_msg = "Expected '{'";
return FALSE;
}
if (parser->list_arg != NULL && !parser->literal_size_return &&
(parser->flags & IMAP_PARSE_FLAG_STOP_AT_LIST) == 0) {
+ parser->error = IMAP_PARSE_ERROR_BAD_SYNTAX;
parser->error_msg = "Missing ')'";
*args_r = NULL;
return -1;
break;
if (parser->line_size > parser->max_line_size) {
+ parser->error = IMAP_PARSE_ERROR_LINE_TOO_LONG;
parser->error_msg = "IMAP command line too large";
break;
}
}
- if (parser->error_msg != NULL) {
+ if (parser->error != IMAP_PARSE_ERROR_NONE) {
/* error, abort */
parser->line_size += parser->cur_pos;
i_stream_skip(parser->input, parser->cur_pos);
IMAP_PARSE_FLAG_STOP_AT_LIST = 0x100
};
+enum imap_parser_error {
+ /* not fatal */
+ IMAP_PARSE_ERROR_NONE = 0,
+ IMAP_PARSE_ERROR_BAD_SYNTAX,
+ IMAP_PARSE_ERROR_LINE_TOO_LONG,
+ /* fatal */
+ IMAP_PARSE_ERROR_LITERAL_TOO_BIG
+};
+
struct imap_parser;
/* Create new IMAP argument parser. output is used for sending command
/* Return the last error in parser. fatal is set to TRUE if there's no way to
continue parsing, currently only if too large non-sync literal size was
given. */
-const char *imap_parser_get_error(struct imap_parser *parser, bool *fatal)
- ATTR_NULL(2);
+const char *imap_parser_get_error(struct imap_parser *parser,
+ enum imap_parser_error *error_r) ATTR_NULL(2);
/* Read a number of arguments. This function doesn't call i_stream_read(), you
need to do that. Returns number of arguments read (may be less than count
struct imap_parser *parser;
const struct imap_arg *args;
unsigned int i;
- bool fatal;
+ enum imap_parser_error parse_error;
test_begin("imap parser crlf handling");
input = test_istream_create(test_input);
test_istream_set_size(input, ++i);
(void)i_stream_read(input);
test_assert(imap_parser_read_args(parser, 0, 0, &args) == -1);
- test_assert(strcmp(imap_parser_get_error(parser, &fatal), "CR sent without LF") == 0 && !fatal);
+ test_assert(strcmp(imap_parser_get_error
+ (parser, &parse_error), "CR sent without LF") == 0 &&
+ parse_error == IMAP_PARSE_ERROR_BAD_SYNTAX);
imap_parser_unref(&parser);
i_stream_destroy(&input);