develooper Front page | perl.perl5.porters | Postings from December 2017

Re: [perl #132638] I've discovered a segfault

Thread Previous | Thread Next
From:
shmem
Date:
December 24, 2017 01:02
Subject:
Re: [perl #132638] I've discovered a segfault
Message ID:
alpine.DEB.1.00.1712240050080.2163@mail.mgm-net.de
From the keyboard of Zefram [23.12.17,15:42]:

> shmem wrote:
>> Why should a buffer overflow be a bug but a stack overflow should not?
>
> For two reasons.  Firstly, buffer overflow is always an implementation
> mistake: Perl doesn't expose fixed-size buffers that the user can
> overflow.  Whereas stack overflow is a natural result of the Perl
> program: it is the user that coded an infinite recursion.  Secondly,
> buffer overflow can cause all kinds of erroneous behaviour, often
> exploitable to defeat security measures.  Whereas stack overflow just
> causes a segv that terminates the program.

Arguably the buffer overflow is an implementation mistake of the C
language implementation, which is known and must carefully be avoided.
C places the burden on the programmer here, as it does with stack
overflow. Perl has made sure buffer overflows don't occur, whereas wrt
stack overflows, perl doesn't care & passes the burden to the perl user.

> It would be nicer if deep recursion that currently occurs on the C stack
> were to be able to use more of the available memory, and eventually fail
> in some slightly cleaner way that cites lack of memory.  Simple cases
> of Perl recursion do avoid the C stack and get such behaviour.  But it
> would be quite infeasible to avoid C stack recursion in all cases, and
> very difficult to give C stack recursion nicer behaviour.  So we have
> made a tacit design decision that we put up with the limited C stack
> size and segv as the result of overflowing it, and thus we let that be
> the behaviour we offer to Perl programs.

It is not a design decision of perl, because it is not perl which emits
the SIGSEGV, it is the kernel - at least on Linux, and I bet it is no
different with other unixish sytems. The C stack size depends on the
current ulimit values which - again, on Linux - can be retrieved with
the getrlimit(2) syscall, and the current stack size can be obtained via
getrusage(2), if I am not mistaken altogether.

I know far too little of the perl internals to be able to tell at which
conditions a stack check along the lines of the above would be nice.

An alternative would be to set up an alternate signal stack as described
in getrlimit(2) and sigaltstack(2) to be able to mask SIGSEGV and make an
educated guess about where the condition occured, which could lead to
better error messages whenever a SIGSEGV is triggered.

The current stack size limit is a perl runtime condition. If I run the
short-circuited overload code in a root shell having set "ulimit -s
unlimited", I can sit and wait until the C stack has gobbled up all
memory (and swap) until the kernel finally emits an emergency kill (or
not, I didn't wait).

Running it with my current ulimit settings (-s being 8192 kbytes) it
segfaults at recursion 26196; if I decrease the stack size limit to 64
kbytes, it is blown off at recursion 171.

The simple recursion 'sub r{&r} r' instead seems to make the heap grow,
which is much harder to handle wrt limits.

Does that make sense?

best regards,
0--gg-

-- 
_($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                               /\_¯/(q    /
----------------------------  \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About