head 1.7; access; symbols OPENPKG_2_STABLE_MP:1.7 OPENPKG_E1_MP_HEAD:1.6 OPENPKG_E1_MP:1.6 OPENPKG_E1_MP_2_STABLE:1.3 OPENPKG_E1_FP:1.3 OPENPKG_2_STABLE_20061018:1.3 OPENPKG_2_STABLE:1.3.0.4 OPENPKG_2_STABLE_BP:1.3 OPENPKG_2_5_SOLID:1.3.0.2 OPENPKG_2_5_SOLID_BP:1.3 OPENPKG_2_4_RELEASE:1.1 OPENPKG_2_4_SOLID:1.1.0.8 OPENPKG_2_4_SOLID_BP:1.1 OPENPKG_2_3_RELEASE:1.1 OPENPKG_2_3_SOLID:1.1.0.6 OPENPKG_2_3_SOLID_BP:1.1 OPENPKG_2_2_RELEASE:1.1 OPENPKG_2_2_SOLID:1.1.0.4 OPENPKG_2_2_SOLID_BP:1.1 OPENPKG_2_0_SOLID:1.1.0.2; locks; strict; comment @# @; 1.7 date 2007.02.14.05.56.26; author cs; state dead; branches; next 1.6; commitid aYeqVE1dRcCxaq6s; 1.6 date 2006.11.08.08.42.39; author rse; state Exp; branches; next 1.5; commitid 7CnkszjZ2Q2SeQTr; 1.5 date 2006.10.06.05.39.35; author rse; state dead; branches; next 1.4; commitid Jqb7xhgLh6tPhAPr; 1.4 date 2006.10.02.06.19.33; author rse; state Exp; branches; next 1.3; commitid WzjBS18y30SvD4Pr; 1.3 date 2005.09.16.14.12.50; author mk; state dead; branches 1.3.4.1; next 1.2; 1.2 date 2005.07.26.09.11.36; author rse; state Exp; branches; next 1.1; 1.1 date 2004.09.15.12.48.45; author rse; state dead; branches 1.1.2.1 1.1.6.1 1.1.8.1; next ; 1.3.4.1 date 2006.12.22.19.13.36; author thl; state Exp; branches; next 1.3.4.2; commitid 2LefOfqsS8nsjyZr; 1.3.4.2 date 2007.02.19.20.13.52; author rse; state dead; branches; next ; commitid sktZvDHxWRbJK87s; 1.1.2.1 date 2004.09.15.12.48.45; author rse; state Exp; branches; next ; 1.1.6.1 date 2005.07.28.11.00.52; author rse; state Exp; branches; next ; 1.1.8.1 date 2005.07.28.10.56.08; author rse; state Exp; branches; next ; desc @@ 1.7 log @upgrading package: spamassassin 3.1.7 -> 3.1.8 @ text @vendor bugfix: spamd died unexpectedly http://issues.apache.org/SpamAssassin/show_bug.cgi?id=4594 Index: lib/Mail/SpamAssassin/SpamdForkScaling.pm --- lib/Mail/SpamAssassin/SpamdForkScaling.pm.orig 2006-10-04 16:01:16 +0200 +++ lib/Mail/SpamAssassin/SpamdForkScaling.pm 2006-11-08 09:38:44 +0100 @@@@ -426,7 +426,13 @@@@ dbg("prefork: ordered $kid to accept"); # now wait for it to say it's done that - return $self->wait_for_child_to_accept($sock); + my $ret = $self->wait_for_child_to_accept($kid, $sock); + if ($ret) { + return $ret; + } else { + # retry with another child + return $self->order_idle_child_to_accept(); + } } else { @@@@ -436,7 +442,7 @@@@ } sub wait_for_child_to_accept { - my ($self, $sock) = @@_; + my ($self, $kid, $sock) = @@_; while (1) { my $state = $self->read_one_message_from_child_socket($sock); @@@@ -447,7 +453,12 @@@@ return undef; } else { - die "prefork: ordered child to accept, but child reported state '$state'"; + warn "prefork: ordered child $kid to accept, but they reported state '$state', killing rogue"; + $self->child_error_kill($kid, $sock); + $self->adapt_num_children(); + sleep 1; + + return undef; } } } @ 1.6 log @apply a vendor bugfix: spamd died unexpectedly @ text @@ 1.5 log @upgrading package: spamassassin 3.1.5 -> 3.1.6 @ text @d1 2 a2 1 http://issues.apache.org/SpamAssassin/show_bug.cgi?id=5101 d4 5 a8 5 Index: lib/Mail/SpamAssassin/ArchiveIterator.pm --- lib/Mail/SpamAssassin/ArchiveIterator.pm.orig 2006-08-29 17:16:47 +0200 +++ lib/Mail/SpamAssassin/ArchiveIterator.pm 2006-10-02 08:16:59 +0200 @@@@ -1141,7 +1141,7 @@@@ } d10 9 a18 3 $self->bump_scan_progress(); - $info->{"$file.$offset"} = Mail::SpamAssassin::Util::receive_date($header); + $info->{$offset} = Mail::SpamAssassin::Util::receive_date($header); d20 4 a23 6 # go onto the next message seek(INPUT, $offset + $size, 0); Index: lib/Mail/SpamAssassin/Constants.pm --- lib/Mail/SpamAssassin/Constants.pm.orig 2006-08-29 17:16:47 +0200 +++ lib/Mail/SpamAssassin/Constants.pm 2006-10-02 08:16:59 +0200 @@@@ -265,7 +265,7 @@@@ d25 20 a44 7 # regular expression that matches message separators in The University of # Washington's MBX mailbox format -use constant MBX_SEPARATOR => qr/([\s|\d]\d-[a-zA-Z]{3}-\d{4}\s\d{2}:\d{2}:\d{2}.*),(\d+);([\da-f]{12})-(\w{8})/; +use constant MBX_SEPARATOR => qr/^([\s|\d]\d-[a-zA-Z]{3}-\d{4}\s\d{2}:\d{2}:\d{2}.*),(\d+);([\da-f]{12})-(\w{8})\r?$/; # $1 = datestamp (str) # $2 = size of message in bytes (int) # $3 = message status - binary (hex) @ 1.4 log @apply a vendor fix @ text @@ 1.3 log @remove patch from CVS @ text @d1 26 a26 24 Index: sa-learn.raw --- sa-learn.raw.orig 2005-03-19 01:06:29 +0100 +++ sa-learn.raw 2005-07-26 11:01:39 +0200 @@@@ -660,7 +660,7 @@@@ Read user score preferences from I (usually C<$HOME/.spamassassin/user_prefs>). - =item B<-D>, B<--debug-level> +=item B<-D>, B<--debug-level> Produce diagnostic output. Index: spamc/spamc.c --- spamc/spamc.c.orig 2004-08-27 18:37:42 +0200 +++ spamc/spamc.c 2005-07-26 11:01:39 +0200 @@@@ -469,7 +469,7 @@@@ #endif #ifndef _WIN32 - openlog("spamc", LOG_CONS | LOG_PID, LOG_MAIL); + openlog("spamc", LOG_CONS | LOG_PID, LOG_USER); signal(SIGPIPE, SIG_IGN); #endif @ 1.3.4.1 log @MFC: make up leeway for 2_STABLE by virtue of build-time results @ text @d1 24 a24 44 vendor bugfix: spamd died unexpectedly http://issues.apache.org/SpamAssassin/show_bug.cgi?id=4594 Index: lib/Mail/SpamAssassin/SpamdForkScaling.pm --- lib/Mail/SpamAssassin/SpamdForkScaling.pm.orig 2006-10-04 16:01:16 +0200 +++ lib/Mail/SpamAssassin/SpamdForkScaling.pm 2006-11-08 09:38:44 +0100 @@@@ -426,7 +426,13 @@@@ dbg("prefork: ordered $kid to accept"); # now wait for it to say it's done that - return $self->wait_for_child_to_accept($sock); + my $ret = $self->wait_for_child_to_accept($kid, $sock); + if ($ret) { + return $ret; + } else { + # retry with another child + return $self->order_idle_child_to_accept(); + } } else { @@@@ -436,7 +442,7 @@@@ } sub wait_for_child_to_accept { - my ($self, $sock) = @@_; + my ($self, $kid, $sock) = @@_; while (1) { my $state = $self->read_one_message_from_child_socket($sock); @@@@ -447,7 +453,12 @@@@ return undef; } else { - die "prefork: ordered child to accept, but child reported state '$state'"; + warn "prefork: ordered child $kid to accept, but they reported state '$state', killing rogue"; + $self->child_error_kill($kid, $sock); + $self->adapt_num_children(); + sleep 1; + + return undef; } } } @ 1.3.4.2 log @MFC: security fixed version @ text @@ 1.2 log @cleanup packaging @ text @@ 1.1 log @file spamassassin.patch was initially added on branch OPENPKG_2_0_SOLID. @ text @d1 24 @ 1.1.6.1 log @Security Fixes (CAN-2005-1266) @ text @a0 161 Security Fixes (CAN-2005-1266) Index: lib/Mail/SpamAssassin/Message.pm --- lib/Mail/SpamAssassin/Message.pm.orig 2005-04-26 22:42:18 +0200 +++ lib/Mail/SpamAssassin/Message.pm 2005-06-06 03:31:23 +0200 @@@@ -122,7 +122,6 @@@@ # Go through all the headers of the message my $header = ''; - my $boundary; while ( my $last = shift @@message ) { if ( $last =~ /^From\s/ ) { # mbox formated mailbox @@@@ -157,72 +156,63 @@@@ } # Store the non-modified headers in a scalar - $self->{'pristine_headers'} .= $last; + unless ($self->{'missing_head_body_separator'}) { + $self->{'pristine_headers'} .= $last; + } # NB: Really need to figure out special folding rules here! if ( $last =~ /^[ \t]+/ ) { # if its a continuation if ($header) { $header .= $last; # fold continuations - - # If we're currently dealing with a content-type header, and there's a - # boundary defined, use it. Since there could be multiple - # content-type headers in a message, the last one will be the one we - # should use, so just keep updating as they come in. - if ($header =~ /^content-type:\s*(\S.*)$/is) { - my($type,$temp_boundary) = Mail::SpamAssassin::Util::parse_content_type($1); - $boundary = $temp_boundary if ($type =~ /^multipart/ && defined $temp_boundary); - } - - # Go onto the next header line, unless the next line is a - # multipart mime boundary, where we know we're going to stop - # below, so drop through for final header processing. - next unless (defined $boundary && $message[0] =~ /^--\Q$boundary\E(?:--|\s*$)/); - } - else { - # There was no previous header and this is just "out there"? - # Ignore it! - next; } } + else { + # Ok, there's a header here, let's go ahead and add it in. + if ($header) { + # Yes, the /s is needed to match \n too. + my ($key, $value) = split (/:\s*(?=.)/s, $header, 2); - # Ok, there's a header here, let's go ahead and add it in. - if ($header) { - # Yes, the /s is needed to match \n too. - my ($key, $value) = split (/:\s*(?=.)/s, $header, 2); + # If it's not a valid header (aka: not in the form "foo: bar"), skip it. + if (defined $value) { + # limit the length of the pairs we store + if (length($key) > MAX_HEADER_KEY_LENGTH) { + $key = substr($key, 0, MAX_HEADER_KEY_LENGTH); + $self->{'truncated_header'} = 1; + } + if (length($value) > MAX_HEADER_VALUE_LENGTH) { + $value = substr($value, 0, MAX_HEADER_VALUE_LENGTH); + $self->{'truncated_header'} = 1; + } + $self->header($key, $value); + } + } - # If it's not a valid header (aka: not in the form "foo: bar"), skip it. - if (defined $value) { - # limit the length of the pairs we store - if (length($key) > MAX_HEADER_KEY_LENGTH) { - $key = substr($key, 0, MAX_HEADER_KEY_LENGTH); - $self->{'truncated_header'} = 1; - } - if (length($value) > MAX_HEADER_VALUE_LENGTH) { - $value = substr($value, 0, MAX_HEADER_VALUE_LENGTH); - $self->{'truncated_header'} = 1; - } - $self->header($key, $value); + # not a continuation... + $header = $last; + } - # If we're currently dealing with a content-type header, and there's a - # boundary defined, use it. Since there could be multiple - # content-type headers in a message, the last one will be the one we - # should use, so just keep updating as they come in. - if (lc $key eq 'content-type') { - my($type,$temp_boundary) = Mail::SpamAssassin::Util::parse_content_type($value); - $boundary = $temp_boundary if ($type =~ /^multipart/ && defined $temp_boundary); - } + if ($header) { + if ($header =~ /^\r?$/) { + last; + } + else { + # Check for missing head/body separator + # RFC 2822, s2.2: + # A field name MUST be composed of printable US-ASCII characters + # (i.e., characters that have values between 33 (041) and 126 (176), inclusive), + # except colon (072). + # FOR THIS NEXT PART: list off the valid REs for what can be next: + # Header, header continuation, blank line + if (!@@message || $message[0] !~ /^(?:[\041-\071\073-\176]+:|[ \t]|\r?$)/ || $message[0] =~ /^--/) { + # No body or no separator before mime boundary is invalid + $self->{'missing_head_body_separator'} = 1; + + # we *have* to go back through again to make sure we catch the last + # header, so fake a separator and loop again. + unshift(@@message, "\n"); + } } } - - # not a continuation... - $header = $last; - - # Ok, we found the header/body blank line ... - last if ($last =~ /^\r?$/m); - - # Alternately, if a multipart mime boundary is found in the header area, - # aka it's malformed, exit out as well and treat it as part of the body. - last if (defined $boundary && $message[0] =~ /^--\Q$boundary\E(?:--|\s*$)/); } # Store the pristine body for later -- store as a copy since @@message @@@@ -586,8 +576,9 @@@@ dbg("parsing normal part"); - $part_msg->{'type'} = - Mail::SpamAssassin::Util::parse_content_type($part_msg->header('content-type')); + # 0: content-type, 1: boundary, 2: charset, 3: filename + my @@ct = Mail::SpamAssassin::Util::parse_content_type($part_msg->header('content-type')); + $part_msg->{'type'} = $ct[0]; # multipart sections are required to have a boundary set ... If this # one doesn't, assume it's malformed and revert to text/plain @@@@ -595,11 +586,15 @@@@ # attempt to figure out a name for this attachment if there is one ... my $disp = $part_msg->header('content-disposition') || ''; - my($filename) = $disp =~ /name="?([^\";]+)"?/i || $part_msg->{'type'} =~ /name="?([^\";]+)"?/i; + if ($disp =~ /name="?([^\";]+)"?/i) { + $part_msg->{'name'} = $1; + } + elsif ($ct[3]) { + $part_msg->{'name'} = $ct[3]; + } $part_msg->{'raw'} = $body; $part_msg->{'boundary'} = $boundary; - $part_msg->{'name'} = $filename if $filename; # If this part is a message/* part, and the parent isn't also a # message/* part (ie: the main part) go ahead and parse into a tree. @ 1.1.8.1 log @Security Fixes (CAN-2005-1266) @ text @a0 161 Security Fixes (CAN-2005-1266) Index: lib/Mail/SpamAssassin/Message.pm --- lib/Mail/SpamAssassin/Message.pm.orig 2005-04-26 22:42:18 +0200 +++ lib/Mail/SpamAssassin/Message.pm 2005-06-06 03:31:23 +0200 @@@@ -122,7 +122,6 @@@@ # Go through all the headers of the message my $header = ''; - my $boundary; while ( my $last = shift @@message ) { if ( $last =~ /^From\s/ ) { # mbox formated mailbox @@@@ -157,72 +156,63 @@@@ } # Store the non-modified headers in a scalar - $self->{'pristine_headers'} .= $last; + unless ($self->{'missing_head_body_separator'}) { + $self->{'pristine_headers'} .= $last; + } # NB: Really need to figure out special folding rules here! if ( $last =~ /^[ \t]+/ ) { # if its a continuation if ($header) { $header .= $last; # fold continuations - - # If we're currently dealing with a content-type header, and there's a - # boundary defined, use it. Since there could be multiple - # content-type headers in a message, the last one will be the one we - # should use, so just keep updating as they come in. - if ($header =~ /^content-type:\s*(\S.*)$/is) { - my($type,$temp_boundary) = Mail::SpamAssassin::Util::parse_content_type($1); - $boundary = $temp_boundary if ($type =~ /^multipart/ && defined $temp_boundary); - } - - # Go onto the next header line, unless the next line is a - # multipart mime boundary, where we know we're going to stop - # below, so drop through for final header processing. - next unless (defined $boundary && @@message && $message[0] =~ /^--\Q$boundary\E(?:--|\s*$)/); - } - else { - # There was no previous header and this is just "out there"? - # Ignore it! - next; } } + else { + # Ok, there's a header here, let's go ahead and add it in. + if ($header) { + # Yes, the /s is needed to match \n too. + my ($key, $value) = split (/:\s*(?=.)/s, $header, 2); - # Ok, there's a header here, let's go ahead and add it in. - if ($header) { - # Yes, the /s is needed to match \n too. - my ($key, $value) = split (/:\s*(?=.)/s, $header, 2); + # If it's not a valid header (aka: not in the form "foo: bar"), skip it. + if (defined $value) { + # limit the length of the pairs we store + if (length($key) > MAX_HEADER_KEY_LENGTH) { + $key = substr($key, 0, MAX_HEADER_KEY_LENGTH); + $self->{'truncated_header'} = 1; + } + if (length($value) > MAX_HEADER_VALUE_LENGTH) { + $value = substr($value, 0, MAX_HEADER_VALUE_LENGTH); + $self->{'truncated_header'} = 1; + } + $self->header($key, $value); + } + } - # If it's not a valid header (aka: not in the form "foo: bar"), skip it. - if (defined $value) { - # limit the length of the pairs we store - if (length($key) > MAX_HEADER_KEY_LENGTH) { - $key = substr($key, 0, MAX_HEADER_KEY_LENGTH); - $self->{'truncated_header'} = 1; - } - if (length($value) > MAX_HEADER_VALUE_LENGTH) { - $value = substr($value, 0, MAX_HEADER_VALUE_LENGTH); - $self->{'truncated_header'} = 1; - } - $self->header($key, $value); + # not a continuation... + $header = $last; + } - # If we're currently dealing with a content-type header, and there's a - # boundary defined, use it. Since there could be multiple - # content-type headers in a message, the last one will be the one we - # should use, so just keep updating as they come in. - if (lc $key eq 'content-type') { - my($type,$temp_boundary) = Mail::SpamAssassin::Util::parse_content_type($value); - $boundary = $temp_boundary if ($type =~ /^multipart/ && defined $temp_boundary); - } + if ($header) { + if ($header =~ /^\r?$/) { + last; + } + else { + # Check for missing head/body separator + # RFC 2822, s2.2: + # A field name MUST be composed of printable US-ASCII characters + # (i.e., characters that have values between 33 (041) and 126 (176), inclusive), + # except colon (072). + # FOR THIS NEXT PART: list off the valid REs for what can be next: + # Header, header continuation, blank line + if (!@@message || $message[0] !~ /^(?:[\041-\071\073-\176]+:|[ \t]|\r?$)/ || $message[0] =~ /^--/) { + # No body or no separator before mime boundary is invalid + $self->{'missing_head_body_separator'} = 1; + + # we *have* to go back through again to make sure we catch the last + # header, so fake a separator and loop again. + unshift(@@message, "\n"); + } } } - - # not a continuation... - $header = $last; - - # Ok, we found the header/body blank line ... - last if ($last =~ /^\r?$/m); - - # Alternately, if a multipart mime boundary is found in the header area, - # aka it's malformed, exit out as well and treat it as part of the body. - last if (defined $boundary && @@message && $message[0] =~ /^--\Q$boundary\E(?:--|\s*$)/); } # Store the pristine body for later -- store as a copy since @@message @@@@ -586,8 +576,9 @@@@ dbg("parsing normal part"); - $part_msg->{'type'} = - Mail::SpamAssassin::Util::parse_content_type($part_msg->header('content-type')); + # 0: content-type, 1: boundary, 2: charset, 3: filename + my @@ct = Mail::SpamAssassin::Util::parse_content_type($part_msg->header('content-type')); + $part_msg->{'type'} = $ct[0]; # multipart sections are required to have a boundary set ... If this # one doesn't, assume it's malformed and revert to text/plain @@@@ -595,11 +586,15 @@@@ # attempt to figure out a name for this attachment if there is one ... my $disp = $part_msg->header('content-disposition') || ''; - my($filename) = $disp =~ /name="?([^\";]+)"?/i || $part_msg->{'type'} =~ /name="?([^\";]+)"?/i; + if ($disp =~ /name="?([^\";]+)"?/i) { + $part_msg->{'name'} = $1; + } + elsif ($ct[3]) { + $part_msg->{'name'} = $ct[3]; + } $part_msg->{'raw'} = $body; $part_msg->{'boundary'} = $boundary; - $part_msg->{'name'} = $filename if $filename; # If this part is a message/* part, and the parent isn't also a # message/* part (ie: the main part) go ahead and parse into a tree. @ 1.1.2.1 log @DoS Security Fixes (OpenPKG-SA-2004.041-spamassassin; CAN-2004-0796) @ text @a0 135 DoS Security Fixes (OpenPKG-SA-2004.041-spamassassin; CAN-2004-0796) See also: http://marc.theaimsgroup.com/?l=spamassassin-announce&m=109168121628767&w=2 Index: lib/Mail/SpamAssassin/Bayes.pm --- lib/Mail/SpamAssassin/Bayes.pm 2004-01-18 00:56:08 +0100 +++ lib/Mail/SpamAssassin/Bayes.pm 2004-08-05 03:48:34 +0200 @@@@ -137,6 +137,15 @@@@ use constant HDRS_TOKENIZE_LONG_TOKENS_AS_SKIPS => 1; use constant BODY_TOKENIZE_LONG_TOKENS_AS_SKIPS => 1; +# maximum byte length of a header key +use constant MAX_HEADER_KEY_LENGTH => 256; + +# maximum byte length of a header value including continued lines +use constant MAX_HEADER_VALUE_LENGTH => 8192; + +# maximum byte length of entire header +use constant MAX_HEADER_LENGTH => 65536; + # We store header-mined tokens in the db with a "HHeaderName:val" format. # some headers may contain lots of gibberish tokens, so allow a little basic # compression by mapping the header name at least here. these are the headers @@@@ -432,7 +441,28 @@@@ sub tokenize_headers { my ($self, $msg) = @@_; - my $hdrs = $msg->get_all_headers(); + my @@hdrs = (); + my $length = 0; + + my $hdr; + foreach $hdr ($msg->get_all_headers()) { + last if ($length + length($hdr) > MAX_HEADER_LENGTH); + + my($key, $value) = split(/:/, $hdr, 2); + + # limit the length of the pairs we store + if (length($key) > MAX_HEADER_KEY_LENGTH) { + $key = substr($key, 0, MAX_HEADER_KEY_LENGTH); + } + if (length($value) > MAX_HEADER_VALUE_LENGTH) { + $value = substr($value, 0, MAX_HEADER_VALUE_LENGTH); + } + push(@@hdrs, "$key:$value"); + $length += length "$key:$value"; + } + + my $hdrs = join('', @@hdrs); + undef @@hdrs; # jm: do not learn additional metadata (X-Languages, X-Relays-Untrusted) # until we can generate that while running sa-learn. TODO Index: lib/Mail/SpamAssassin/PerMsgStatus.pm Mail-SpamAssassin-2.64/lib/Mail/SpamAssassin/PerMsgStatus.pm --- lib/Mail/SpamAssassin/PerMsgStatus.pm 2004-01-20 22:40:04 +0100 +++ lib/Mail/SpamAssassin/PerMsgStatus.pm 2004-08-05 03:48:33 +0200 @@@@ -48,6 +48,16 @@@@ use constant MAX_BODY_LINE_LENGTH => 2048; +# maximum byte length of a header key +use constant MAX_HEADER_KEY_LENGTH => 256; + +# maximum byte length of a header value including continued lines +use constant MAX_HEADER_VALUE_LENGTH => 8192; + +# maximum byte length of entire header +use constant MAX_HEADER_LENGTH => 65536; + + use vars qw{ @@ISA $base64alphabet }; @@@@ -1314,7 +1324,26 @@@@ my $getraw = ($hdrname eq 'ALL' || $hdrname =~ s/:raw$//); if ($hdrname eq 'ALL') { - $_ = $self->{msg}->get_all_headers(); + my @@hdrs = (); + my $length = 0; + + my $hdr; + foreach $hdr ($self->{msg}->get_all_headers()) { + last if ($length + length($hdr) > MAX_HEADER_LENGTH); + + my($key, $value) = split(/:/, $hdr, 2); + # limit the length of the pairs we store + if (length($key) > MAX_HEADER_KEY_LENGTH) { + $key = substr($key, 0, MAX_HEADER_KEY_LENGTH); + } + if (length($value) > MAX_HEADER_VALUE_LENGTH) { + $value = substr($value, 0, MAX_HEADER_VALUE_LENGTH); + } + push(@@hdrs, "$key:$value"); + $length += length "$key:$value"; + } + + $_ = join('', @@hdrs); } # ToCc: the combined recipients list elsif ($hdrname eq 'ToCc') { @@@@ -1324,7 +1353,14 @@@@ $_ .= ", " if /\S/; } $_ .= join ("\n", $self->{msg}->get_header ('Cc')); - undef $_ if $_ eq ''; + if ($_ eq '') { + undef $_; + } + else { + if (length($_) > MAX_HEADER_VALUE_LENGTH) { + $_ = substr($_, 0, MAX_HEADER_VALUE_LENGTH); + } + } } # MESSAGEID: handle lists which move the real message-id to another # header for resending. @@@@ -1334,12 +1370,18 @@@@ $self->{msg}->get_header ('Resent-Message-Id'), $self->{msg}->get_header ('X-Original-Message-ID'), # bug 2122 $self->{msg}->get_header ('Message-Id')); + if (length($_) > MAX_HEADER_VALUE_LENGTH) { + $_ = substr($_, 0, MAX_HEADER_VALUE_LENGTH); + } } # a conventional header else { my @@hdrs = $self->{msg}->get_header ($hdrname); if ($#hdrs >= 0) { $_ = join ("\n", @@hdrs); + if (length($_) > MAX_HEADER_VALUE_LENGTH) { + $_ = substr($_, 0, MAX_HEADER_VALUE_LENGTH); + } } else { $_ = undef; @