Skip to content
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

panic: memory wrap #105

Open
mjegh opened this issue Jul 22, 2019 · 4 comments
Open

panic: memory wrap #105

mjegh opened this issue Jul 22, 2019 · 4 comments

Comments

@mjegh
Copy link
Member

mjegh commented Jul 22, 2019

This is very similar to issue 15 (which was RT 94232) and was causes by the fix to RT91698 but far worse:

use strict;
use warnings;
use DBI;
use DBD::Oracle qw(:ora_types);
use Data::Dumper;

print "perl=$]  DBI=$DBI::VERSION  DBD::Oracle=$DBD::Oracle::VERSION\n";

my $dbh = DBI->connect(
    "dbi:Oracle:blahblah',
    "username",
    "password",
    {RaiseError => 1}
);

my $sth = $dbh->prepare(qq{
    BEGIN
        :out := '1';
    END;
});
$sth->bind_param_inout(':out', \my $result, 1
        , {ora_type => ORA_CHAR}
);
$sth->execute();
print Dumper($result);

$sth->execute();
print Dumper($result);

$dbh->disconnect;

Which outputs:

perl=5.022000  DBI=1.639  DBD::Oracle=1.791
$VAR1 = '1  ';
panic: memory wrap at rt94232_gh_15.pl line 27.
@djzort
Copy link
Collaborator

djzort commented Jun 20, 2020

Im guessing this is still an issue?

@tonycoz
Copy link

tonycoz commented Jun 26, 2020

@djzort asked me to have a look at this, but I've run into limits on my knowledge (and time) on how this is meant to work:

The base issue is this code:

                 SvGROW(phs->sv,(STRLEN) (unsigned int)phs->maxlen-1);

is called when phs->maxlen is 0, subtracting 1 returns 0xffffffffffffffff:

Breakpoint 1, Perl_croak_memory_wrap () at util.c:1776
1776	    Perl_croak_nocontext("%s",PL_memory_wrap);
(gdb) bt
#0  Perl_croak_memory_wrap () at util.c:1776
#1  0x00005555556fbb1c in Perl_sv_grow (my_perl=0x5555559ae260, 
    sv=0x555555e488b8, newlen=18446744073709551615) at sv.c:1607
#2  0x00007ffff7b90fbb in dbd_rebind_ph_char (imp_sth=0x555555a53cc0, 
    phs=0x555555f6ee20) at dbdimp.c:2789
#3  0x00007ffff7b92a73 in dbd_rebind_ph (sth=0x555555c95ba8, 
    imp_sth=0x555555a53cc0, phs=0x555555f6ee20) at dbdimp.c:3204
#4  0x00007ffff7b950e8 in ora_st_execute (sth=0x555555c95ba8, 
    imp_sth=0x555555a53cc0) at dbdimp.c:3689
#5  0x00007ffff7b7b4f5 in XS_DBD__Oracle__st_execute (my_perl=0x5555559ae260, 
    cv=0x555555de2ce0) at ./Oracle.xsi:623
#6  0x00007ffff7bd4cda in XS_DBI_dispatch (my_perl=0x5555559ae260, 
    cv=0x555555d43dd8) at DBI.xs:3783
#7  0x00005555556f5f99 in Perl_pp_entersub (my_perl=0x5555559ae260)
    at pp_hot.c:5277
#8  0x00005555556e2fe0 in Perl_runops_standard (my_perl=0x5555559ae260)
    at run.c:41
#9  0x00005555555d67eb in S_run_body (my_perl=0x5555559ae260, oldscope=1)
    at perl.c:2761
#10 0x00005555555d61ea in perl_run (my_perl=0x5555559ae260) at perl.c:2684
#11 0x000055555559c20a in main (argc=3, argv=0x7fffffffebb8, 
    env=0x7fffffffebd8) at perlmain.c:127
(gdb) up 2
#2  0x00007ffff7b90fbb in dbd_rebind_ph_char (imp_sth=0x555555a53cc0, 
    phs=0x555555f6ee20) at dbdimp.c:2789
2789	                SvGROW(phs->sv,(STRLEN) (unsigned int)phs->maxlen-1);
(gdb) p phs->maxlen
$1 = 0

How does it get that value? Initially it's set to the maxlen supplied to bind_param_inout:

3507		phs->maxlen = maxlen;		/* 0 if not inout		*/
(gdb) p maxlen
$2 = 1

but later it's modified:

(gdb) watch -l phs->maxlen
Hardware watchpoint 3: -location phs->maxlen
(gdb) c
Continuing.

Hardware watchpoint 3: -location phs->maxlen

Old value = 1
New value = 0
dbd_rebind_ph_char (imp_sth=0x555555a53810, phs=0x555555f6fb10)
    at dbdimp.c:2846
2846		if (phs->maxlen < 0)		/* can happen with nulls	*/
(gdb) l 2845 
2840	        }
2841			phs->maxlen  = ((IV)SvLEN(phs->sv)); /* avail buffer space (64bit safe) Logicaly maxlen should never change but it does why I know not - MJE because SvGROW can allocate more than you ask for - anyway - I fixed that and it doesn't grow anymore */
2842	
2843		}

Since $result is undef at this point, SvLEN() is 0 and phs->maxlen isn't modified again until the panic.

Hopefully someone with a better knowledge of DBD::Oracle will understand what's going on here.

@djzort
Copy link
Collaborator

djzort commented Jun 26, 2020

thanks @tonycoz

@djzort
Copy link
Collaborator

djzort commented Jun 28, 2020

@mjegh can we arrange to look at this? maybe chat via irc or something

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants