From 735c861de4d662f5bfe4fddff9fbfa8bc5a503c1 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Fri, 24 May 2019 23:52:37 +0200 Subject: [PATCH] libinterimap: astring is 1*ASTRING-CHAR / string. Not 1*ATOM-CHAR / string. Also accept LIST responses mailbox names containing '%', '*', or ']'. From RFC 3501: astring = 1*ASTRING-CHAR / string ASTRING-CHAR = ATOM-CHAR / resp-specials list = "LIST" SP mailbox SP list-mailbox list-mailbox = 1*list-char / string list-char = ATOM-CHAR / list-wildcards / resp-specials list-wildcards = "%" / "*" resp-specials = "]" --- Changelog | 3 +++ lib/Net/IMAP/InterIMAP.pm | 13 ++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Changelog b/Changelog index 9cce062..587dc9b 100644 --- a/Changelog +++ b/Changelog @@ -3,6 +3,9 @@ interimap (0.5) upstream; - libinterimap: bugfix: hierarchy delimiters in LIST responses were returned as an escaped quoted special, like "\\", not as a single character (backslash in this case). + - libinterimap: the parser choked on responses with non-quoted/literal + astring containing ']' characters. And LIST responses with + non-quoted/literal list-mailbox names '%', '*' or ']' characters. - libinterimap: quote() the empty string as "" instead of a 0-length literal. (This saves 3 bytes + one round-trip on servers not supporting non-synchronizing literals, and 4 bytes otherwise.) diff --git a/lib/Net/IMAP/InterIMAP.pm b/lib/Net/IMAP/InterIMAP.pm index 26c3712..86f08a9 100644 --- a/lib/Net/IMAP/InterIMAP.pm +++ b/lib/Net/IMAP/InterIMAP.pm @@ -40,9 +40,10 @@ BEGIN { } -# Regexes for RFC 3501's 'ATOM-CHAR', 'ASTRING-CHAR' and 'TEXT-CHAR'. +# Regexes for RFC 3501's 'ATOM-CHAR', 'ASTRING-CHAR', 'list-char' and 'TEXT-CHAR'. my $RE_ATOM_CHAR = qr/[\x21\x23\x24\x26\x27\x2B-\x5B\x5E-\x7A\x7C-\x7E]/; my $RE_ASTRING_CHAR = qr/[\x21\x23\x24\x26\x27\x2B-\x5B\x5D-\x7A\x7C-\x7E]/; +my $RE_LIST_CHAR = qr/[\x21\x23-\x27\x2A\x2B-\x5B\x5D-\x7A\x7C-\x7E]/; my $RE_TEXT_CHAR = qr/[\x01-\x09\x0B\x0C\x0E-\x7F]/; my $RE_SSL_PROTO = qr/(?:SSLv[23]|TLSv1|TLSv1\.[0-3])/; @@ -2192,7 +2193,13 @@ sub _nstring($$) { # Parse and consume an RFC 3501 astring (1*ASTRING-CHAR / string). sub _astring($$) { my ($self, $stream) = @_; - return $$stream =~ s/\A($RE_ATOM_CHAR+)// ? $1 : $self->_string($stream); + return $$stream =~ s/\A$RE_ASTRING_CHAR+//p ? ${^MATCH} : $self->_string($stream); +} + +# Parse and consume an RFC 3501 list-mailbox (1*list-char / string). +sub _list_mailbox($$) { + my ($self, $stream) = @_; + return $$stream =~ s/\A$RE_LIST_CHAR+//p ? ${^MATCH} : $self->_string($stream); } # Parse and consume an RFC 3501 string (quoted / literal). @@ -2364,7 +2371,7 @@ sub _resp($$;&$$) { elsif (s/\ALIST \((\\?$RE_ATOM_CHAR+(?: \\?$RE_ATOM_CHAR+)*)?\) ("(?:\\[\x22\x5C]|[\x01-\x09\x0B\x0C\x0E-\x21\x23-\x5B\x5D-\x7F])"|NIL) //) { my ($delim, $attrs) = ($2, $1); my @attrs = defined $attrs ? split(/ /, $attrs) : (); - my $mailbox = $self->_astring(\$_); + my $mailbox = $self->_list_mailbox(\$_); $self->panic($_) unless $_ eq ''; $mailbox = 'INBOX' if uc $mailbox eq 'INBOX'; # INBOX is case-insensitive undef $delim if uc $delim eq 'NIL'; -- 2.39.2