Ian Miller <[EMAIL PROTECTED]> writes:
> On Wed, Jun 28, 2000 at 10:46:29AM +0200, Gisle Aas screived:
> >
> > > sub text {
> > > my ($self, $text) = @_;
> > >
> > > print STDERR "$text\n----- END CHUNK -----\n";
> > > @_ = split(/\W/, $text); ## this causes the segfault
> > > }
> >
> > By the assignment to @_ you are clobbering $self and other stuff. Why
> > don't you use your own lexical array??? :-)
>
> Sorry, I culled that program from something bigger and only used @_ on the
> spur of the moment, to stop -w giving a warning about a useless split!
> It was my belief at the time that it was the split command itself that
> was causing the segmentation fault [now known to be untrue].
>
> (Ironically, it turns out that -w doesn't give a warning when split
> is the last command in a method anyway, as it is then the return value!)
I was wrong about the assignment to @_. It does not clobber the stuff
inside @_. Sorry. That was my fast&wrong conclution when I saw that
$self got undefined and that the problem got fixed in my reduced
test case by making a mortal copy of the reference. Unfortunately I
forgot to check again against your full test case.
> > ...but HTML::Parser was stupid enough to send the same reference to
> > all calls. That meant that the next handler invoked got your
> > clobbered $self as its argument and eventually perl got confused
> > during global destruction. This patch make sure that we copy the
> > reference for each callback invocation. That should cure the problem.
>
> I think I understand... however, this is apparently *not* the cause of
> the problem. I have applied the patch, and the segmentation fault still
> occurs at the @_ assignment!
>
> Furthermore, a segmentation fault even occurs for assignment to a lexical!
> e.g.
> sub text {
> my ($self, $text) = @_;
>
> print STDERR "$text\n----- END CHUNK -----\n";
> my @blahblah = split(/\W/, $text); ## this causes the segfault
> }
>
> And... if you reverse the order of the print and assignment lines, then
> you get a `bus error' instead of a segmentation fault! Very, very strange...
There was one more bug. When we call flush_pending_text() something
might happen that change the stack pointer cached by dSP declared at
the start of the report_event() routine, so we need to refresh it. I
also added a few more mortal copies to make sure you can't try assign
to perl's internal constants by assignment to $_[$n] inside a handler.
If you apply this patch on top of the previous one, all your bugs
should be fixed (I hope)! I'll think I wait a day or two before
pushing this as HTML-Parser-3.10 :-)
Regards,
Gisle
Index: hparser.c
===================================================================
RCS file: /home/cvs/aas/perl/mods/html-parser/hparser.c,v
retrieving revision 2.43
retrieving revision 2.44
diff -u -p -u -r2.43 -r2.44
--- hparser.c 2000/06/28 08:34:31 2.43
+++ hparser.c 2000/06/28 11:35:05 2.44
@@ -1,4 +1,4 @@
-/* $Id: hparser.c,v 2.43 2000/06/28 08:34:31 gisle Exp $
+/* $Id: hparser.c,v 2.44 2000/06/28 11:35:05 gisle Exp $
*
* Copyright 1999-2000, Gisle Aas
* Copyright 1999-2000, Michael A. Chase
@@ -149,6 +149,7 @@ report_event(PSTATE* p_state,
if (SvOK(p_state->pend_text)) {
if (p_state->is_cdata != p_state->pend_text_is_cdata) {
flush_pending_text(p_state, self);
+ SPAGAIN;
goto INIT_PEND_TEXT;
}
}
@@ -163,6 +164,7 @@ report_event(PSTATE* p_state,
}
else if (p_state->pend_text && SvOK(p_state->pend_text)) {
flush_pending_text(p_state, self);
+ SPAGAIN;
}
h = &p_state->handlers[event];
@@ -345,7 +347,7 @@ report_event(PSTATE* p_state,
break;
case ARG_UNDEF:
- arg = &PL_sv_undef;
+ arg = sv_mortalcopy(&PL_sv_undef);
break;
default:
@@ -354,7 +356,7 @@ report_event(PSTATE* p_state,
}
if (!arg)
- arg = &PL_sv_undef;
+ arg = sv_mortalcopy(&PL_sv_undef);
if (array) {
/* have to fix mortality here or