diff --git a/maul/files/docs/internals/maul-conventions.md b/maul/files/docs/internals/maul-conventions.md index 7144b88..302ed8a 100644 --- a/maul/files/docs/internals/maul-conventions.md +++ b/maul/files/docs/internals/maul-conventions.md @@ -95,6 +95,7 @@ The libraries are one product family: a program may link several of them, and a - Getters that cannot fail take ids and return values. Out-parameters end in `Out`. - Strings cross the API as UTF-8 with an explicit byte length, never as NUL-terminated text alone, so text from hostile sources is never measured by searching for a terminator. - A library's root object is a typed opaque pointer. Every object a root owns is named by a typed value id, a 1-based slot index (0 is null) and a generation, one struct per kind. A stale id is refused with a typed result, never dereferenced, which costs one array read and a compare. Platform handles are never identities. +- State a caller holds is checked by how a caller can get it wrong. Opaque state that only the library writes is checked by its cookie, and its ABI version where it records one, and by every index, slot and length in it being in bounds, so that no bit pattern makes a call read outside the state or the data it names; a forged one is outside the contract, and its fields' consistency with each other is not checked again. A value struct with documented fields that a call takes back from the caller, which the caller may copy and assign, carries no raw pointer and size into the library's data: it names the object or data it came from and an index, checked on each call, so that a field copied from another value cannot reach memory outside what it names. A struct the library only fills in for the caller, such as a label it points at, may point into its data. Caller memory a call keeps "as checked", such as a bound message, must stay unchanged as documented, and whatever it becomes, a later call reads only within the extents it recorded. - An operation that finishes later is a request: it returns its status at once and, accepted, a typed request id that exactly one completion record answers, in the owner's notification queue, with a typed outcome. Callbacks that deliver completions fire at unsafe points and leave re-entrancy rules to every caller; a queue does not. ## Floating point and determinism