# GC protection for on-stack objects

FIXME: obsolete

## 1. About

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

## 2. The Problem

Working on the previous stack protection strategy, following problem occurs.(the explanation is based on Anthy-dev 2273 by Jun Inoue, and assumes that the stack grows downward).

Take a look in following code fragment.

    {
        ...
        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.

## 3. 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.

    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`.

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