diff --git a/ts/services/storageRecordOps.ts b/ts/services/storageRecordOps.ts index f38f8cb1e8..e9a006abf2 100644 --- a/ts/services/storageRecordOps.ts +++ b/ts/services/storageRecordOps.ts @@ -54,6 +54,7 @@ import { toTaggedPni, } from '../types/ServiceId'; import { normalizeAci } from '../util/normalizeAci'; +import { isAciString } from '../util/isAciString'; import * as Stickers from '../types/Stickers'; import type { StoryDistributionWithMembersType, @@ -997,6 +998,11 @@ export async function mergeContactRecord( return { hasConflict: false, shouldDrop: true, details: ['no uuid'] }; } + // Contacts should not have PNI as ACI + if (aci && !isAciString(aci)) { + return { hasConflict: false, shouldDrop: true, details: ['invalid aci'] }; + } + if ( window.storage.user.getOurServiceIdKind(serviceId) !== ServiceIdKind.Unknown ) { diff --git a/ts/textsecure/ContactsParser.ts b/ts/textsecure/ContactsParser.ts index 865c61766e..d2f323b44b 100644 --- a/ts/textsecure/ContactsParser.ts +++ b/ts/textsecure/ContactsParser.ts @@ -7,6 +7,7 @@ import protobuf from '../protobuf/wrap'; import { SignalService as Proto } from '../protobuf'; import { normalizeAci } from '../util/normalizeAci'; +import { isAciString } from '../util/isAciString'; import { DurationInSeconds } from '../util/durations'; import * as Errors from '../types/errors'; import * as log from '../logging/log'; @@ -115,33 +116,44 @@ export class ContactBuffer extends ParserBase< } public override next(): ModifiedContactDetails | undefined { - const proto = this.decodeDelimited(); - if (!proto) { - return undefined; + while (this.reader.pos < this.reader.len) { + const proto = this.decodeDelimited(); + if (!proto) { + return undefined; + } + + if (!proto.aci) { + return proto; + } + + const { verified } = proto; + + if ( + !isAciString(proto.aci) || + (verified?.destinationAci && !isAciString(verified.destinationAci)) + ) { + continue; + } + + return { + ...proto, + + verified: + verified && verified.destinationAci + ? { + ...verified, + + destinationAci: normalizeAci( + verified.destinationAci, + 'ContactBuffer.verified.destinationAci' + ), + } + : verified, + + aci: normalizeAci(proto.aci, 'ContactBuffer.aci'), + }; } - if (!proto.aci) { - return proto; - } - - const { verified } = proto; - - return { - ...proto, - - verified: - verified && verified.destinationAci - ? { - ...verified, - - destinationAci: normalizeAci( - verified.destinationAci, - 'ContactBuffer.verified.destinationAci' - ), - } - : verified, - - aci: normalizeAci(proto.aci, 'ContactBuffer.aci'), - }; + return undefined; } } diff --git a/ts/util/normalizeAci.ts b/ts/util/normalizeAci.ts index 280861a1ca..0ecc8d66a7 100644 --- a/ts/util/normalizeAci.ts +++ b/ts/util/normalizeAci.ts @@ -5,6 +5,7 @@ import type { AciString } from '../types/ServiceId'; import type { LoggerType } from '../types/Logging'; import * as log from '../logging/log'; import { isAciString } from './isAciString'; +import { strictAssert } from './assert'; export function normalizeAci( rawAci: string, @@ -28,6 +29,7 @@ export function normalizeAci( } const result = rawAci.toLowerCase(); + strictAssert(!result.startsWith('pni:'), 'ACI should not start with PNI:'); if (!isAciString(result)) { logger.warn(