Skip to content

Add additional check for custom array/hash access checking #23399

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: blead
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 8 additions & 4 deletions peep.c
Original file line number Diff line number Diff line change
Expand Up @@ -2203,16 +2203,20 @@ S_maybe_multideref(pTHX_ OP *start, OP *orig_o, UV orig_action, U8 hints)
* OP_EXISTS or OP_DELETE */

/* if a custom array/hash access checker is in scope,
* abandon optimisation attempt */
* abandon optimisation attempt. Check two different ways because
* of z/OS (see comments in opcode.h) */
if ( (o->op_type == OP_AELEM || o->op_type == OP_HELEM)
&& PL_check[o->op_type] != Perl_ck_null)
&& UNLIKELY(PL_check[o->op_type] != Perl_ck_null)
&& UNLIKELY(PL_check[o->op_type] != PL_check[PERL_CK_NULL]))
return;
/* similarly for customised exists and delete */
if ( (o->op_type == OP_EXISTS)
&& PL_check[o->op_type] != Perl_ck_exists)
&& UNLIKELY(PL_check[OP_EXISTS] != Perl_ck_exists)
&& UNLIKELY(PL_check[OP_EXISTS] != PL_check[PERL_CK_EXISTS]))
return;
if ( (o->op_type == OP_DELETE)
&& PL_check[o->op_type] != Perl_ck_delete)
&& UNLIKELY(PL_check[OP_DELETE] != Perl_ck_delete)
&& UNLIKELY(PL_check[OP_DELETE] != PL_check[PERL_CK_DELETE]))
return;

if ( o->op_type != OP_AELEM
Expand Down
26 changes: 26 additions & 0 deletions regen/opcode.pl
Original file line number Diff line number Diff line change
Expand Up @@ -1114,13 +1114,39 @@ sub generate_opcode_h_pl_check {
INIT({
END


for (@ops) {
print "\t", tab(3, "Perl_$check{$_},"), "\t/* $_ */\n";
}

print <<~'END';

/* The final entries are function pointers not attached to an opcode.
* These are used to compare with function pointers in the earlier part of
* the array, since in some platforms (notably z/OS), it is undefined
* behavior to compare function pointers for equality, even though calling
* them will invoke the same function. This minimizes the risk of them
* being different by initializing them to the same values in the same
* array. */
END
my @perl_internal_extras = qw(ck_null ck_exists ck_delete);
for (@perl_internal_extras) {
print "\t", tab(3, "Perl_$_,\n");
}

print <<~'END';
});

/* Indexes into PL_check for the comparison function pointers */
#ifdef PERL_IN_PEEP_C
END

for (my $i = 0; $i < @perl_internal_extras; $i++) {
my $index = @ops + $i;
my $define = uc $perl_internal_extras[$i];
print " #define PERL_$define $index\n";
}
print "#endif\n";
}

sub generate_opcode_h_pl_opargs {
Expand Down
Loading