imap: skip literals inside quoted strings

Fixes #20320
Closes #20322
This commit is contained in:
calm329
2026-01-14 09:12:20 -08:00
committed by Daniel Stenberg
parent 5fac56a8b3
commit de69e67793
2 changed files with 34 additions and 5 deletions

View File

@@ -236,6 +236,34 @@ static char *imap_atom(const char *str, bool escape_only)
return curlx_dyn_ptr(&line);
}
/*
* Finds the start of a literal '{size}' in line, skipping over quoted strings.
*/
static const char *imap_find_literal(const char *line, size_t len)
{
const char *end = line + len;
bool in_quote = FALSE;
while(line < end) {
if(in_quote) {
if(*line == '\\' && (line + 1) < end) {
line += 2;
continue;
}
if(*line == '"')
in_quote = FALSE;
}
else {
if(*line == '"')
in_quote = TRUE;
else if(*line == '{')
return line;
}
line++;
}
return NULL;
}
/***********************************************************************
*
* imap_matchresp()
@@ -1168,7 +1196,7 @@ static CURLcode imap_state_listsearch_resp(struct Curl_easy *data,
body data). Literal syntax is {size}\r\n */
const char *cr = memchr(line, '\r', len);
size_t line_len = cr ? (size_t)(cr - line) : len;
const char *ptr = memchr(line, '{', line_len);
const char *ptr = imap_find_literal(line, line_len);
if(ptr) {
curl_off_t size = 0;
bool parsed = FALSE;
@@ -1347,7 +1375,7 @@ static CURLcode imap_state_fetch_resp(struct Curl_easy *data,
/* Something like this is received "* 1 FETCH (BODY[TEXT] {2021}\r" so parse
the continuation data contained within the curly brackets */
ptr = memchr(ptr, '{', len);
ptr = imap_find_literal(ptr, len);
if(ptr) {
ptr++;
if(!curlx_str_number(&ptr, &size, CURL_OFF_T_MAX) &&

View File

@@ -15,7 +15,7 @@ CUSTOMREQUEST
%repeat[120 x Testing large IMAP literal with custom FETCH. XXXXXXXXXXXXX%0d]%
</data>
<datacheck>
* 456 FETCH (BODY[TEXT] {7201}%CR
* 456 FETCH (("fake {50}" BODY[TEXT]) {7201}%CR
%repeat[120 x Testing large IMAP literal with custom FETCH. XXXXXXXXXXXXX%0d]%
</datacheck>
</reply>
@@ -28,8 +28,9 @@ imap
<name>
IMAP custom FETCH with larger literal response (~7KB)
</name>
# The quoted string contains {50} which must not be parsed as a literal
<command>
imap://%HOSTIP:%IMAPPORT/%TESTNUMBER/ -u user:secret -X 'FETCH 456 BODY[TEXT]'
imap://%HOSTIP:%IMAPPORT/%TESTNUMBER/ -u user:secret -X 'FETCH 456 ("fake {50}" BODY[TEXT])'
</command>
</client>
@@ -39,7 +40,7 @@ IMAP custom FETCH with larger literal response (~7KB)
A001 CAPABILITY
A002 LOGIN user secret
A003 SELECT %TESTNUMBER
A004 FETCH 456 BODY[TEXT]
A004 FETCH 456 ("fake {50}" BODY[TEXT])
A005 LOGOUT
</protocol>
</verify>