Skip Menu |

This queue is for tickets about the POE CPAN distribution.

Report information
The Basics
Id: 133264
Status: open
Priority: 0/
Queue: POE

People
Owner: Nobody in particular
Requestors: perl [...] pied.nu
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: (no value)
Fixed in: (no value)



Subject: POE::Filter::HTTPD is corrupting binary data
POE::Filter::HTTPD->put() will concatenate HTTP header to the HTTP body. If the HTTP header is UTF-8, then the body is updated to UTF-8. Should be fine, except that POE::Driver::SysRW->flush() has use bytes; and that causes syswrite() to send the upgraded data buffer over the wire, rather then the code points (not sure of the correct term). The included patch moves the "use bytes" in SysRW->flush() to the scope it's necessary, the length() call. And it runs utf8::downgrade() on all data in HTTPD->put() for good measure.
Subject: Philip_Gwyn-POE-bytes_vs_syswrite.01.patch
Only in POE-1.368: MYMETA.json Only in POE-1.368: MYMETA.yml Only in POE-1.368: Makefile Only in POE-1.368: bingos-followtail Only in POE-1.368: blib Only in POE-1.368: diff diff -bur POE-1.368-orig/lib/POE/Driver/SysRW.pm POE-1.368/lib/POE/Driver/SysRW.pm --- POE-1.368-orig/lib/POE/Driver/SysRW.pm 2020-02-01 11:21:39.000000000 -0500 +++ POE-1.368/lib/POE/Driver/SysRW.pm 2020-09-01 17:03:58.024635768 -0400 @@ -118,7 +118,10 @@ my ($self, $handle) = @_; # Need to check lengths in octets, not characters. - BEGIN { eval { require bytes } and bytes->import; } + # 2020-09-01 Leolo - use bytes; is going to cause syswrite + # to use perl's internal buffer, which is will jumble binary data + # that's been upgraded to utf-8 + # BEGIN { eval { require bytes } and bytes->import; } # Reset errno in case there is nothing to write. # https://rt.cpan.org/Public/Bug/Display.html?id=87721 @@ -146,6 +149,7 @@ unless ($self->[CURRENT_OCTETS_LEFT] -= $wrote_count) { shift(@{$self->[OUTPUT_QUEUE]}); if (@{$self->[OUTPUT_QUEUE]}) { + BEGIN { eval { require bytes } and bytes->import; } $self->[CURRENT_OCTETS_DONE] = 0; $self->[CURRENT_OCTETS_LEFT] = length($self->[OUTPUT_QUEUE]->[0]); } Only in POE-1.368/lib/POE/Driver: SysRW.pm~ diff -bur POE-1.368-orig/lib/POE/Filter/HTTPD.pm POE-1.368/lib/POE/Filter/HTTPD.pm --- POE-1.368-orig/lib/POE/Filter/HTTPD.pm 2020-02-01 11:21:39.000000000 -0500 +++ POE-1.368/lib/POE/Filter/HTTPD.pm 2020-09-02 12:01:21.125462026 -0400 @@ -410,6 +410,7 @@ my $endl = "\x0D\x0A"; push @headers, $self->headers_as_strings( $_->headers, $endl ); push @raw, join( $endl, @headers, "", "") . $_->content; + utf8::downgrade( $raw[-1] ) if HAVE_UTF8 and utf8::is_utf8( $raw[-1] ); } \@raw; @@ -440,15 +441,12 @@ # In other words, plain ascii text. HTTP::Headers doesn't check for # this, of course. So if we complain here, the cluck ends up in # the wrong place. Doing the simplest thing - utf8::downgrade( $name ) if HAVE_UTF8; - # Deal with header values foreach my $value ( $H->header( $name ) ) { if( HAVE_UTF8 and utf8::is_utf8( $value ) ) { DEBUG and warn "$$: Header $name is UTF-8"; $value = encode_value( $value ); } - push @ret, join ": ", $name, _process_newline( $value, $endl ); } } Only in POE-1.368/lib/POE/Filter: HTTPD.pm~ Only in POE-1.368: pm_to_blib Only in POE-1.368: run_network_tests Only in POE-1.368/t/20_resources: 10_perl Only in POE-1.368/t: 30_loops