Fix incorrect collapser source being generated due to unicode collapse points
Peter Rabbitson [Fri, 24 Oct 2014 21:38:17 +0000 (23:38 +0200)]
I am not sure how nobody but abraxxa ran into this - the missing escapes have
been used by a ton of people for over a year. In any case the issue is real,
and fixed by trivial {}-escaping.

Add an extra stresstest envvar to make sure this does not regress in the
future (the envvar will be picked up and set by POISON_ENV on travis)

Changes
lib/DBIx/Class/ResultSet.pm
lib/DBIx/Class/ResultSource/RowParser.pm
lib/DBIx/Class/ResultSource/RowParser/Util.pm
lib/DBIx/Class/_Util.pm
t/resultset/rowparser_internals.t

diff --git a/Changes b/Changes
index fac01ff..3e703e8 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,9 @@
 Revision history for DBIx::Class
 
+    * Fixes
+        - Fix incorrect collapsing-parser source being generated in the
+          presence of unicode data among the collapse-points
+
 0.082801 2014-10-05 23:55 (UTC)
     * Known Issues
         - Passing large amounts of objects with stringification overload
index 3b3aab0..4513011 100644 (file)
@@ -1460,6 +1460,9 @@ sub _construct_results {
         if @violating_idx;
 
       $unrolled_non_null_cols_to_check = join (',', @$check_non_null_cols);
+
+      utf8::upgrade($unrolled_non_null_cols_to_check)
+        if DBIx::Class::_ENV_::STRESSTEST_UTF8_UPGRADE_GENERATED_COLLAPSER_SOURCE;
     }
 
     my $next_cref =
index 1c84b3c..107a53f 100644 (file)
@@ -136,6 +136,9 @@ sub _mk_row_parser {
     });
   };
 
+  utf8::upgrade($src)
+    if DBIx::Class::_ENV_::STRESSTEST_UTF8_UPGRADE_GENERATED_COLLAPSER_SOURCE;
+
   return (
     $args->{eval} ? ( eval "sub $src" || die $@ ) : $src,
     $check_null_columns,
index 4a03a55..3cf4aee 100644 (file)
@@ -153,12 +153,15 @@ sub assemble_collapsing_parser {
 
   my @idcol_args = $no_rowid_container ? ('', '') : (
     ', %cur_row_ids', # only declare the variable if we'll use it
-    join ("\n", map { qq(\$cur_row_ids{$_} = ) . (
-      # in case we prune - we will never hit these undefs
-      $args->{prune_null_branches} ? qq(\$cur_row_data->[$_];)
-      : HAS_DOR                    ? qq(\$cur_row_data->[$_] // "\0NULL\xFF\$rows_pos\xFF$_\0";)
-      :                              qq(defined(\$cur_row_data->[$_]) ? \$cur_row_data->[$_] : "\0NULL\xFF\$rows_pos\xFF$_\0";)
-    ) } sort { $a <=> $b } keys %{ $stats->{idcols_seen} } ),
+    join ("\n", map {
+      my $quoted_null_val = qq( "\0NULL\xFF\${rows_pos}\xFF${_}\0" );
+      qq(\$cur_row_ids{$_} = ) . (
+        # in case we prune - we will never hit these undefs
+        $args->{prune_null_branches} ? qq( \$cur_row_data->[$_]; )
+        : HAS_DOR                    ? qq( \$cur_row_data->[$_] // $quoted_null_val; )
+        :                              qq( defined(\$cur_row_data->[$_]) ? \$cur_row_data->[$_] : $quoted_null_val; )
+      )
+    } sort { $a <=> $b } keys %{ $stats->{idcols_seen} } ),
   );
 
   my $parser_src = sprintf (<<'EOS', @idcol_args, $top_node_key_assembler||'', $top_node_key, join( "\n", @{$data_assemblers||[]} ) );
index e2a9bbf..e01cebe 100644 (file)
@@ -34,6 +34,8 @@ BEGIN {
 
     ASSERT_NO_INTERNAL_INDIRECT_CALLS => $ENV{DBIC_ASSERT_NO_INTERNAL_INDIRECT_CALLS} ? 1 : 0,
 
+    STRESSTEST_UTF8_UPGRADE_GENERATED_COLLAPSER_SOURCE => $ENV{DBIC_STRESSTEST_UTF8_UPGRADE_GENERATED_COLLAPSER_SOURCE} ? 1 : 0,
+
     IV_SIZE => $Config{ivsize},
 
     OS_NAME => $^O,
index dd89b40..2377185 100644 (file)
@@ -751,6 +751,10 @@ done_testing;
 
 my $deparser;
 sub is_same_src { SKIP: {
+
+  skip "Skipping comparison of unicode-posioned source", 1
+    if DBIx::Class::_ENV_::STRESSTEST_UTF8_UPGRADE_GENERATED_COLLAPSER_SOURCE;
+
   $deparser ||= B::Deparse->new;
   local $Test::Builder::Level = $Test::Builder::Level + 1;