From 6a06af19af6cfe95e57377c982167ac78e38f426 Mon Sep 17 00:00:00 2001 From: Sirac Ozmen Date: Wed, 4 Nov 2026 04:36:01 +0300 Subject: [PATCH 1/2] docs(maul): let a caller-built input point where its builder chose maul-ui's audit under #119 found muiAccessUpdate, which the library fills but the header also documents as input a host builds. To the call that takes it, its pointers are caller memory, so it is not a breach; the rule now says so, and that such a call still checks every count, offset and index it can. --- maul/files/docs/internals/maul-conventions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maul/files/docs/internals/maul-conventions.md b/maul/files/docs/internals/maul-conventions.md index 302ed8a..ed6594e 100644 --- a/maul/files/docs/internals/maul-conventions.md +++ b/maul/files/docs/internals/maul-conventions.md @@ -95,7 +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. +- 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. So may one the header also documents as input a caller builds, such as an accessibility update: to the call that takes it, its pointers and counts are the caller's to keep valid, as with any buffer argument, and the call checks every count, offset and index it can without trusting them. 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 From 2107c76d7d3c4279e03d46141f67f7f91c17936a Mon Sep 17 00:00:00 2001 From: Sirac Ozmen Date: Wed, 4 Nov 2026 04:36:53 +0300 Subject: [PATCH 2/2] docs(maul): tie the caller-built exception to how the call reads --- maul/files/docs/internals/maul-conventions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maul/files/docs/internals/maul-conventions.md b/maul/files/docs/internals/maul-conventions.md index ed6594e..80f34b2 100644 --- a/maul/files/docs/internals/maul-conventions.md +++ b/maul/files/docs/internals/maul-conventions.md @@ -95,7 +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. So may one the header also documents as input a caller builds, such as an accessibility update: to the call that takes it, its pointers and counts are the caller's to keep valid, as with any buffer argument, and the call checks every count, offset and index it can without trusting them. 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. +- 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. So may one the header also documents as input a caller builds, such as an accessibility update, provided the call that takes it reads through it as through any buffer argument: only within the ranges its own pointers and counts state, checking every count, offset and index it reads there as untrusted, and relying on nothing the library validated earlier. Its pointers and counts are then the caller's to keep valid. 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