From: Peter Rabbitson Date: Fri, 24 Oct 2014 21:38:17 +0000 (+0200) Subject: Fix incorrect collapser source being generated due to unicode collapse points X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=2fdeef656102aed6c01b6af14d0f14ef06673fb3;p=dbsrgits%2FDBIx-Class-Historic.git Fix incorrect collapser source being generated due to unicode collapse points 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) --- diff --git a/Changes b/Changes index fac01ff..3e703e8 100644 --- 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 diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index 3b3aab0..4513011 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -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 = diff --git a/lib/DBIx/Class/ResultSource/RowParser.pm b/lib/DBIx/Class/ResultSource/RowParser.pm index 1c84b3c..107a53f 100644 --- a/lib/DBIx/Class/ResultSource/RowParser.pm +++ b/lib/DBIx/Class/ResultSource/RowParser.pm @@ -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, diff --git a/lib/DBIx/Class/ResultSource/RowParser/Util.pm b/lib/DBIx/Class/ResultSource/RowParser/Util.pm index 4a03a55..3cf4aee 100644 --- a/lib/DBIx/Class/ResultSource/RowParser/Util.pm +++ b/lib/DBIx/Class/ResultSource/RowParser/Util.pm @@ -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||[]} ) ); diff --git a/lib/DBIx/Class/_Util.pm b/lib/DBIx/Class/_Util.pm index e2a9bbf..e01cebe 100644 --- a/lib/DBIx/Class/_Util.pm +++ b/lib/DBIx/Class/_Util.pm @@ -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, diff --git a/t/resultset/rowparser_internals.t b/t/resultset/rowparser_internals.t index dd89b40..2377185 100644 --- a/t/resultset/rowparser_internals.t +++ b/t/resultset/rowparser_internals.t @@ -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;