]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-imap: imap-parser - Parse literal size using as same algorithm as str_parse*().
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 4 Jun 2021 09:46:53 +0000 (12:46 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Fri, 4 Jun 2021 11:29:35 +0000 (11:29 +0000)
This prevents wrapping the integer value and fixes an ubsan complaint.

Based on Stephan's similar patch in managesieve-parser.

src/lib-imap/imap-parser.c

index 20cee08c2905eeee0bbda973fc4c06458e1cc3f7..2deb75f5fba4943f6f22aac3746fdf89706b6e2a 100644 (file)
@@ -438,7 +438,7 @@ static bool imap_parser_read_literal(struct imap_parser *parser,
                                     const unsigned char *data,
                                     size_t data_size)
 {
-       size_t i, prev_size;
+       size_t i;
 
        /* expecting digits + "}" */
        for (i = parser->cur_pos; i < data_size; i++) {
@@ -465,15 +465,16 @@ static bool imap_parser_read_literal(struct imap_parser *parser,
                        return FALSE;
                }
 
-               prev_size = parser->literal_size;
-               parser->literal_size = parser->literal_size*10 + (data[i]-'0');
-
-               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 (parser->literal_size >= ((uoff_t)-1 / 10)) {
+                       if (parser->literal_size > ((uoff_t)-1 / 10) ||
+                           (uoff_t)(data[i] - '0') > ((uoff_t)-1 % 10)) {
+                               parser->error = IMAP_PARSE_ERROR_LITERAL_TOO_BIG;
+                               parser->error_msg = "Literal size too large";
+                               return FALSE;
+                       }
                }
+               parser->literal_size = parser->literal_size * 10 +
+                       (data[i] - '0');
        }
 
        parser->cur_pos = i;