]> git.wincent.com - wikitext.git/commit
Call Data_Wrap_Struct on ary structs
authorWincent Colaiuta <win@wincent.com>
Sat, 23 Feb 2008 14:55:43 +0000 (15:55 +0100)
committerWincent Colaiuta <win@wincent.com>
Sat, 23 Feb 2008 14:55:43 +0000 (15:55 +0100)
commit7f506d3b6a3d6e1b6b9c37d4b5fbf540e32160ae
treeab23e2c9b2c4afba8665eb173be4d9ff9ff27b75
parent840b62d90846d3ad7f0df35170a7ba10f77dac35
Call Data_Wrap_Struct on ary structs

There is a minuscule overhead introduced by this commit (the allocation
of three Ruby objects per parse, which in turn means three more objects
involved in Ruby's mark-and-sweep Garbage Collection scheme) which
brings with it a robustness enhancement: if we exit the parse method
irregularly (by an exception) the three ary structs will be properly
freed rather than leaking.

This was never a big deal as the structs themselves were typically
small (defaulting to 64 entries each) and irregular exits shouldn't
really ever happen in practice (the only times when we would exit via an
exception are when we run out of memory, in which case we're totally
hosed anyway and process termination is just around the corner, and when
we have invalidly encoded UTF-8 input; this latter scenario may be an
issue if an attacker specifically tries to consume resources by
repeatedly feeding in hand-crafted bad input, but I don't know whether
such an attack would be practically feasible).

The key piece of the puzzle is that the object returned by
Data_Wrap_Struct must be locatable on the C stack in order for Ruby to
refrain from collecting it prematurely. Without the volatile keyword the
compiler will see that the pointer is initialized and then never used
again and is free to optimize it away to nothing, which then allows Ruby
to go ahead and free the structure before its time. The volatile keyword
here prevents this optimization, at least in GCC, and is apparently an
"accepted hack" that is used in the Ruby source itself.

Signed-off-by: Wincent Colaiuta <win@wincent.com>
ext/parser.c