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
12 changes: 11 additions & 1 deletion src/Signal/libsignal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,17 @@ function readVarint(buffer: Uint8Array, offset: number): { value: number; nextOf
}

shift += 7
if (shift > 35) {
// Reject once shift would reach 35 — NOT just exceed it. The 5
// valid byte shifts are 0, 7, 14, 21, 28. After processing byte 4
// (`shift` was 28), this increment makes `shift = 35`. With a
// `shift > 35` guard, byte 5 would still be read on the next loop
// iteration and `(byte & 0x7f) << 35` would silently fold into
Comment on lines +308 to +312
// `<< 3` because JS `<<` is modulo-32 on the right operand —
// producing a corrupt value that the outer `>>> 0` would happily
// accept as a valid uint32, neutralising the
// `extractIdentityFromPkmsg` field-3 (identityKey) parse on
// crafted pkmsg payloads.
if (shift >= 35) {
// Varint too long (max 5 bytes for 32-bit)
// This could indicate a malformed or malicious message
// Caller should log this condition at debug level
Expand Down
23 changes: 21 additions & 2 deletions src/Utils/multi-db-sqlite/schemas/msgstore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,19 @@ CREATE TABLE IF NOT EXISTS jid (
agent INTEGER,
device INTEGER,
type INTEGER,
raw_string TEXT
/* NOT NULL prevents two distinct failure modes —
(1) SQLite treats NULL as DISTINCT inside a UNIQUE index, so any
malformed insert path that produced NULL would silently create
duplicate rows that the jid_raw_string_idx was supposed to
prevent;
(2) selectJidIdByRaw filters by WHERE raw_string = ?, and SQL
NULL = NULL evaluates to UNKNOWN, so the row is never returned
— rowIdFor would then throw "failed to materialize jid row"
for every subsequent access.
CREATE TABLE IF NOT EXISTS is a no-op when the table exists, so
legacy databases keep the nullable column; new databases get the
constraint enforced. */
raw_string TEXT NOT NULL
);

CREATE UNIQUE INDEX IF NOT EXISTS jid_raw_string_idx ON jid (raw_string);
Expand All @@ -36,7 +48,14 @@ CREATE INDEX IF NOT EXISTS jid_user_server_idx ON jid (user, server);
CREATE TABLE IF NOT EXISTS jid_map (
lid_row_id INTEGER PRIMARY KEY NOT NULL,
jid_row_id INTEGER NOT NULL,
sort_id INTEGER
/* NOT NULL DEFAULT 0 so a row inserted without an explicit sort_id
can never end up as NULL. ORDER BY sort_id DESC ranks NULLs LAST
in SQLite which would silently demote a freshly-inserted-but-NULL
row below older ones — the opposite of the "last write wins"
intent. upsertMap always provides a real epoch-ms tick so the
default is just defensive against any future code path that
bypasses upsertMap. */
sort_id INTEGER NOT NULL DEFAULT 0
);

CREATE INDEX IF NOT EXISTS jid_map_jid_row_id_idx ON jid_map (jid_row_id);
Expand Down
2 changes: 1 addition & 1 deletion src/Voip/signaling/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const ACK_TIMEOUT_MS = 15_000
// version lazy-loaded `@whiskeysockets/baileys` as a peer dep. Inside the fork
// we ship as part of the same package, so static imports are cleaner and avoid
// the runtime `import()` ceremony.
import { proto } from '../../../WAProto/index'
import { proto } from '../../../WAProto/index.js'
import { encodeWAMessage, unpadRandomMax16 } from '../../Utils/generics'
import { parseAndInjectE2ESessions } from '../../Utils/signal'
import { encodeSignedDeviceIdentity } from '../../Utils/validate-connection'
Expand Down
Loading