Skip to content

sv_setsv_cow() will SEGV if dstsv != perfectsv (design question) #23625

@bulk88

Description

@bulk88

Description

Design question.

I have 4-6 choices in my head how to fix this.
My opinion is all 4-6 choices are equally "the correct and best fix".
Looking for input before I write a patch making a permanent internal API change.
Or 6 years from now this could be a permanent CPAN XS pubic API

1 caller + PE export table inside perl543.dll @ 5.43.2, for a total of 2 consumers.

S_reg_set_capture_string+182	call    Perl_sv_setsv_cow
rdata:off_18030FE58	dd rva PL_EXACTFish_bitmask, rva PL_EXACT_REQ8_bitmask;
#ifdef PERL_ANY_COW
#  define SVt_COW SVt_PV
SV *
Perl_sv_setsv_cow(pTHX_ SV *dsv, SV *ssv)
{
    STRLEN cur = SvCUR(ssv);
    STRLEN len = SvLEN(ssv);
    char *new_pv;
    U32 new_flags = (SVt_COW|SVf_POK|SVp_POK|SVf_IsCOW);
#if defined(PERL_DEBUG_READONLY_COW) && defined(PERL_COPY_ON_WRITE)
    const bool already = cBOOL(SvIsCOW(ssv));
#endif

    PERL_ARGS_ASSERT_SV_SETSV_COW;
#ifdef DEBUGGING
    if (DEBUG_C_TEST) {
        PerlIO_printf(Perl_debug_log, "Fast copy on write: %p -> %p\n",
                      (void*)ssv, (void*)dsv);
        sv_dump(ssv);
        if (dsv)
                    sv_dump(dsv);
    }
#endif
    if (dsv) {
        if (SvTHINKFIRST(dsv))
            sv_force_normal_flags(dsv, SV_COW_DROP_PV);
        else if (SvPVX_const(dsv))      <<<<< ---- WHAT ??? !!!!!!!!!!!!!!!!!!!!!!
            Safefree(SvPVX_mutable(dsv));
        SvUPGRADE(dsv, SVt_COW); <<<<< ---- WHAT ??? !!!!!!!!!!!!!!!!!!!!!!
    }
    else
        dsv = newSV_type(SVt_COW);

Steps to Reproduce

use Devel::Peek;
use Data::Dumper;
#use Inline  ('force', 'noclean');

use Inline C => Config =>
 PRE_HEAD => '

 #define PERL_NO_GET_CONTEXT 1

 ';
use Inline C => Config => BUILD_NOISY => 1;
use Inline C => Config => PREFIX => 'MXS';

use Inline C => <<'END_OF_C_CODE';

static void S_setsv_cow(pTHX_ CV* cv) {
    dXSARGS;
    if(items != 2)
		croak_xs_usage(cv, "dsv, ssv");
    SV* ssv = POPs;
	SV* dsv = POPs;
	SV* retsv = Perl_sv_setsv_cow(aTHX_ dsv, ssv);
	PUSHs(retsv);
	PUTBACK;
    return;
}

void BOOT1() {
    dTHX;
	newXS( "setsv_cow", S_setsv_cow, __FILE__);
	return;
}

END_OF_C_CODE

$, = "\n";

#use v5.30;
#use strict;
#use warnings;
#$DB::single = 1;

use Benchmark qw(:all);
use Devel::Peek 'Dump';

BOOT1();

my $spath = 'txt.t';
my $dpath = (length(pack('p',undef)) * 3) + 2;
Dump($spath);
Dump($dpath);

# Unhandled exception thrown: read access violation.
# **ptr** was 0x2.
my $rpath = setsv_cow($dpath,$spath);

# unreached
Dump($rpath); 

__END__

>	perl541.dll!VMem::Free(void * pMem) Line 215	C++
 	[Inline Frame] perl541.dll!Perl_safesysfree(void * where) Line 433	C++
 	perl541.dll!Perl_sv_setsv_cow(interpreter * my_perl, sv * dsv, sv * ssv) Line 4922	C++
 	inlinec_pl_ae81.dll!S_setsv_cow(interpreter * my_perl, cv * cv) Line 40	C
 	[Inline Frame] perl541.dll!Perl_rpp_invoke_xs(interpreter *) Line 1177	C++
 	perl541.dll!Perl_pp_entersub(interpreter * my_perl) Line 6529	C++
 	perl541.dll!Perl_runops_standard(interpreter * my_perl) Line 41	C++
 	perl541.dll!S_run_body(interpreter * my_perl, long oldscope) Line 2885	C++
 	perl541.dll!perl_run(interpreter * my_perl) Line 2798	C++
 	perl541.dll!RunPerl(int argc, char * * argv, char * * env) Line 206	C++
 	[Inline Frame] perl.exe!invoke_main() Line 78	C++
 	perl.exe!__scrt_common_main_seh() Line 288	C++
 	kernel32.dll!BaseThreadInitThunk�()	Unknown
 	ntdll.dll!RtlUserThreadStart�()	Unknown

Expected behavior

Not

# Unhandled exception thrown: read access violation (0xC0000005)
# **ptr** was 0x2.

Fix is some permutation of P5P to P5P doc change (C comments), P5P to perlintern.pod doc change, P5P to perlapi.pod doc change, and C code change.

Its a matrix of choices, not pick 1 of 4.

doc change and/or code change

Perl configuration

5.43.2 and going back many years

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions