Commits

Nick Wellnhofer committed 676a653

Make parse_fh more robust wrt encoding layers

Throw an exception instead of crashing when a file handle which uses an
encoding layer is passed to parse_fh and reads more bytes than requested.
Fixes RT #78448:

https://rt.cpan.org/Ticket/Display.html?id=78448

A better fix would require to rewrite the LibXML_read_perl interface to
allow for variable size results.

  • Participants
  • Parent commits f353c23

Comments (0)

Files changed (4)

 Revision history for Perl extension XML::LibXML
 
 Not yet released
+    - Die if a file handle with an encoding layer returns more bytes
+      than requested in parse_fh.
+        - https://rt.cpan.org/Ticket/Display.html?id=78448
     - Make insertData, deleteData, replaceData work correctly with UTF-8
       strings.
     - Fix substringData
 
     int cnt;
     SV * read_results;
+    IV read_results_iv;
     STRLEN read_length;
     char * chars;
     SV * tbuff = NEWSV(0,len);
         croak("read error");
     }
 
-    read_length = SvIV(read_results);
+    read_results_iv = SvIV(read_results);
 
     chars = SvPV(tbuff, read_length);
+
+    /*
+     * If the file handle uses an encoding layer, the length parameter is
+     * interpreted as character count, not as byte count. So it's possible
+     * that more than len bytes are read which would overflow the buffer.
+     * Check for this condition also by comparing the return value.
+     */
+    if (read_results_iv != read_length || read_length > len) {
+        croak("Read more bytes than requested. Do you use an encoding-related"
+              " PerlIO layer?");
+    }
     strncpy(buffer, chars, read_length);
 
     PUTBACK;
 use strict;
 use warnings;
 
-use Test::More tests => 531;
+use Test::More tests => 533;
 use IO::File;
 
 use XML::LibXML::Common qw(:libxml);
 
 }
 
+{
+    my $parser = XML::LibXML->new();
+    open(my $fh, '<:utf8', 't/data/chinese.xml');
+    ok( $fh, 'open chinese.xml');
+    eval {
+        $parser->parse_fh($fh);
+    };
+    like( $@, qr/Read more bytes than requested/,
+          'UTF-8 encoding layer throws exception' );
+    close($fh);
+}
+
 sub tsub {
     my $doc = shift;
 
     SKIP:
     {
         my $num_tests = 2;
+
+        # LibXML_read_perl doesn't play well with encoding layers. Skip
+        # unconditionally for now.
+        skip("skipping until LibXML_read_perl is fixed", $num_tests);
+
         if (1000*$] < 5008)
         {
             skip("skipping for Perl < 5.8", $num_tests);
 
     SKIP:
     {
+        my $num_tests = 2;
+
+        # LibXML_read_perl doesn't play well with encoding layers. Skip
+        # unconditionally for now.
+        skip("skipping until LibXML_read_perl is fixed", $num_tests);
+
         if (1000*$] < 5008)
         {
-            skip("skipping for Perl < 5.8", 2);
+            skip("skipping for Perl < 5.8", $num_tests);
         }
         # translate to UTF8 on perl-side
         open my $fh, '<:encoding(iso-8859-2)', $test_file