diff --git a/.eslint/rules/file-suffix.js b/.eslint/rules/file-suffix.js index 912dff3eda..2713c67af4 100644 --- a/.eslint/rules/file-suffix.js +++ b/.eslint/rules/file-suffix.js @@ -260,7 +260,6 @@ const STD_PACKAGES = new Set([ 'pify', 'pino', 'pngjs', - 'protobufjs', 'qrcode-generator', 'react', 'react-intl', diff --git a/ACKNOWLEDGMENTS.md b/ACKNOWLEDGMENTS.md index 1b9ce13b6d..74749a6448 100644 --- a/ACKNOWLEDGMENTS.md +++ b/ACKNOWLEDGMENTS.md @@ -4772,48 +4772,6 @@ Signal Desktop makes use of the following open source projects. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -## protobufjs - - This license applies to all parts of protobuf.js except those files - either explicitly including or referencing a different license or - located in a directory containing a different LICENSE file. - - --- - - Copyright (c) 2016, Daniel Wirtz All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of its author, nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - --- - - Code generated by the command line utilities is owned by the owner - of the input file used when generating it. This code is not - standalone and requires a support library to be linked with it. This - support library is itself covered by the above license. - ## proxy-agent (The MIT License) diff --git a/package.json b/package.json index d771c93e06..b3b3fc3b58 100644 --- a/package.json +++ b/package.json @@ -193,7 +193,6 @@ "parsecurrency": "1.1.1", "pify": "3.0.0", "pino": "9.8.0", - "protobufjs": "7.3.2", "proxy-agent": "6.4.0", "qrcode-generator": "1.4.4", "radix-ui": "1.4.2", @@ -414,8 +413,7 @@ "ignoredBuiltDependencies": [ "core-js", "electron-winstaller", - "es5-ext", - "protobufjs" + "es5-ext" ] }, "engines": { @@ -699,8 +697,6 @@ "!node_modules/@react-stately/**", "!node_modules/@popperjs/**", "!node_modules/@internationalized/**", - "!node_modules/protobufjs/dist/**", - "node_modules/protobufjs/dist/minimal/**", "!**/node_modules/react-dom/*/*.development.js", "!node_modules/mp4box/**", "node_modules/mp4box/package.json", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4622a83432..ae6f9f214d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -305,9 +305,6 @@ importers: pino: specifier: 9.8.0 version: 9.8.0 - protobufjs: - specifier: 7.3.2 - version: 7.3.2 proxy-agent: specifier: 6.4.0 version: 6.4.0 @@ -2138,36 +2135,6 @@ packages: '@popperjs/core@2.11.8': resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} - '@protobufjs/aspromise@1.1.2': - resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} - - '@protobufjs/base64@1.1.2': - resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} - - '@protobufjs/codegen@2.0.4': - resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} - - '@protobufjs/eventemitter@1.1.0': - resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} - - '@protobufjs/fetch@1.1.0': - resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} - - '@protobufjs/float@1.0.2': - resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} - - '@protobufjs/inquire@1.1.0': - resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} - - '@protobufjs/path@1.1.2': - resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} - - '@protobufjs/pool@1.1.0': - resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} - - '@protobufjs/utf8@1.1.0': - resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - '@radix-ui/number@1.1.1': resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} @@ -7842,9 +7809,6 @@ packages: resolution: {integrity: sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==} engines: {node: '>= 0.6.0'} - long@5.2.3: - resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} - longest-streak@2.0.4: resolution: {integrity: sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==} @@ -9003,10 +8967,6 @@ packages: prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - protobufjs@7.3.2: - resolution: {integrity: sha512-RXyHaACeqXeqAKGLDl68rQKbmObRsTIn4TYVUUug1KfS47YWCo5MacGITEryugIgZqORCvJWEk4l449POg5Txg==} - engines: {node: '>=12.0.0'} - proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -12314,29 +12274,6 @@ snapshots: '@popperjs/core@2.11.8': {} - '@protobufjs/aspromise@1.1.2': {} - - '@protobufjs/base64@1.1.2': {} - - '@protobufjs/codegen@2.0.4': {} - - '@protobufjs/eventemitter@1.1.0': {} - - '@protobufjs/fetch@1.1.0': - dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/inquire': 1.1.0 - - '@protobufjs/float@1.0.2': {} - - '@protobufjs/inquire@1.1.0': {} - - '@protobufjs/path@1.1.2': {} - - '@protobufjs/pool@1.1.0': {} - - '@protobufjs/utf8@1.1.0': {} - '@radix-ui/number@1.1.1': {} '@radix-ui/primitive@1.1.2': {} @@ -19580,8 +19517,6 @@ snapshots: loglevel@1.9.2: {} - long@5.2.3: {} - longest-streak@2.0.4: {} loose-envify@1.4.0: @@ -20757,21 +20692,6 @@ snapshots: object-assign: 4.1.1 react-is: 16.13.1 - protobufjs@7.3.2: - dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/base64': 1.1.2 - '@protobufjs/codegen': 2.0.4 - '@protobufjs/eventemitter': 1.1.0 - '@protobufjs/fetch': 1.1.0 - '@protobufjs/float': 1.0.2 - '@protobufjs/inquire': 1.1.0 - '@protobufjs/path': 1.1.2 - '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.0 - '@types/node': 20.17.6 - long: 5.2.3 - proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 diff --git a/ts/sql/cleanDataForIpc.std.ts b/ts/sql/cleanDataForIpc.std.ts index 30f702680d..9f29675352 100644 --- a/ts/sql/cleanDataForIpc.std.ts +++ b/ts/sql/cleanDataForIpc.std.ts @@ -18,7 +18,7 @@ const log = createLogger('cleanDataForIpc'); * * This cleans the data so it's roughly JSON-serializable, though it does not handle * every case. You can see the expected behavior in the tests. Notably, we try to convert - * protobufjs numbers to JavaScript numbers, and we don't touch ArrayBuffers. + * bigint numbers to plain numbers, and we don't touch ArrayBuffers. * * [0]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm */ diff --git a/ts/test-node/util/DelimitedStream_test.node.ts b/ts/test-node/util/DelimitedStream_test.node.ts index 1e24d28c73..23e787a2ad 100644 --- a/ts/test-node/util/DelimitedStream_test.node.ts +++ b/ts/test-node/util/DelimitedStream_test.node.ts @@ -4,9 +4,9 @@ import { assert } from 'chai'; import { Readable, Writable } from 'node:stream'; import { pipeline } from 'node:stream/promises'; -import { BufferWriter } from 'protobufjs'; import { DelimitedStream } from '../../util/DelimitedStream.node.js'; +import { encodeDelimited } from '../../util/encodeDelimited.std.js'; describe('DelimitedStream', () => { function collect(out: Array): Writable { @@ -46,39 +46,43 @@ describe('DelimitedStream', () => { } it('should parse single-byte delimited data', async () => { - const w = new BufferWriter(); - w.string('a'); - w.string('bc'); + const data = Buffer.concat([ + ...encodeDelimited(Buffer.from('a')), + ...encodeDelimited(Buffer.from('bc')), + ]); - await strideTest(w.finish(), ['a', 'bc']); + await strideTest(data, ['a', 'bc']); }); it('should parse two-byte delimited data', async () => { - const w = new BufferWriter(); - w.string('a'.repeat(129)); - w.string('b'.repeat(154)); + const data = Buffer.concat([ + ...encodeDelimited(Buffer.from('a'.repeat(129))), + ...encodeDelimited(Buffer.from('b'.repeat(154))), + ]); - await strideTest(w.finish(), ['a'.repeat(129), 'b'.repeat(154)]); + await strideTest(data, ['a'.repeat(129), 'b'.repeat(154)]); }); it('should parse three-byte delimited data', async () => { - const w = new BufferWriter(); - w.string('a'.repeat(32000)); - w.string('b'.repeat(32500)); + const data = Buffer.concat([ + ...encodeDelimited(Buffer.from('a'.repeat(32000))), + ...encodeDelimited(Buffer.from('b'.repeat(32500))), + ]); - await strideTest(w.finish(), ['a'.repeat(32000), 'b'.repeat(32500)]); + await strideTest(data, ['a'.repeat(32000), 'b'.repeat(32500)]); }); it('should parse mixed delimited data', async () => { - const w = new BufferWriter(); - w.string('a'); - w.string('b'.repeat(129)); - w.string('c'.repeat(32000)); - w.string('d'.repeat(32)); - w.string('e'.repeat(415)); - w.string('f'.repeat(33321)); + const data = Buffer.concat([ + ...encodeDelimited(Buffer.from('a')), + ...encodeDelimited(Buffer.from('b'.repeat(129))), + ...encodeDelimited(Buffer.from('c'.repeat(32000))), + ...encodeDelimited(Buffer.from('d'.repeat(32))), + ...encodeDelimited(Buffer.from('e'.repeat(415))), + ...encodeDelimited(Buffer.from('f'.repeat(33321))), + ]); - await strideTest(w.finish(), [ + await strideTest(data, [ 'a', 'b'.repeat(129), 'c'.repeat(32000), @@ -89,13 +93,14 @@ describe('DelimitedStream', () => { }); it('should error on incomplete prefix', async () => { - const w = new BufferWriter(); - w.string('a'.repeat(32000)); + const data = Buffer.concat([ + ...encodeDelimited(Buffer.from('a'.repeat(32000))), + ]); const out = new Array(); await assert.isRejected( pipeline( - Readable.from(w.finish().subarray(0, 1)), + Readable.from(data.subarray(0, 1)), new DelimitedStream(), collect(out) ), @@ -104,13 +109,14 @@ describe('DelimitedStream', () => { }); it('should error on incomplete data', async () => { - const w = new BufferWriter(); - w.string('a'.repeat(32000)); + const data = Buffer.concat([ + ...encodeDelimited(Buffer.from('a'.repeat(32000))), + ]); const out = new Array(); await assert.isRejected( pipeline( - Readable.from(w.finish().subarray(0, 10)), + Readable.from(data.subarray(0, 10)), new DelimitedStream(), collect(out) ), diff --git a/ts/util/inspectProtobufs.std.ts b/ts/util/inspectProtobufs.std.ts index dfe66bc31c..5172951d99 100644 --- a/ts/util/inspectProtobufs.std.ts +++ b/ts/util/inspectProtobufs.std.ts @@ -1,10 +1,6 @@ // Copyright 2023 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import protobufjs from 'protobufjs'; - -const { Reader } = protobufjs; - type MessageWithUnknownFields = { $unknown?: ReadonlyArray; }; @@ -41,8 +37,17 @@ export function inspectUnknownFieldTags( message.$unknown?.map(field => { // https://protobuf.dev/programming-guides/encoding/ // The first byte of a field is a varint encoding the tag bit-shifted << 3 + let tag = 0; + for (const [i, b] of field.entries()) { + // eslint-disable-next-line no-bitwise + tag |= (b & 0x7f) << (7 * i); + // eslint-disable-next-line no-bitwise + if ((b & 0x80) === 0) { + break; + } + } // eslint-disable-next-line no-bitwise - return new Reader(field).uint32() >>> 3; + return tag >>> 3; }) ?? [] ); } diff --git a/ts/util/lint/exceptions.json b/ts/util/lint/exceptions.json index 5e2bb73b2b..944ef11037 100644 --- a/ts/util/lint/exceptions.json +++ b/ts/util/lint/exceptions.json @@ -708,51 +708,6 @@ "reasonCategory": "testCode", "updated": "2024-06-24T19:19:28.335Z" }, - { - "rule": "eval", - "path": "node_modules/protobufjs/dist/light/protobuf.js", - "line": " var mod = eval(\"quire\".replace(/^/,\"re\"))(moduleName); // eslint-disable-line no-eval", - "reasonCategory": "usageTrusted", - "updated": "2019-03-09T00:08:44.242Z", - "reasonDetail": "Eval is used here to produce and evaluate the expression 'require'" - }, - { - "rule": "eval", - "path": "node_modules/protobufjs/dist/light/protobuf.min.js", - "reasonCategory": "usageTrusted", - "updated": "2018-09-18T19:19:27.699Z", - "reasonDetail": "Hard-coded string" - }, - { - "rule": "eval", - "path": "node_modules/protobufjs/dist/minimal/protobuf.js", - "line": " var mod = eval(\"quire\".replace(/^/,\"re\"))(moduleName); // eslint-disable-line no-eval", - "reasonCategory": "usageTrusted", - "updated": "2019-03-09T00:08:44.242Z", - "reasonDetail": "Eval is used here to produce and evaluate the expression 'require'" - }, - { - "rule": "eval", - "path": "node_modules/protobufjs/dist/minimal/protobuf.min.js", - "reasonCategory": "falseMatch", - "updated": "2018-09-18T19:19:27.699Z", - "reasonDetail": "Inside of regular expression" - }, - { - "rule": "eval", - "path": "node_modules/protobufjs/dist/protobuf.js", - "line": " var mod = eval(\"quire\".replace(/^/,\"re\"))(moduleName); // eslint-disable-line no-eval", - "reasonCategory": "usageTrusted", - "updated": "2019-03-09T00:08:44.242Z", - "reasonDetail": "Eval is used here to produce and evaluate the expression 'require'" - }, - { - "rule": "eval", - "path": "node_modules/protobufjs/dist/protobuf.min.js", - "reasonCategory": "usageTrusted", - "updated": "2018-09-18T19:19:27.699Z", - "reasonDetail": "Hard-coded string" - }, { "rule": "DOM-document.write(", "path": "node_modules/qrcode-generator/sample.js", diff --git a/ts/util/lint/linter.node.ts b/ts/util/lint/linter.node.ts index 39196a7693..ba9d7d91f6 100644 --- a/ts/util/lint/linter.node.ts +++ b/ts/util/lint/linter.node.ts @@ -241,7 +241,6 @@ const excludedFilesRegexp = RegExp( '^node_modules/preserve/.+', '^node_modules/prettier/.+', '^node_modules/prop-types/.+', - '^node_modules/protobufjs/cli/.+', '^node_modules/ramda/.+', '^node_modules/rambda/.+', '^node_modules/react-devtools/.+',