MOO-cows Mailing List Archive

[Prev][Next][Index][Thread]

Calling verbs from built-in functions



> I have indeed studied on create() which does the following:
>	call_verb(oid, "initialize", args, 0);
> I found it an easy hack, and after some testing it did work.

It's not that this call is wrong, it's that you're wrong in assuming that it's
this call that makes the server actually invoke the "initialize" verb.  Take a
look further at bf_create() and note that it returns
	make_call_pack(2, data)
Note also that it tests the value of the C argument `next' in deciding what to
do.

The point is that built-in function implementations which call verbs are
actually called *twice*.  The first time, they do some work, call `call_verb()'
to tell the virtual machine which verb to call, and then return
`make_call_pack()'.  The virtual machine notices the `make_call_pack()' result
and saves away the arguments to `make_call_pack()' for later use.  It *then*
calls the verb mentioned in `call_verb()'.  When that verb returns, the virtual
machine calls the built-in function implementation *again*, passing the first
argument to `make_call_pack()' as the argument `next', the second argument
to `make_call_pack()' as the argument `vdata', and the result of the verb call
as the argument `arglist'.  The built-in function can then do as it likes,
either returning normally this time, or raising an error, or even calling
another verb; in all cases, its intent is communicated to the virtual machine
through the kind of `package' it returns.

What your code does is to mix up its signals.  On the one hand, it called
`call_verb()' to set things up for a verb call; on the other hand, it returned
`no_var_pack()' (which is equivalent to `make_var_pack(zero)').  So part of the
virtual machine is set up to call a new verb while the rest is taking this zero
you returned and pushing it on the stack.  The virtual machine, in executing
the code for that verb, will never notice that there's this extra value on the
stack.  The problem is that the MOO-code compiler actually keeps very close
track of exactly how big a stack is necessary, and the virtual machine only
allocates precisely enough, with no extra.  That extra value you got pushed on
is taking up space that was supposed to be used by the verb's code.  The result
is that the verb may very well try to use more stack slots than exist, thereby
overwriting some random piece of memory.

In your testing, you got lucky and that overwriting didn't cause a crash and
(apparently, but not certainly) didn't destroy any other useful data.  It could
have done either or both.  *That's* why I advised people not to use your code.

I've Cc'd MOO-Cows on this response because this is a tricky part of the way
the server is implemented and it's not explicitly documented anywhere, so lots
of folks are likely to get it wrong.  Perhaps, with this message, more folks
will either get it right or know enough to stay away from the area completely.

	Pavel


Follow-Ups:

Home | Subject Index | Thread Index