GC protection for on-stack objects
==================================

FIXME: obsolete


About
-----

This document describes GC protection for on-stack objects safe against an
irregular stack layout such as stack-smashing protection performs.


The Problem
-----------

Working on the previous stack protection strategy, following problem
occurs.(the explanation is based on
http://lists.sourceforge.jp/pipermail/anthy-dev/2005-August/002272.html[Anthy-dev 2273]
by Jun Inoue, and assumes that the stack grows downward).

Take a look in following code fragment.

[C]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{
    ...
    exp = "(number->string (* 32 1024))";
    {
        ScmObj stack_start;
        ScmObj str_port;
        ScmObj obj;
    
        scm_gc_protect_stack(&stack_start);
    
        str_port = scm_make_string_port(exp);
        obj = scm_read(str_port);
        obj = SCM_EVAL(obj, SCM_INTERACTION_ENV);
    
        scm_gc_unprotect_stack(stack_start);
    }

    return SCM_STRING_STR(obj);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The previous strategy assumes that `stack_start` is certainly located at lower
than `str_port` and `obj` to cover them on the mark-and-sweep stage. But the
actual layout breaks the assumption as follows.

At the breakpoint immediately before `scm_gc_protect_stack()` of the code
compiled with gcc4 ((GCC) 4.0.1 20050617 (prerelease) (Debian 4.0.0-10)
(IA32)), actual stack layout had been reported as follows.

----------------------------------------------------------------
(gdb) p &stack_start
$6 = (ScmObj *) 0xbfffe7d8
(gdb) p &str_port
$7 = (ScmObj *) 0xbfffe7dc
(gdb) p $sp
$12 = (void *) 0xbfffe7d0
----------------------------------------------------------------

This result indicates the storage location order inversion:

  expected: %esp < &str_port < &stack_start
  actual:   %esp < &stack_start < &str_port

So `str_port` is not protected in the case.


Solution
--------

  - Allocate the `stack_start` dummy variable in a separated frame

  - Ensure that a code fragment that its stack must be protected is certainly
    executed on the stack grown over the frame containing `stack_start`

To accomplish it, a series of macros which turns a function into
stack-protected. See following steps to know how to use it.

1) Split the code fragment off into a function. No stack protection handling is
needed here.

[C]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static const char *
eval_str(const char *exp)
{
    ScmObj str_port;
    ScmObj obj;

    str_port = scm_make_string_port(exp);
    obj = scm_read(str_port);
    obj = SCM_EVAL(obj, SCM_INTERACTION_ENV);
    return SCM_STRING_STR(obj);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


2) Call the function prepared in 1) with the macro `SCM_GC_PROTECTED_CALL()` as
follows. The macro handles all of the GC protection issues. Once the function
returned, the stack protection is disabled again. To protect another function
call, apply the macro to the call.

Use `SCM_GC_PROTECTED_CALL_VOID()` instead if the calee function returns
`void`.

[C]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{
    const char *exp, *ret;
    ...
    exp = "(number->string (* 32 1024))";
    SCM_GC_PROTECTED_CALL(ret, const char *, eval_str, (exp));
    return ret;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
