fail() sentinel fallback does not cover ok_new==true with no obj/err #53

Open
opened 2026-08-16 06:28:57 +02:00 by michael · 3 comments
Owner

Problem

fail()'s local sentinel fallback does not fully guarantee a
daw_error/v1-shaped return value.

local ok_new, obj, err = pcall(daw_error.new, _NAME, code, message, opts)
if not ok_new then
  return { schema = "daw_error/v1", id = "daw-error-facility-unavailable", ... }
end
return obj or err

If pcall succeeds (ok_new == true) but daw_error.new() returns
neither obj nor err (e.g. nil, nil), fail() returns nil.
A caller then does return nil, nil, silently violating the "always
return a daw_error/v1 on failure" rule this sentinel path exists to
protect against.

Found while reviewing the daw_i18n/v1 migration of crypto/hash.lua
(DAW/daw-lua-common#48), but the same fail() shape exists in every
file migrated so far (base64.lua, config_parser.lua, crypto/hash.lua)
and likely in further not-yet-migrated files using the same pattern.

Scope

  • Audit all local fail() implementations using this pattern
  • Close the ok_new == true but obj == nil and err == nil gap,
    e.g. falling through to the same sentinel object instead of obj or err
  • Do not change behavior for the already-covered ok_new == false
    (pcall crash) case

Acceptance criteria

  • All affected fail() implementations identified
  • Gap closed consistently across all of them
  • fragjan code . and make test (5.1 and 5.4) pass

DAW/daw-lua-common#48

## Problem `fail()`'s local sentinel fallback does not fully guarantee a daw_error/v1-shaped return value. ```lua local ok_new, obj, err = pcall(daw_error.new, _NAME, code, message, opts) if not ok_new then return { schema = "daw_error/v1", id = "daw-error-facility-unavailable", ... } end return obj or err ``` If `pcall` succeeds (`ok_new == true`) but `daw_error.new()` returns neither `obj` nor `err` (e.g. `nil, nil`), `fail()` returns `nil`. A caller then does `return nil, nil`, silently violating the "always return a daw_error/v1 on failure" rule this sentinel path exists to protect against. Found while reviewing the daw_i18n/v1 migration of crypto/hash.lua (DAW/daw-lua-common#48), but the same `fail()` shape exists in every file migrated so far (base64.lua, config_parser.lua, crypto/hash.lua) and likely in further not-yet-migrated files using the same pattern. ## Scope - Audit all local `fail()` implementations using this pattern - Close the `ok_new == true` but `obj == nil` and `err == nil` gap, e.g. falling through to the same sentinel object instead of `obj or err` - Do not change behavior for the already-covered ok_new == false (pcall crash) case ## Acceptance criteria - [ ] All affected `fail()` implementations identified - [ ] Gap closed consistently across all of them - [ ] fragjan code . and make test (5.1 and 5.4) pass ## Related DAW/daw-lua-common#48
Author
Owner

Also affects crypto/init.lua (same fail()/missing() fallback shape as hash.lua and hmac.lua). No separate issue -- covered by this one.

Also affects crypto/init.lua (same fail()/missing() fallback shape as hash.lua and hmac.lua). No separate issue -- covered by this one.
Author
Owner

Also affects decimal/util.lua, decimal/init.lua, decimal/convert.lua, decimal/compare.lua, decimal/arith.lua (same fail()/no_util()/missing() fallback shape). No separate issue -- covered by this one.

Also affects decimal/util.lua, decimal/init.lua, decimal/convert.lua, decimal/compare.lua, decimal/arith.lua (same fail()/no_util()/missing() fallback shape). No separate issue -- covered by this one.
Author
Owner

Also affects fs/dir.lua's err() (same fail()-shape). No separate issue -- covered by this one.

Also affects fs/dir.lua's err() (same fail()-shape). No separate issue -- covered by this one.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
DAW/daw-lua-common#53
No description provided.