Skip to content

Commit

Permalink
whichsig nul-cleanup.
Browse files Browse the repository at this point in the history
This adds _pv, _pvn, and _pv versions of whichsig() in mg.c, which
get both kill "NAME" and %SIG lookup nul-clean.
  • Loading branch information
Hugmeir authored and Father Chrysostomos committed Oct 6, 2011
1 parent 89a5757 commit 84c7b88
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 24 deletions.
1 change: 1 addition & 0 deletions MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -3870,6 +3870,7 @@ ext/XS-APItest/t/temp_lv_sub.t XS::APItest: tests for lvalue subs returning temp
ext/XS-APItest/t/underscore_length.t Test find_rundefsv()
ext/XS-APItest/t/utf16_to_utf8.t Test behaviour of utf16_to_utf8{,reversed}
ext/XS-APItest/t/utf8.t Tests for code in utf8.c
ext/XS-APItest/t/whichsig.t XS::APItest: tests for whichsig() and variants
ext/XS-APItest/t/xs_special_subs_require.t for require too
ext/XS-APItest/t/xs_special_subs.t Test that XS BEGIN/CHECK/INIT/END work
ext/XS-APItest/t/xsub_h.t Tests for XSUB.h
Expand Down
11 changes: 7 additions & 4 deletions doio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1567,6 +1567,7 @@ Perl_apply(pTHX_ I32 type, register SV **mark, register SV **sp)
register I32 tot = 0;
const char *const what = PL_op_name[type];
const char *s;
STRLEN len;
SV ** const oldmark = mark;

PERL_ARGS_ASSERT_APPLY;
Expand Down Expand Up @@ -1677,12 +1678,14 @@ nothing in the core.
APPLY_TAINT_PROPER();
if (mark == sp)
break;
s = SvPVx_nolen_const(*++mark);
s = SvPVx_const(*++mark, len);
if (isALPHA(*s)) {
if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
if (*s == 'S' && s[1] == 'I' && s[2] == 'G') {
s += 3;
if ((val = whichsig(s)) < 0)
Perl_croak(aTHX_ "Unrecognized signal name \"%s\"",s);
len -= 3;
}
if ((val = whichsig_pvn(s, len)) < 0)
Perl_croak(aTHX_ "Unrecognized signal name \"%"SVf"\"", SVfARG(*mark));
}
else
val = SvIV(*mark);
Expand Down
4 changes: 3 additions & 1 deletion embed.fnc
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,9 @@ Afp |void |ck_warner_d |U32 err|NN const char* pat|...
Ap |void |vwarner |U32 err|NN const char* pat|NULLOK va_list* args
: FIXME
p |void |watch |NN char** addr
Ap |I32 |whichsig |NN const char* sig
Ap |I32 |whichsig_sv |NN SV* sigsv
Ap |I32 |whichsig_pv |NN const char* sig
Ap |I32 |whichsig_pvn |NN const char* sig|STRLEN len
: Used in pp_ctl.c
p |void |write_to_stderr|NN SV* msv
: Used in op.c
Expand Down
4 changes: 3 additions & 1 deletion embed.h
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,9 @@
#ifndef PERL_IMPLICIT_CONTEXT
#define warner Perl_warner
#endif
#define whichsig(a) Perl_whichsig(aTHX_ a)
#define whichsig_pv(a) Perl_whichsig_pv(aTHX_ a)
#define whichsig_pvn(a,b) Perl_whichsig_pvn(aTHX_ a,b)
#define whichsig_sv(a) Perl_whichsig_sv(aTHX_ a)
#if !(defined(HAS_SIGACTION) && defined(SA_SIGINFO))
#define csighandler Perl_csighandler
#endif
Expand Down
25 changes: 25 additions & 0 deletions ext/XS-APItest/APItest.xs
Original file line number Diff line number Diff line change
Expand Up @@ -2002,6 +2002,31 @@ gv_autoload_type(stash, methname, type, method)
}
XPUSHs( gv ? (SV*)gv : &PL_sv_undef);

void
whichsig_type(namesv, type)
SV* namesv
int type
PREINIT:
STRLEN len;
const char * const name = SvPV_const(namesv, len);
I32 i;
PPCODE:
switch (type) {
case 0:
i = whichsig(name);
break;
case 1:
i = whichsig_sv(namesv);
break;
case 2:
i = whichsig_pv(name);
break;
case 3:
i = whichsig_pvn(name, len);
break;
}
XPUSHs(sv_2mortal(newSViv(i)));

