Grrr....  The previous patch I submitted *still* wasn't quite right; a 
malicious user could still send a mail which would result in an infinite 
loop, eating up CPU resources and slowing down the mail server.  *This* 
patched I've stared at, slept on, and stared at again, and I'm positive that 
it's bullet proof.

Sorry about all the patches for the same thing...


Also, I don't thing that:

        boundary=["']?(.*)["']?

Is quite right for the extracting the boundary string.  The greedy ".*" will 
eat up the possible quote at the end, and it will still match because the "?" 
means that a quote doesn't have to be there.  It needs to be made non-greedy, 
so that the quote won't end up inside the parens.  Like this:

        boundary=["']?(.*?)["']?

This is also in the attached diff file.

-- 
Visit http://dmoz.org, the world's   | Give a man a match, and he'll be warm
largest human edited web directory.  | for a minute, but set him on fire, and
                                     | he'll be warm for the rest of his life.
[EMAIL PROTECTED]  ICQ: 132152059 |
Index: lib/Mail/SpamAssassin/PerMsgStatus.pm
===================================================================
RCS file: /cvsroot/spamassassin/spamassassin/lib/Mail/SpamAssassin/PerMsgStatus.pm,v
retrieving revision 1.82
diff -u -3 -p -r1.82 PerMsgStatus.pm
--- lib/Mail/SpamAssassin/PerMsgStatus.pm	7 Mar 2002 10:51:22 -0000	1.82
+++ lib/Mail/SpamAssassin/PerMsgStatus.pm	10 Mar 2002 07:38:34 -0000
@@ -403,23 +414,30 @@ sub rewrite_as_spam {
       $rep =~ s/=/=3D/gs;               # quote the = chars
     }
 
-    if ($self->{msg}->get_header ('Content-Type') =~ /boundary=["']?(.*)["']?(;|$)/i) {
+    if ($self->{msg}->get_header ('Content-Type') =~ /boundary=["']?(.*?)["']?(;|$)/i) {
       # Deal with MIME "null block".  If this is a multipart MIME mail,
       # peel off the MIME header for the main part of the message,
       # stick in the report, then put the MIME header back in front,
       # so that the report is *after* the MIME header.
       my $boundary = "--" . quotemeta($1);
-      my @main_part;
-
-      if (grep(/^$boundary/i, @{$lines})) {
-        # If, for some reason, the boundry marker doesn't appear in the
-        # body of the text, don't bother with the following three lines,
-        # because otherwise @{$lines} will go down to zero size, so
-        # $lines->[0] will be undefined, and Perl (or at least some versions
-        # of it) will go into an infinite loop of throwing warnings.
-        push(@main_part, shift(@{$lines})) while ($lines->[0] !~ /^$boundary/i);
-        push(@main_part, shift(@{$lines})) while ($lines->[0] !~ /^$/);
-        push(@main_part, shift(@{$lines}));
+      my @main_part = ();
+      my $line_num = 0;
+      my $found = 0;
+
+      # This is paranoid checking to find the place were the first MIME
+      # block begins.  Otherwise a malicious user could trick us into
+      # doing something weird, or even going into an infinite loop.
+      while ($line_num < @{$lines}) {
+        last if $lines->[$line_num++] =~ /^$boundary/;
+      }
+      while ($line_num < @{$lines}) {
+        if ($lines->[$line_num++] =~ /^$/) {
+          $found = 1;
+          last;
+        }
+      }
+      if ($found) {
+        @main_part = splice(@{$lines}, 0, $line_num);
       }
 
       unshift (@{$lines}, split (/$/, $rep));

Reply via email to