Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ jobs:
version: v2.1.0
args: false # Will be run as part of `make check`

- name: Install lua-language-server
run: |
curl -sL "https://github.com/LuaLS/lua-language-server/releases/download/$LUALS/lua-language-server-$LUALS-linux-x64.tar.gz" \
| tar -xz -C "$RUNNER_TEMP"
echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
env:
LUALS: 3.19.0

- name: Check
run: make check

Expand Down
40 changes: 37 additions & 3 deletions .luarc-typecheck.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,42 @@
{
"runtime": { "version": "LuaJIT" },
"runtime": {
"version": "LuaJIT",
"special": {},
"plugin": "",
"pluginArgs": []
},
"workspace": {
"useGitIgnore": false,
"library": ["vendor"],
"ignoreDir": [".claude", ".git", ".idea", ".venv", "build", "dist", "node_modules", "vendor"]
"library": [
"vendor"
],
"ignoreDir": [
".claude",
".git",
".idea",
".install",
".lua",
".luarocks",
".venv",
"build",
"dist",
"node_modules",
"vendor"
],
"maxPreload": 5000,
"preloadFileSize": 500
},
"diagnostics": {
"enable": true,
"disable": [],
"severity": {},
"globals": [],
"globalsRegex": [],
"neededFileStatus": {},
"groupFileStatus": {},
"groupSeverity": {},
"enableScheme": [
"file"
]
}
}
9 changes: 5 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,10 @@ lint:
# luacheck -- duplicate or undefined `@alias`, return counts that disagree with
# `@return`, fields missing from a `@class` -- so it is a separate target.
#
# Deliberately NOT part of `check`: a handful of type-narrowing and
# deliberate-bad-argument diagnostics remain, and turning CI red on those is a
# separate decision from making the check runnable.
# Part of `check`, so CI enforces it. The type-narrowing and
# deliberate-bad-argument findings that held it out are resolved: the narrowing
# ones were real defects, and the bad-argument ones are negative tests carrying
# a scoped `@diagnostic` bypass.
#
# Checks the whole repo, not just src/: an editor's workspace is the repo, and
# @alias resolves workspace-wide, so a narrower scope gives different findings
Expand All @@ -184,7 +185,7 @@ typecheck:
fi

.PHONY: check
check: format-check lint
check: format-check lint typecheck
@echo "Code quality checks complete."

# Clean generated files
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/aes_gcm.lua
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ local RCON = {
--- Initialize a 4-element AES word with zeros
--- @return AESWord word Initialized word
local function create_aes_word()
--- @type AESState
--- @type AESWord
return { 0, 0, 0, 0 }
end

Expand Down
2 changes: 2 additions & 0 deletions src/crypto/ed25519.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1203,9 +1203,11 @@ function ed25519.selftest()
name = "verify returns false for non-string arguments",
test = function()
local v = test_vectors[3]
--- @diagnostic disable: param-type-mismatch -- the wrong types are the test
assert(ed25519.verify(nil, v.message, v.signature) == false, "nil public key must be rejected")
assert(ed25519.verify(v.public_key, nil, v.signature) == false, "nil message must be rejected")
assert(ed25519.verify(v.public_key, v.message, 42) == false, "non-string signature must be rejected")
--- @diagnostic enable: param-type-mismatch
end,
},
}
Expand Down
12 changes: 8 additions & 4 deletions src/crypto/srp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,15 @@ local function resolve_group(group)
local N = bignum.from_hex(group.N)
assert(not bignum.is_zero(N), "SRP: group modulus N must be non-zero")

-- Read into a local because narrowing applies to locals, not table fields:
-- `type(group.g)` does not tell the checker anything about `group.g`.
local g_spec = group.g
local g
if type(group.g) == "number" then
g = bignum.from_number(group.g)
if type(g_spec) == "number" then
g = bignum.from_number(g_spec)
else
assert(type(group.g) == "string", "SRP: group.g must be a number or a hex string")
g = bignum.from_hex(group.g)
assert(type(g_spec) == "string", "SRP: group.g must be a number or a hex string")
g = bignum.from_hex(g_spec)
end
assert(not bignum.is_zero(g), "SRP: group generator g must be non-zero")

Expand Down Expand Up @@ -790,6 +793,7 @@ function srp.selftest()
end)

check("verify rejects a non-string M2", function()
--- @diagnostic disable-next-line: param-type-mismatch -- the wrong type is the test
return reference_session:verify(nil) == false
end)

Expand Down
Loading