void
eval_sv(sv, flags)
SV* sv
Expand Down
26 changes: 26 additions & 0 deletions ext/XS-APItest/t/whichsig.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!perl

use strict;
use warnings;

use Test::More tests => 9;

use_ok('XS::APItest');

my @types = map { 'whichsig' . $_ } '', qw( _sv _pv _pvn );

sub test { "Sanity check" }

{
for my $type ( 0..3 ) {
is XS::APItest::whichsig_type("KILL", $type), 9, "Sanity check, $types[$type] works";
}
}

is XS::APItest::whichsig_type("KILL\0whoops", 0), 9, "whichsig() is not nul-clean";

is XS::APItest::whichsig_type("KILL\0whoops", 1), -1, "whichsig_sv() is nul-clean";

is XS::APItest::whichsig_type("KILL\0whoops", 2), 9, "whichsig_pv() is not nul-clean";

is XS::APItest::whichsig_type("KILL\0whoops", 3), -1, "whichsig_pvn() is nul-clean";
57 changes: 42 additions & 15 deletions mg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1302,7 +1302,9 @@ Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg)
PERL_ARGS_ASSERT_MAGIC_GETSIG;

if (!i) {
mg->mg_private = i = whichsig(MgPV_nolen_const(mg));
STRLEN siglen;
const char * sig = MgPV_const(mg, siglen);
mg->mg_private = i = whichsig_pvn(sig, siglen);
}

if (i > 0) {
Expand Down Expand Up @@ -1493,18 +1495,21 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
PERL_ARGS_ASSERT_MAGIC_SETSIG;

if (*s == '_') {
if (strEQ(s,"__DIE__"))
if (memEQs(s, len, "__DIE__"))
svp = &PL_diehook;
else if (strEQ(s,"__WARN__")
else if (memEQs(s, len, "__WARN__")
&& (sv ? 1 : PL_warnhook != PERL_WARNHOOK_FATAL)) {
/* Merge the existing behaviours, which are as follows:
magic_setsig, we always set svp to &PL_warnhook
(hence we always change the warnings handler)
For magic_clearsig, we don't change the warnings handler if it's
set to the &PL_warnhook. */
svp = &PL_warnhook;
} else if (sv)
Perl_croak(aTHX_ "No such hook: %s", s);
} else if (sv) {
SV *tmp = sv_newmortal();
Perl_croak(aTHX_ "No such hook: %s",
pv_pretty(tmp, s, len, 0, NULL, NULL, 0));
}
i = 0;
if (svp && *svp) {
if (*svp != PERL_WARNHOOK_FATAL)
Expand All @@ -1515,12 +1520,15 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
else {
i = (I16)mg->mg_private;
if (!i) {
i = whichsig(s); /* ...no, a brick */
i = whichsig_pvn(s, len); /* ...no, a brick */
mg->mg_private = (U16)i;
}
if (i <= 0) {
if (sv)
Perl_ck_warner(aTHX_ packWARN(WARN_SIGNAL), "No such signal: SIG%s", s);
if (sv) {
SV *tmp = sv_newmortal();
Perl_ck_warner(aTHX_ packWARN(WARN_SIGNAL), "No such signal: SIG%s",
pv_pretty(tmp, s, len, 0, NULL, NULL, 0));
}
return 0;
}
#ifdef HAS_SIGPROCMASK
Expand Down Expand Up @@ -1576,7 +1584,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
} else {
sv = NULL;
}
if (sv && strEQ(s,"IGNORE")) {
if (sv && memEQs(s, len,"IGNORE")) {
if (i) {
#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
PL_sig_ignoring[i] = 1;
Expand All @@ -1586,7 +1594,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
#endif
}
}
else if (!sv || strEQ(s,"DEFAULT") || !len) {
else if (!sv || memEQs(s, len,"DEFAULT") || !len) {
if (i) {
#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
PL_sig_defaulting[i] = 1;
Expand Down Expand Up @@ -2981,22 +2989,41 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
}

I32
Perl_whichsig(pTHX_ const char *sig)
Perl_whichsig_sv(pTHX_ SV *sigsv)
{
const char *sigpv;
STRLEN siglen;
PERL_ARGS_ASSERT_WHICHSIG_SV;
PERL_UNUSED_CONTEXT;
sigpv = SvPV_const(sigsv, siglen);
return whichsig_pvn(sigpv, siglen);
}

I32
Perl_whichsig_pv(pTHX_ const char *sig)
{
PERL_ARGS_ASSERT_WHICHSIG_PV;
PERL_UNUSED_CONTEXT;
return whichsig_pvn(sig, strlen(sig));
}

I32
Perl_whichsig_pvn(pTHX_ const char *sig, STRLEN len)
{
register char* const* sigv;

PERL_ARGS_ASSERT_WHICHSIG;
PERL_ARGS_ASSERT_WHICHSIG_PVN;
PERL_UNUSED_CONTEXT;

for (sigv = (char* const*)PL_sig_name; *sigv; sigv++)
if (strEQ(sig,*sigv))
if (strlen(*sigv) == len && memEQ(sig,*sigv, len))
return PL_sig_num[sigv - (char* const*)PL_sig_name];
#ifdef SIGCLD
if (strEQ(sig,"CHLD"))
if (memEQs(sig, len, "CHLD"))
return SIGCLD;
#endif
#ifdef SIGCHLD
if (strEQ(sig,"CLD"))
if (memEQs(sig, len, "CLD"))
return SIGCHLD;
#endif
return -1;
Expand Down
2 changes: 2 additions & 0 deletions mg.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ struct magic {
#define SvTIED_obj(sv,mg) \
((mg)->mg_obj ? (mg)->mg_obj : sv_2mortal(newRV(sv)))

#define whichsig(pv) whichsig_pv(pv)

/*
* Local variables:
* c-indentation-style: bsd
Expand Down
14 changes: 12 additions & 2 deletions proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -4643,11 +4643,21 @@ PERL_CALLCONV void Perl_watch(pTHX_ char** addr)
#define PERL_ARGS_ASSERT_WATCH \
assert(addr)

PERL_CALLCONV I32 Perl_whichsig(pTHX_ const char* sig)
PERL_CALLCONV I32 Perl_whichsig_pv(pTHX_ const char* sig)
__attribute__nonnull__(pTHX_1);
#define PERL_ARGS_ASSERT_WHICHSIG \
#define PERL_ARGS_ASSERT_WHICHSIG_PV \
assert(sig)

PERL_CALLCONV I32 Perl_whichsig_pvn(pTHX_ const char* sig, STRLEN len)
__attribute__nonnull__(pTHX_1);
#define PERL_ARGS_ASSERT_WHICHSIG_PVN \
assert(sig)

PERL_CALLCONV I32 Perl_whichsig_sv(pTHX_ SV* sigsv)
__attribute__nonnull__(pTHX_1);
#define PERL_ARGS_ASSERT_WHICHSIG_SV \
assert(sigsv)

PERL_CALLCONV void Perl_write_to_stderr(pTHX_ SV* msv)
__attribute__nonnull__(pTHX_1);
#define PERL_ARGS_ASSERT_WRITE_TO_STDERR \
Expand Down
17 changes: 16 additions & 1 deletion t/op/sigdispatch.t
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ BEGIN {
use strict;
use Config;

plan tests => 23;
plan tests => 26;

watchdog(15);

Expand Down Expand Up @@ -122,3 +122,18 @@ SKIP: {
alarm(0);
is($@, "HANDLER CALLED\n", 'string eval');
}

eval { $SIG{"__WARN__\0"} = sub { 1 } };
like $@, qr/No such hook: __WARN__\\0 at/, q!Fetching %SIG hooks with an extra trailing nul is nul-clean!;

eval { $SIG{"__DIE__\0whoops"} = sub { 1 } };
like $@, qr/No such hook: __DIE__\\0whoops at/;

{
use warnings;
my $w;
local $SIG{__WARN__} = sub { $w = shift };

$SIG{"KILL\0"} = sub { 1 };
like $w, qr/No such signal: SIGKILL\\0 at/, 'Arbitrary signal lookup through %SIG is clean';
}

0 comments on commit 84c7b88

Please sign in to comment.