========================================================================
CVE-2020-STDIN -- Integer overflow in get_stdinput()
========================================================================

The following loop reads lines from stdin as long as the last character
of the lines is '\\' (line 1273). Each line that is read is appended to
a "growable string", the gstring g (at line 1266):

1229 gstring * g = NULL;
....
1233 for (i = 0;; i++)
1234   {
1235   uschar buffer[1024];
....
1252     if (Ufgets(buffer, sizeof(buffer), stdin) == NULL) break;
1253     p = buffer;
....
1258   ss = p + (int)Ustrlen(p);
....
1266   g = string_catn(g, p, ss - p);
....
1273   if (ss == p || g->s[g->ptr-1] != '\\')
1274     break;

Eventually, the integer g->size of the growable string overflows, and
becomes negative (in gstring_grow(), which is called by string_catn()).
Consequently, in store_newblock() (which is called by gstring_grow()),
newsize is negative:

506 void *
507 store_newblock_3(void * block, int newsize, int len,
508   const char * filename, int linenumber)
509 {
510 BOOL release_ok = store_last_get[store_pool] == block;
511 uschar * newtext = store_get(newsize);
512
513 memcpy(newtext, block, len);
514 if (release_ok) store_release_3(block, filename, linenumber);
515 return (void *)newtext;
516 }

- the store_get() at line 511 back-jumps the current block of memory
  (Digression 1b);

- the memcpy() at line 513 forward-overflows the current block of memory
  (Digression 1a).

(for ((i=0; i<4096; i++)); do echo "`date` $i" >&2; perl -e 'print "\\" x 1048576'; done) | /usr/sbin/exim4 -bt | wc
Program received signal SIGSEGV, Segmentation fault.

If exploitable, this vulnerability would allow an unprivileged local
attacker to obtain full root privileges. We have not tried to exploit
this vulnerability, because it took more than 5 days to overflow the
integer g->size. Indeed, the loop in get_stdinput() has an O(n^2) time
complexity: for each line that is read, store_newblock() allocates a new
block of memory (at line 511) and recopies the entire contents of the
growable string (at line 513).

