Any news on getting this fixed?

I've rewritten my test program to be more simple and i will explain what is wrong, including sample output. hopefully this clears up the prior confusion with my previous bug reports.

--------PROGRAM----------

#!/usr/bin/perl -w

use strict;

use HTTP::Message;
use HTTP::Headers;
use Data::Dumper;

my $content = '------------0xKhTmLbOuNdArY
Content-Disposition: form-data; name="correct"

some data
------------0xKhTmLbOuNdArY
Content-Disposition: form-data; name="incorrect"

aoeu:aoeu
------------0xKhTmLbOuNdArY--
';

my $headers = HTTP::Headers->new;
$headers->header( 'content-type' => 'multipart/form-data; boundary=----------0xKhTmLbOuNdArY' );
my $m = HTTP::Message->new($headers,$content);

foreach my $part ($m->parts)
{
  print STDERR Dumper($part);
}



------OUTPUT----------

$VAR1 = bless( {
                 '_content' => 'some data',
                 '_headers' => bless( {
'content-disposition' => 'form-data; name="correct"'
                                      }, 'HTTP::Headers' )
               }, 'HTTP::Message' );
$VAR1 = bless( {
                 '_content' => '',
                 '_headers' => bless( {
'content-disposition' => 'form-data; name="incorrect"',
                                        '
aoeu' => 'aoeu'
                                      }, 'HTTP::Headers' )
               }, 'HTTP::Message' );

What's wrong: The 2nd Part shows no content and lists "\naoeu" => 'aoeu' as a header. 'aoeu:aoeu' should be the content. The parser is parsing the content of the message. It should not be. Once the blank line is reached, it's the beginning of the content and should no longer be parsed.

Here is the current parse() function:

sub parse
{
    my($class, $str) = @_;

    my @hdr;
    while (1) {
        if ($str =~ s/^([^ \t:]+)[ \t]*: ?(.*)\n?//) {
            push(@hdr, $1, $2);
            $hdr[-1] =~ s/\r\z//;
        }
        elsif (@hdr && $str =~ s/^([ \t].*)\n?//) {
            $hdr[-1] .= "\n$1";
            $hdr[-1] =~ s/\r\z//;
        }
        else {
            $str =~ s/^\r?\n//;
            last;
        }
    }

    new($class, [EMAIL PROTECTED], $str);
}

When the part is being parsed, the first REGEX is matching past the end of the headers and into the content. This is because the ([^ \t:] +) goes past blank line that is supposed to be the end of the headers and into the content. One way to fix this is to change the code so that it checks for the end of the headers as a last part of the loop.

sub parse
{
    my($class, $str) = @_;

    my @hdr;
    while (1) {
        if ($str =~ s/^([^ \t:]+)[ \t]*: ?(.*)\n?//) {
            push(@hdr, $1, $2);
            $hdr[-1] =~ s/\r\z//;
        }
        elsif (@hdr && $str =~ s/^([ \t].*)\n?//) {
            $hdr[-1] .= "\n$1";
            $hdr[-1] =~ s/\r\z//;
        }

        # check to see if we are at the end of the headers.
        if ($str =~ /^\r?\n/) {
            $str =~ s/^\r?\n//;
            last;
        }
    }

    new($class, [EMAIL PROTECTED], $str);
}

Please contact me if there is still confusion with this.

Best Regards,


Brian Hirt


On Aug 15, 2005, at 2:12 AM, Brian Hirt wrote:

FYI, i'm not the only one seeing this bug.

Begin forwarded message:


From: " via RT" <[EMAIL PROTECTED]>
Date: August 13, 2005 8:55:10 PM MDT
To: [EMAIL PROTECTED]
Subject: [cpan #13025] parsing bug in HTTP::Message::parse()
Reply-To: [EMAIL PROTECTED]


Full context and any attached attachments can be found at:
<URL: http://rt.cpan.org/NoAuth/Bug.html?id=13025 >

[guest - Mon May 30 19:20:21 2005]:



Hi!

I've stumbled across a bug in multi-part messages in HTTP::Message.
If the message content contains something that looks like a header, it accidentally gets detected as a header. However, a blank line after a header should signal the end of headers, and below it, the
   start of content as per the spec.  It just looks like your regex
   needs some tweeking, or maybe do something like this:



Found the same problem today... :(

  #!/usr/bin/perl
  use strict;
  use warnings;
  use HTTP::Message;
  use Data::Dumper;

  my $bad = qq(Content-Disposition: form-data; name="fetch_url"\n)
      . qq(\nhttp://www.jbisbee.com/\n);
  my $part = HTTP::Message->parse($bad);
  warn Dumper($part);

With the output...

  $VAR1 = bless( {
    '_content' => '',
    '_headers' => bless( {
      'content-disposition' => 'form-data; name="fetch_url"',
      '                                  '
http' => '//www.jbisbee.com/'
    }, 'HTTP::Headers' )
  }, 'HTTP::Message' );

of course this only happens with forms that specify

  enctype="multipart/form-data"

for uploads so it may be a bit hard to reproduce




--------------------------------------------
MobyGames
http://www.mobygames.com
The world's largest and most comprehensive
gaming database project

Reply via email to