Bug: dot-stuffing may not work under some circumstances.

Damian amavis at arcsin.de
Fri Oct 28 14:42:45 CEST 2016


Hello,

I recently hit on a bug where a "\r\n." in a mail triggered an "end of
DATA" at the upstream mail server.
>From the current (2.11) amavis source:

> #package Amavis::Out::SMTP;
> sub mail_via_smtp(@) {
>   ...
>           while (($nbytes = $msg->read($buff,3*16384)) > 0) {
>             $smtp_handle->datasend($buff);
>           }
> ...
> }
>
>
> #package Amavis::Out::SMTP::Protocol;
> sub datasend {
>   my $self = shift;
>   my $buff = @_ == 1 ? $_[0] : join('', at _);
>   ...
>   # CR/LF are never split across a buffer boundary
>   $buff =~ s{\n}{\015\012}gs;  # quite fast, but still a bottleneck
>   if ($self->{dotstuffing}) {
>     $buff =~ s{\015\012\.}{\015\012..}gs;  # dot stuffing
>     $self->{io}->print('.')  if substr($buff,0,1) eq '.' &&
>                              $self->{at_line_boundary};
>   }
>   $self->{io}->print($buff);
>   $self->{at_line_boundary} = $self->{io}->at_line_boundary;
>   ...
> }
>
>
> #package Amavis::IO::RW;
> sub print {
>   my $self = shift;
>   $self->{out} .= $_  for @_;
> # $self->out_buff_large ? $self->flush : 1;
>   length $self->{out} > 40000 ? $self->flush : 1;  # inlined
> out_buff_large()
> }
>
> sub at_line_boundary {
>   my $self = $_[0];
>   my $eol_str = $self->{eol_str};
>   my $eol_str_l = !defined($eol_str) ? 0 : length($eol_str);
>   !$eol_str_l ? 1
>     : substr($self->{out}, -$eol_str_l, $eol_str_l) eq $eol_str ? 1 : 0;
> }

Lets say we have a mail with a list of chunks read by mail_via_smtp()
and given to datasend():

- "40000+ chars with \r\n at the end\r\n"
-- No dot stuffing of trailing "\r\n", as there is no dot.
-- flushing of $self->{out} in Amavis::IO::RW::print().
-- Amavis::IO::RW::at_line_boundary() returns 0 in datasend(), as the
buffer is empty.

- ". some chars with dot at first position"
-- No dot stuffing via regex, as there is no leading "\r\n".
-- No dot stuffing via print('.'), as at_line_boundary is false from the
previous chunk.

I would kindly ask for a bugfix.

Thanks
 Damian


More information about the amavis-users mailing list