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