Skip to content

Commit

Permalink
[perl #131645] Fix assert fail in pp_sselect
Browse files Browse the repository at this point in the history
pp_sselect (4-arg select) process its first three bitfield arguments
first, making sure each one has a valid PV, and then it moves on to
the final, timeout argument.

SvGETMAGIC() on the timeout argument will wipe out any values the SV
holds, so if the same scalar is used as a bitfield argument *and* as
the timeout, it will no longer hold a valid PV.

Assertions later in pp_sselect make sure there is a valid PV.

This commit solves the assertion failure by making a temporary copy of
any gmagical or overloaded argument.  When the temporary copy is made,
the values written to the temporary copies of the bitfield arguments
are then copied back to the original magical arguments.
  • Loading branch information
Father Chrysostomos committed Jul 2, 2017
1 parent 7600a9e commit e26c690
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 7 deletions.
21 changes: 15 additions & 6 deletions pp_sys.c
Expand Up @@ -1149,6 +1149,7 @@ PP(pp_sselect)
struct timeval *tbuf = &timebuf;
I32 growsize;
char *fd_sets[4];
SV *svs[4];
#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
I32 masksize;
I32 offset;
Expand All @@ -1164,7 +1165,7 @@ PP(pp_sselect)

SP -= 4;
for (i = 1; i <= 3; i++) {
SV * const sv = SP[i];
SV * const sv = svs[i] = SP[i];
SvGETMAGIC(sv);
if (!SvOK(sv))
continue;
Expand All @@ -1177,9 +1178,14 @@ PP(pp_sselect)
if (!SvPOKp(sv))
Perl_ck_warner(aTHX_ packWARN(WARN_MISC),
"Non-string passed as bitmask");
SvPV_force_nomg_nolen(sv); /* force string conversion */
if (SvGAMAGIC(sv)) {
svs[i] = sv_newmortal();
sv_copypv_nomg(svs[i], sv);
}
else
SvPV_force_nomg_nolen(sv); /* force string conversion */
}
j = SvCUR(sv);
j = SvCUR(svs[i]);
if (maxlen < j)
maxlen = j;
}
Expand Down Expand Up @@ -1228,7 +1234,7 @@ PP(pp_sselect)
tbuf = NULL;

for (i = 1; i <= 3; i++) {
sv = SP[i];
sv = svs[i];
if (!SvOK(sv) || SvCUR(sv) == 0) {
fd_sets[i] = 0;
continue;
Expand Down Expand Up @@ -1275,7 +1281,7 @@ PP(pp_sselect)
#endif
for (i = 1; i <= 3; i++) {
if (fd_sets[i]) {
sv = SP[i];
sv = svs[i];
#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
s = SvPVX(sv);
for (offset = 0; offset < growsize; offset += masksize) {
Expand All @@ -1284,7 +1290,10 @@ PP(pp_sselect)
}
Safefree(fd_sets[i]);
#endif
SvSETMAGIC(sv);
if (sv != SP[i])
SvSetMagicSV(SP[i], sv);
else
SvSETMAGIC(sv);
}
}

Expand Down
11 changes: 10 additions & 1 deletion t/op/sselect.t
Expand Up @@ -13,7 +13,7 @@ BEGIN {
skip_all("Win32 miniperl has no socket select")
if $^O eq "MSWin32" && is_miniperl();

plan (15);
plan (16);

my $blank = "";
eval {select undef, $blank, $blank, 0};
Expand Down Expand Up @@ -95,3 +95,12 @@ note("diff=$diff under=$under");
select (undef, undef, undef, $sleep);
::is($count, 1, 'RT120102');
}

package _131645{
sub TIESCALAR { bless [] }
sub FETCH { 0 }
sub STORE { }
}
tie $tie, _131645::;
select ($tie, undef, undef, $tie);
ok("no crash from select $numeric_tie, undef, undef, $numeric_tie")

0 comments on commit e26c690

Please sign in to comment.