Fix three real bugs the second ygg-verify pass found
- koffi's `_Out_` sugar still counts toward the call's declared arity in this
version (an arity check rejected the shorter call); pass `null` at each such
slot, since the value comes back through the named field on the result
object regardless of what was passed.
- The negative-grep test read `dist-test/src/...`, which does not exist:
`__dirname` at runtime is `dist-test/test`, and only compiled output is
mirrored there, so the original source is two levels up in `src/`, not one.
- Two generated Odin test roots shared one hardcoded key id
("odin-root-1"), so trust negative (c) had the trust policy's root looked
up successfully under the signer's own id and failed on signature mismatch
instead of "not trusted" — proving the wrong rule. Each generated root now
gets a distinct key id.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
a44505fab8
commit
92dc3a74d6
3 changed files with 16 additions and 7 deletions
|
|
@ -217,22 +217,26 @@ function loadBindings(): NativeBindings {
|
|||
const { promisify } = require("node:util") as typeof import("node:util");
|
||||
const nextEventAsync = promisify(nextEvent.async) as NativeBindings["nextEventAsync"];
|
||||
|
||||
// Every `_Out_` parameter still occupies a call-site slot in this koffi
|
||||
// version (an arity check rejects a shorter call); its value is written
|
||||
// back through the named field on the returned object regardless of what
|
||||
// was passed here, so `null` is a safe placeholder at each such slot.
|
||||
bindingsCache = {
|
||||
runtimeOpen: (appName) => runtimeOpen(appName),
|
||||
runtimeOpen: (appName) => runtimeOpen(appName, null),
|
||||
runtimeClose: (runtime) => runtimeClose(runtime),
|
||||
listenerOpen: (runtime, host, port, pkcs12, pkcs12Length, password) =>
|
||||
listenerOpen(runtime, host, port, pkcs12, pkcs12Length, password),
|
||||
listenerOpen(runtime, host, port, pkcs12, pkcs12Length, password, null, null),
|
||||
listenerClose: (runtime, listenerId) => listenerClose(runtime, listenerId),
|
||||
connectionOpen: (runtime, host, port) => connectionOpen(runtime, host, port),
|
||||
connectionOpen: (runtime, host, port) => connectionOpen(runtime, host, port, null),
|
||||
connectionCertificateComplete: (runtime, connectionId, accept) =>
|
||||
connectionCertificateComplete(runtime, connectionId, accept),
|
||||
connectionShutdown: (runtime, connectionId, code) => connectionShutdown(runtime, connectionId, code),
|
||||
streamOpen: (runtime, connectionId, kind) => streamOpen(runtime, connectionId, kind),
|
||||
streamOpen: (runtime, connectionId, kind) => streamOpen(runtime, connectionId, kind, null),
|
||||
streamSendFrame: (runtime, streamId, encodedFrame, length, fin) =>
|
||||
streamSendFrame(runtime, streamId, encodedFrame, length, fin),
|
||||
streamShutdown: (runtime, streamId, code) => streamShutdown(runtime, streamId, code),
|
||||
nextEventAsync: (runtime, timeoutMs, payload, payloadCapacity) =>
|
||||
nextEventAsync(runtime, timeoutMs, payload, payloadCapacity) as Promise<KoffiOutResult<NativeEventStruct>>,
|
||||
nextEventAsync(runtime, timeoutMs, null, payload, payloadCapacity, null) as Promise<KoffiOutResult<NativeEventStruct>>,
|
||||
lastError: (runtime, destination, capacity) => lastError(runtime, destination, capacity),
|
||||
lastStatus: (runtime) => lastStatus(runtime),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -245,13 +245,16 @@ function base64UrlToBase64(value: string): string {
|
|||
return base64;
|
||||
}
|
||||
|
||||
let odinRootSequence = 0;
|
||||
|
||||
function generateOdinRoot(): { privateKey: KeyObject; publicKey: CultMeshP256PublicKey } {
|
||||
const { publicKey, privateKey } = generateKeyPairSync("ec", { namedCurve: "prime256v1" });
|
||||
const jwk = publicKey.export({ format: "jwk" }) as { x: string; y: string };
|
||||
odinRootSequence += 1;
|
||||
return {
|
||||
privateKey,
|
||||
publicKey: {
|
||||
keyId: "odin-root-1",
|
||||
keyId: `odin-root-${odinRootSequence}`,
|
||||
x: base64UrlToBase64(jwk.x),
|
||||
y: base64UrlToBase64(jwk.y),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -137,7 +137,9 @@ test("a full loopback connection delivers one raw frame end to end", async (t) =
|
|||
});
|
||||
|
||||
test("negative grep: no koffi callbacks, .async only on nextEvent", () => {
|
||||
const source = readFileSync(join(__dirname, "..", "src", "realtime-quic-native.ts"), "utf8");
|
||||
// __dirname at runtime is dist-test/test; the source lives two levels up,
|
||||
// in src/, since only .js output is mirrored under dist-test.
|
||||
const source = readFileSync(join(__dirname, "..", "..", "src", "realtime-quic-native.ts"), "utf8");
|
||||
const asyncUses = [...source.matchAll(/\.async\(/g)];
|
||||
assert.ok(asyncUses.length > 0, "expected at least one .async( use for nextEvent");
|
||||
for (const match of asyncUses) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue