Geary.Imap.Deserialiser: Handle reserved chars in response-text
RFC 3501 allows any kind of char except CRLF in `resp-text` after an optional response code, so handle that. Addresses another issue in #711
This commit is contained in:
parent
16b7d6528d
commit
d6d36768f9
2 changed files with 42 additions and 6 deletions
|
|
@ -30,6 +30,10 @@ public class Geary.Imap.Deserializer : BaseObject, Logging.Source {
|
|||
|
||||
private const size_t MAX_BLOCK_READ_SIZE = 4096;
|
||||
|
||||
private const string[] RESPONSE_ATOMS = {
|
||||
"OK", "NO", "BAD", "BYE", "PREAUTH"
|
||||
};
|
||||
|
||||
private enum Mode {
|
||||
LINE,
|
||||
BLOCK,
|
||||
|
|
@ -49,6 +53,7 @@ public class Geary.Imap.Deserializer : BaseObject, Logging.Source {
|
|||
LITERAL,
|
||||
LITERAL_DATA_BEGIN,
|
||||
LITERAL_DATA,
|
||||
RESPONSE_TEXT,
|
||||
FAILED,
|
||||
CLOSED,
|
||||
COUNT
|
||||
|
|
@ -102,6 +107,7 @@ public class Geary.Imap.Deserializer : BaseObject, Logging.Source {
|
|||
private Geary.Memory.GrowableBuffer? block_buffer = null;
|
||||
private unowned uint8[]? current_buffer = null;
|
||||
private int ins_priority = Priority.DEFAULT;
|
||||
|
||||
private bool is_parsing_flags = false;
|
||||
|
||||
|
||||
|
|
@ -179,12 +185,12 @@ public class Geary.Imap.Deserializer : BaseObject, Logging.Source {
|
|||
new Geary.State.Mapping(State.START_PARAM, Event.ERROR, on_error),
|
||||
|
||||
new Geary.State.Mapping(State.ATOM, Event.CHAR, on_atom_char),
|
||||
new Geary.State.Mapping(State.ATOM, Event.EOL, on_atom_eol),
|
||||
new Geary.State.Mapping(State.ATOM, Event.EOL, on_param_eol),
|
||||
new Geary.State.Mapping(State.ATOM, Event.EOS, on_eos),
|
||||
new Geary.State.Mapping(State.ATOM, Event.ERROR, on_error),
|
||||
|
||||
new Geary.State.Mapping(State.FLAG, Event.CHAR, on_flag_char),
|
||||
new Geary.State.Mapping(State.FLAG, Event.EOL, on_atom_eol),
|
||||
new Geary.State.Mapping(State.FLAG, Event.EOL, on_param_eol),
|
||||
new Geary.State.Mapping(State.FLAG, Event.EOS, on_eos),
|
||||
new Geary.State.Mapping(State.FLAG, Event.ERROR, on_error),
|
||||
|
||||
|
|
@ -217,6 +223,11 @@ public class Geary.Imap.Deserializer : BaseObject, Logging.Source {
|
|||
new Geary.State.Mapping(State.LITERAL_DATA, Event.EOS, on_eos),
|
||||
new Geary.State.Mapping(State.LITERAL_DATA, Event.ERROR, on_error),
|
||||
|
||||
new Geary.State.Mapping(State.RESPONSE_TEXT, Event.CHAR, on_response_text_char),
|
||||
new Geary.State.Mapping(State.RESPONSE_TEXT, Event.EOL, on_param_eol),
|
||||
new Geary.State.Mapping(State.RESPONSE_TEXT, Event.EOS, on_eos),
|
||||
new Geary.State.Mapping(State.RESPONSE_TEXT, Event.ERROR, on_error),
|
||||
|
||||
new Geary.State.Mapping(State.FAILED, Event.EOL, on_failed_eol),
|
||||
new Geary.State.Mapping(State.FAILED, Event.EOS, Geary.State.nop),
|
||||
new Geary.State.Mapping(State.FAILED, Event.ERROR, Geary.State.nop),
|
||||
|
|
@ -590,7 +601,12 @@ public class Geary.Imap.Deserializer : BaseObject, Logging.Source {
|
|||
return State.START_PARAM;
|
||||
|
||||
default:
|
||||
if (!this.is_parsing_flags) {
|
||||
if (this.context_stack.size == 1 &&
|
||||
this.context.size >= 2 &&
|
||||
this.context.get(1).to_string().ascii_up() in RESPONSE_ATOMS) {
|
||||
append_to_string(ch);
|
||||
return State.RESPONSE_TEXT;
|
||||
} else if (!this.is_parsing_flags) {
|
||||
if (DataFormat.is_atom_special(ch)) {
|
||||
warning("Received an invalid atom-char: %c", ch);
|
||||
return State.FAILED;
|
||||
|
|
@ -697,7 +713,7 @@ public class Geary.Imap.Deserializer : BaseObject, Logging.Source {
|
|||
return State.TAG;
|
||||
}
|
||||
|
||||
private uint on_atom_eol(uint state, uint event, void *user) {
|
||||
private uint on_param_eol(uint state, uint event, void *user) {
|
||||
// clean up final atom
|
||||
save_string_parameter(false);
|
||||
flush_params();
|
||||
|
|
@ -837,6 +853,12 @@ public class Geary.Imap.Deserializer : BaseObject, Logging.Source {
|
|||
return State.START_PARAM;
|
||||
}
|
||||
|
||||
private uint on_response_text_char(uint state, uint event, void *user) {
|
||||
char ch = *((char *) user);
|
||||
append_to_string(ch);
|
||||
return State.RESPONSE_TEXT;
|
||||
}
|
||||
|
||||
private uint on_eos() {
|
||||
debug("EOS");
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ class Geary.Imap.DeserializerTest : TestCase {
|
|||
// fail, disable for the moment
|
||||
add_test("invalid_flag_prefix", invalid_flag_prefix);
|
||||
|
||||
add_test("reserved_in_response_text", reserved_in_response_text);
|
||||
|
||||
|
||||
add_test("instant_eos", instant_eos);
|
||||
add_test("bye_eos", bye_eos);
|
||||
}
|
||||
|
|
@ -220,14 +223,13 @@ class Geary.Imap.DeserializerTest : TestCase {
|
|||
|
||||
public void aliyun_greeting() throws Error {
|
||||
string greeting = "* OK AliYun IMAP Server Ready(10.147.40.164)";
|
||||
string parsed = "* OK AliYun IMAP Server Ready (10.147.40.164)";
|
||||
this.stream.add_data(greeting.data);
|
||||
this.stream.add_data(EOL.data);
|
||||
|
||||
this.process.begin(Expect.MESSAGE, this.async_completion);
|
||||
RootParameters? message = this.process.end(async_result());
|
||||
|
||||
assert(message.to_string() == parsed);
|
||||
assert(message.to_string() == greeting);
|
||||
}
|
||||
|
||||
public void invalid_atom_prefix() throws Error {
|
||||
|
|
@ -320,6 +322,18 @@ class Geary.Imap.DeserializerTest : TestCase {
|
|||
//this.process.end(async_result());
|
||||
}
|
||||
|
||||
public void reserved_in_response_text() throws Error {
|
||||
// As seen in #711
|
||||
string line = """a008 BAD Missing ] in: header.fields""";
|
||||
this.stream.add_data(line.data);
|
||||
this.stream.add_data(EOL.data);
|
||||
|
||||
this.process.begin(Expect.MESSAGE, this.async_completion);
|
||||
RootParameters? message = this.process.end(async_result());
|
||||
|
||||
assert(message.to_string() == line);
|
||||
}
|
||||
|
||||
public void instant_eos() throws Error {
|
||||
this.process.begin(Expect.EOS, this.async_completion);
|
||||
this.process.end(async_result());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue