Fwd: [cpan #13025] parsing bug in HTTP::Message::parse()
Brian Hirt <[email protected]>
| Newsgroups | gmane.comp.lang.perl.modules.lwp |
|---|---|
| Message-ID | <[email protected]> |
i'm not sure if this made it to the list, so I'm reposting. Begin forwarded message: > From: Brian Hirt <[email protected]> > Date: August 31, 2005 12:34:21 PM MDT > To: [email protected] > Cc: [email protected], Brian Hirt <[email protected]> > Subject: Re: [cpan #13025] parsing bug in HTTP::Message::parse() > > > 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, \@hdr, $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, \@hdr, $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 > > -------------------------------------------- MobyGames http://www.mobygames.com The world's largest and most comprehensive gaming database project