be more tolerant of formally malformed response codes

fastmail sends flags containing ']' in PERMANENTFLAGS, which is formally
illegal. however, if we parse the embedded list before looking for the
response code's closing ']', things work out fine.

as a side effect we won't complain about similarly or completely
malformed response codes we don't recognize at all, which may or may not
be considered an improvement ...
This commit is contained in:
Oswald Buddenhagen 2021-02-14 23:37:39 +01:00
parent 8c86f34bf0
commit 95a83c8220

View File

@ -1253,48 +1253,53 @@ parse_response_code( imap_store_t *ctx, imap_cmd_t *cmd, char *s )
if (!s || *s != '[') if (!s || *s != '[')
return RESP_OK; /* no response code */ return RESP_OK; /* no response code */
s++; s++;
if (!(p = strchr( s, ']' ))) { if (!(arg = next_arg( &s ))) {
bad_resp:
error( "IMAP error: malformed response code\n" ); error( "IMAP error: malformed response code\n" );
return RESP_CANCEL; return RESP_CANCEL;
} }
*p++ = 0;
if (!(arg = next_arg( &s )))
goto bad_resp;
if (!strcmp( "UIDVALIDITY", arg )) { if (!strcmp( "UIDVALIDITY", arg )) {
if (!(arg = next_arg( &s )) || if (!(arg = next_arg( &s )) ||
(ctx->uidvalidity = strtoul( arg, &earg, 10 ), *earg)) (ctx->uidvalidity = strtoul( arg, &earg, 10 ), *earg != ']'))
{ {
error( "IMAP error: malformed UIDVALIDITY status\n" ); error( "IMAP error: malformed UIDVALIDITY status\n" );
return RESP_CANCEL; return RESP_CANCEL;
} }
} else if (!strcmp( "UIDNEXT", arg )) { } else if (!strcmp( "UIDNEXT", arg )) {
if (!(arg = next_arg( &s )) || if (!(arg = next_arg( &s )) ||
(ctx->uidnext = strtoul( arg, &earg, 10 ), *earg)) (ctx->uidnext = strtoul( arg, &earg, 10 ), *earg != ']'))
{ {
error( "IMAP error: malformed UIDNEXT status\n" ); error( "IMAP error: malformed UIDNEXT status\n" );
return RESP_CANCEL; return RESP_CANCEL;
} }
} else if (!strcmp( "CAPABILITY", arg )) { } else if (!strcmp( "CAPABILITY", arg )) {
if (!(p = strchr( s, ']' ))) {
error( "IMAP error: malformed CAPABILITY status\n" );
return RESP_CANCEL;
}
*p = 0;
parse_capability( ctx, s ); parse_capability( ctx, s );
} else if (!strcmp( "ALERT", arg )) { } else if (!strcmp( "ALERT]", arg )) {
/* RFC2060 says that these messages MUST be displayed /* RFC2060 says that these messages MUST be displayed
* to the user * to the user
*/ */
for (; isspace( (uchar)*p ); p++); if (!s) {
error( "*** IMAP ALERT *** %s\n", p ); error( "IMAP error: malformed ALERT status\n" );
return RESP_CANCEL;
}
for (; isspace( (uchar)*s ); s++);
error( "*** IMAP ALERT *** %s\n", s );
} else if (cmd && !strcmp( "APPENDUID", arg )) { } else if (cmd && !strcmp( "APPENDUID", arg )) {
if (!(arg = next_arg( &s )) || if (!(arg = next_arg( &s )) ||
(ctx->uidvalidity = strtoul( arg, &earg, 10 ), *earg) || (ctx->uidvalidity = strtoul( arg, &earg, 10 ), *earg) ||
!(arg = next_arg( &s )) || !(arg = next_arg( &s )) ||
(((imap_cmd_out_uid_t *)cmd)->out_uid = strtoul( arg, &earg, 10 ), *earg)) (((imap_cmd_out_uid_t *)cmd)->out_uid = strtoul( arg, &earg, 10 ), *earg != ']'))
{ {
error( "IMAP error: malformed APPENDUID status\n" ); error( "IMAP error: malformed APPENDUID status\n" );
return RESP_CANCEL; return RESP_CANCEL;
} }
} else if (!strcmp( "PERMANENTFLAGS", arg )) { } else if (!strcmp( "PERMANENTFLAGS", arg )) {
parse_list_init( &ctx->parse_list_sts ); parse_list_init( &ctx->parse_list_sts );
if (parse_imap_list( NULL, &s, &ctx->parse_list_sts ) != LIST_OK) { if (parse_imap_list( NULL, &s, &ctx->parse_list_sts ) != LIST_OK || *s != ']') {
error( "IMAP error: malformed PERMANENTFLAGS status\n" ); error( "IMAP error: malformed PERMANENTFLAGS status\n" );
return RESP_CANCEL; return RESP_CANCEL;
} }