nodejs-insta-private-api-mqt 1.3.73 → 1.3.74

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,325 +3,366 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BufferReader = exports.thriftReadToObject = exports.thriftRead = void 0;
4
4
  const thrift_1 = require("./thrift");
5
5
  const errors_1 = require("../errors");
6
+
7
+ /**
8
+ * Thrift Compact Protocol reader (subset) for MQTT-over-Thrift payloads.
9
+ * Fixes / improvements:
10
+ * - fixes infinite loop in thriftRead()
11
+ * - correct INT_64 list decoding (BigInt zigzag varint)
12
+ * - faster descriptor lookup via Map in thriftReadSingleLevel()
13
+ * - keeps existing INT_64 return shape: { int: BigInt, num: Number, safe?: boolean }
14
+ */
15
+
6
16
  function thriftRead(message) {
7
- const reader = new BufferReader(message);
8
- const messages = [];
9
- let context = '';
10
- const position = 0;
11
- while (position < message.length) {
12
- const type = reader.readField();
13
- if (type === thrift_1.ThriftTypes.STOP) {
14
- if (reader.stack.length === 0) {
15
- return messages;
16
- }
17
- reader.popStack();
18
- context = reader.stack.join('/');
19
- continue;
20
- }
21
- else if (type === thrift_1.ThriftTypes.STRUCT) {
22
- reader.pushStack();
23
- context = reader.stack.join('/');
24
- continue;
25
- }
26
- messages.push(getReadFunction(type)({ reader, context }));
17
+ const reader = new BufferReader(message);
18
+ const messages = [];
19
+ let context = "";
20
+
21
+ // FIX: iterate using reader.position, not a constant local var
22
+ while (reader.position < message.length) {
23
+ const type = reader.readField();
24
+
25
+ if (type === thrift_1.ThriftTypes.STOP) {
26
+ if (reader.stack.length === 0) return messages;
27
+ reader.popStack();
28
+ context = reader.stack.join("/");
29
+ continue;
30
+ } else if (type === thrift_1.ThriftTypes.STRUCT) {
31
+ reader.pushStack();
32
+ context = reader.stack.join("/");
33
+ continue;
27
34
  }
28
- return messages;
35
+
36
+ messages.push(getReadFunction(type)({ reader, context }));
37
+ }
38
+
39
+ return messages;
29
40
  }
30
41
  exports.thriftRead = thriftRead;
42
+
31
43
  function getReadFunction(type) {
32
- switch (type) {
33
- case thrift_1.ThriftTypes.STRUCT:
34
- case thrift_1.ThriftTypes.STOP: {
35
- throw new errors_1.InvalidStateError(`Invalid state: got type ${type}`);
36
- }
37
- case thrift_1.ThriftTypes.TRUE:
38
- case thrift_1.ThriftTypes.FALSE:
39
- return ({ reader, context }) => ({
40
- context,
41
- field: reader.field,
42
- value: type === thrift_1.ThriftTypes.TRUE,
43
- type,
44
- });
45
- case thrift_1.ThriftTypes.BYTE:
46
- return ({ reader, context }) => ({
47
- context,
48
- field: reader.field,
49
- value: reader.readSByte(),
50
- type,
51
- });
52
- case thrift_1.ThriftTypes.INT_16:
53
- case thrift_1.ThriftTypes.INT_32:
54
- return ({ reader, context }) => ({
55
- context,
56
- field: reader.field,
57
- value: reader.readSmallInt(),
58
- type,
59
- });
60
- case thrift_1.ThriftTypes.INT_64:
61
- return ({ reader, context }) => ({
62
- context,
63
- field: reader.field,
64
- value: reader.readBigint(),
65
- type,
66
- });
67
- case thrift_1.ThriftTypes.BINARY:
68
- return ({ reader, context }) => ({
69
- context,
70
- field: reader.field,
71
- value: reader.readString(reader.readVarInt()),
72
- type,
44
+ switch (type) {
45
+ case thrift_1.ThriftTypes.STRUCT:
46
+ case thrift_1.ThriftTypes.STOP: {
47
+ throw new errors_1.InvalidStateError(`Invalid state: got type ${type}`);
48
+ }
49
+
50
+ case thrift_1.ThriftTypes.TRUE:
51
+ case thrift_1.ThriftTypes.FALSE:
52
+ return ({ reader, context }) => ({
53
+ context,
54
+ field: reader.field,
55
+ value: type === thrift_1.ThriftTypes.TRUE,
56
+ type,
57
+ });
58
+
59
+ case thrift_1.ThriftTypes.BYTE:
60
+ return ({ reader, context }) => ({
61
+ context,
62
+ field: reader.field,
63
+ value: reader.readSByte(),
64
+ type,
65
+ });
66
+
67
+ case thrift_1.ThriftTypes.INT_16:
68
+ case thrift_1.ThriftTypes.INT_32:
69
+ return ({ reader, context }) => ({
70
+ context,
71
+ field: reader.field,
72
+ value: reader.readSmallInt(),
73
+ type,
74
+ });
75
+
76
+ case thrift_1.ThriftTypes.INT_64:
77
+ return ({ reader, context }) => ({
78
+ context,
79
+ field: reader.field,
80
+ value: reader.readBigint(),
81
+ type,
82
+ });
83
+
84
+ case thrift_1.ThriftTypes.BINARY:
85
+ return ({ reader, context }) => ({
86
+ context,
87
+ field: reader.field,
88
+ value: reader.readString(reader.readVarInt()),
89
+ type,
90
+ });
91
+
92
+ case thrift_1.ThriftTypes.SET:
93
+ case thrift_1.ThriftTypes.LIST:
94
+ return ({ reader, context }) => {
95
+ const byte = reader.readByte();
96
+ let size = byte >> 4;
97
+ const listType = byte & 0x0f;
98
+ if (size === 0x0f) size = reader.readVarInt();
99
+ return {
100
+ context,
101
+ field: reader.field,
102
+ value: reader.readList(size, listType),
103
+ type: (listType << 8) | type,
104
+ };
105
+ };
106
+
107
+ case thrift_1.ThriftTypes.MAP:
108
+ return ({ reader, context }) => {
109
+ const size = reader.readVarInt();
110
+ const kvType = size ? reader.readByte() : 0;
111
+ const keyType = (kvType & 0xf0) >> 4;
112
+ const valueType = kvType & 0x0f;
113
+
114
+ if (size && keyType && valueType) {
115
+ const keyFunc = getReadFunction(keyType);
116
+ const valueFunc = getReadFunction(valueType);
117
+ const entries = [];
118
+ for (let i = 0; i < size; i++) {
119
+ entries.push({
120
+ key: keyFunc({ reader, context }),
121
+ value: valueFunc({ reader, context }),
73
122
  });
74
- case thrift_1.ThriftTypes.SET:
75
- case thrift_1.ThriftTypes.LIST:
76
- return ({ reader, context }) => {
77
- const byte = reader.readByte();
78
- let size = byte >> 4;
79
- const listType = byte & 0x0f;
80
- if (size === 0x0f)
81
- size = reader.readVarInt();
82
- return {
83
- context,
84
- field: reader.field,
85
- value: reader.readList(size, listType),
86
- type: (listType << 8) | type,
87
- };
88
- };
89
- case thrift_1.ThriftTypes.MAP:
90
- return ({ reader, context }) => {
91
- const size = reader.readVarInt();
92
- const kvType = size ? reader.readByte() : 0;
93
- const keyType = (kvType & 0xf0) >> 4;
94
- const valueType = kvType & 0x0f;
95
- if (size && keyType && valueType) {
96
- const keyFunc = getReadFunction(keyType);
97
- const valueFunc = getReadFunction(valueType);
98
- const entries = [];
99
- for (let i = 0; i < size; i++) {
100
- entries.push({
101
- key: keyFunc({ reader, context }),
102
- value: valueFunc({ reader, context }),
103
- });
104
- }
105
- return {
106
- context,
107
- field: reader.field,
108
- value: entries,
109
- type: (kvType << 8) | type,
110
- };
111
- }
112
- return {
113
- context,
114
- field: reader.field,
115
- value: [],
116
- type: (kvType << 8) | type,
117
- };
118
- };
119
- default: {
120
- throw new errors_1.ThriftError(`Unknown type: ${type}`);
123
+ }
124
+ return {
125
+ context,
126
+ field: reader.field,
127
+ value: entries,
128
+ type: (kvType << 8) | type,
129
+ };
121
130
  }
131
+
132
+ return {
133
+ context,
134
+ field: reader.field,
135
+ value: [],
136
+ type: (kvType << 8) | type,
137
+ };
138
+ };
139
+
140
+ default: {
141
+ throw new errors_1.ThriftError(`Unknown type: ${type}`);
122
142
  }
143
+ }
123
144
  }
145
+
124
146
  function thriftReadToObject(message, descriptors) {
125
- const readResult = thriftRead(message);
126
- const topLevel = readResult.filter(x => x.context.length === 0);
127
- const result = thriftReadSingleLevel(topLevel, descriptors);
128
- const structs = [];
129
- for (const readData of readResult) {
130
- if (readData.context.length === 0)
131
- continue;
132
- const fieldPath = readData.context.split('/').map(c => Number(c));
133
- const possible = structs.findIndex(s => equalArrays(s.fieldPath, fieldPath));
134
- if (possible !== -1) {
135
- structs[possible].items.push(readData);
136
- }
137
- else {
138
- structs.push({ fieldPath, items: [readData] });
139
- }
147
+ const readResult = thriftRead(message);
148
+
149
+ const topLevel = readResult.filter((x) => x.context.length === 0);
150
+ const result = thriftReadSingleLevel(topLevel, descriptors);
151
+
152
+ const structs = [];
153
+ for (const readData of readResult) {
154
+ if (readData.context.length === 0) continue;
155
+
156
+ const fieldPath = readData.context.split("/").map((c) => Number(c));
157
+ const possible = structs.findIndex((s) => equalArrays(s.fieldPath, fieldPath));
158
+ if (possible !== -1) {
159
+ structs[possible].items.push(readData);
160
+ } else {
161
+ structs.push({ fieldPath, items: [readData] });
140
162
  }
141
- for (const struct of structs) {
142
- let descriptor;
143
- for (const level of struct.fieldPath) {
144
- if (descriptor) {
145
- descriptor = descriptor.structDescriptors?.find(x => x.field === level);
146
- }
147
- else {
148
- descriptor = descriptors.find(x => x.field === level);
149
- }
150
- if (!descriptor)
151
- break;
152
- }
153
- if (descriptor) {
154
- defineEnumerableProperty(result, descriptor.fieldName, thriftReadSingleLevel(struct.items, descriptor.structDescriptors ?? []));
155
- }
156
- else {
157
- if (result.otherFindings)
158
- result.otherFindings.push(struct);
159
- else
160
- result.otherFindings = [struct];
161
- }
163
+ }
164
+
165
+ for (const struct of structs) {
166
+ let descriptor;
167
+ for (const level of struct.fieldPath) {
168
+ if (descriptor) descriptor = descriptor.structDescriptors?.find((x) => x.field === level);
169
+ else descriptor = descriptors.find((x) => x.field === level);
170
+ if (!descriptor) break;
162
171
  }
163
- return result;
172
+
173
+ if (descriptor) {
174
+ defineEnumerableProperty(
175
+ result,
176
+ descriptor.fieldName,
177
+ thriftReadSingleLevel(struct.items, descriptor.structDescriptors ?? [])
178
+ );
179
+ } else {
180
+ if (result.otherFindings) result.otherFindings.push(struct);
181
+ else result.otherFindings = [struct];
182
+ }
183
+ }
184
+
185
+ return result;
164
186
  }
165
187
  exports.thriftReadToObject = thriftReadToObject;
188
+
166
189
  function thriftReadSingleLevel(readResults, descriptors) {
167
- const result = {};
168
- const otherFindings = [];
169
- for (const message of readResults) {
170
- const descriptor = descriptors.find(d => d.field === message.field &&
171
- (d.type === message.type || ((0, thrift_1.isThriftBoolean)(message.type) && (0, thrift_1.isThriftBoolean)(d.type))));
172
- if (descriptor) {
173
- // special checks for maps
174
- if (descriptor.type === thrift_1.ThriftTypes.MAP_BINARY_BINARY) {
175
- const res = {};
176
- for (const pair of message.value) {
177
- defineEnumerableProperty(res, pair.key.value, pair.value.value);
178
- }
179
- defineEnumerableProperty(result, descriptor.fieldName, res);
180
- continue;
181
- }
182
- defineEnumerableProperty(result, descriptor.fieldName, message.value);
183
- }
184
- else {
185
- otherFindings.push(message);
190
+ const result = {};
191
+ const otherFindings = [];
192
+
193
+ // PERF: build lookup map once
194
+ const byField = new Map();
195
+ for (const d of descriptors) {
196
+ // multiple descriptors could share field? keep first
197
+ if (!byField.has(d.field)) byField.set(d.field, []);
198
+ byField.get(d.field).push(d);
199
+ }
200
+
201
+ for (const message of readResults) {
202
+ const candidates = byField.get(message.field) || [];
203
+ const descriptor = candidates.find(
204
+ (d) =>
205
+ d.type === message.type ||
206
+ ((0, thrift_1.isThriftBoolean)(message.type) && (0, thrift_1.isThriftBoolean)(d.type))
207
+ );
208
+
209
+ if (descriptor) {
210
+ // special checks for maps
211
+ if (descriptor.type === thrift_1.ThriftTypes.MAP_BINARY_BINARY) {
212
+ const res = {};
213
+ for (const pair of message.value) {
214
+ defineEnumerableProperty(res, pair.key.value, pair.value.value);
186
215
  }
216
+ defineEnumerableProperty(result, descriptor.fieldName, res);
217
+ continue;
218
+ }
219
+ defineEnumerableProperty(result, descriptor.fieldName, message.value);
220
+ } else {
221
+ otherFindings.push(message);
187
222
  }
188
- return otherFindings.length > 0
189
- ? {
190
- ...result,
191
- otherFindings,
192
- }
193
- : result;
223
+ }
224
+
225
+ return otherFindings.length > 0 ? { ...result, otherFindings } : result;
194
226
  }
195
- const defineEnumerableProperty = (object, name, value) => Object.defineProperty(object, name, { value, enumerable: true });
227
+
228
+ const defineEnumerableProperty = (object, name, value) =>
229
+ Object.defineProperty(object, name, { value, enumerable: true });
230
+
196
231
  class BufferReader {
197
- get stack() {
198
- return this._stack;
199
- }
200
- get position() {
201
- return this._position;
232
+ get stack() {
233
+ return this._stack;
234
+ }
235
+ get position() {
236
+ return this._position;
237
+ }
238
+ get length() {
239
+ return this.buffer.length;
240
+ }
241
+ get field() {
242
+ return this._field;
243
+ }
244
+
245
+ constructor(buffer) {
246
+ this._stack = [];
247
+ this._position = 0;
248
+ this._field = 0;
249
+
250
+ this.readInt16 = this.readSmallInt;
251
+ this.readInt32 = this.readSmallInt;
252
+
253
+ this.readByte = () => this.buffer.readUInt8(this.move(1));
254
+ this.readSByte = () => this.buffer.readInt8(this.move(1));
255
+ this.readString = (len) => this.buffer.toString("utf8", this.move(len), this._position);
256
+
257
+ this.buffer = buffer;
258
+ }
259
+
260
+ move(bytes) {
261
+ this._position = Math.min(Math.max(this._position + bytes, 0), this.buffer.length);
262
+ return this._position - bytes;
263
+ }
264
+
265
+ readVarInt() {
266
+ let shift = 0;
267
+ let result = 0;
268
+ while (this._position < this.length) {
269
+ const byte = this.readByte();
270
+ result |= (byte & 0x7f) << shift;
271
+ if ((byte & 0x80) === 0) break;
272
+ shift += 7;
202
273
  }
203
- get length() {
204
- return this.buffer.length;
205
- }
206
- get field() {
207
- return this._field;
208
- }
209
- constructor(buffer) {
210
- this._stack = [];
211
- this._position = 0;
212
- this._field = 0;
213
- this.readInt16 = this.readSmallInt;
214
- this.readInt32 = this.readSmallInt;
215
- this.readByte = () => this.buffer.readUInt8(this.move(1));
216
- this.readSByte = () => this.buffer.readInt8(this.move(1));
217
- this.readString = (len) => this.buffer.toString('utf8', this.move(len), this._position);
218
- this.buffer = buffer;
219
- }
220
- move(bytes) {
221
- this._position = Math.min(Math.max(this._position + bytes, 0), this.buffer.length);
222
- return this._position - bytes;
223
- }
224
- readVarInt() {
225
- let shift = 0;
226
- let result = 0;
227
- while (this._position < this.length) {
228
- const byte = this.readByte();
229
- result |= (byte & 0x7f) << shift;
230
- if ((byte & 0x80) === 0) {
231
- break;
232
- }
233
- shift += 7;
234
- }
235
- return result;
236
- }
237
- readVarBigint() {
238
- let shift = BigInt(0);
239
- let result = BigInt(0);
240
- while (true) {
241
- const byte = this.readByte();
242
- result = result | ((BigInt(byte) & BigInt(0x7f)) << shift);
243
- if ((byte & 0x80) !== 0x80)
244
- break;
245
- shift += BigInt(7);
246
- }
247
- return result;
248
- }
249
- zigzagToBigint(n) {
250
- return (n >> BigInt(1)) ^ -(n & BigInt(1));
251
- }
252
- readBigint() {
253
- const result = this.zigzagToBigint(this.readVarBigint());
254
- return { int: result, num: Number(result) };
255
- }
256
- readSmallInt() {
257
- return BufferReader.fromZigZag(this.readVarInt());
258
- }
259
- readField() {
260
- const byte = this.readByte();
261
- if (byte === 0) {
262
- return thrift_1.ThriftTypes.STOP;
263
- }
264
- const delta = (byte & 0xf0) >> 4;
265
- if (delta === 0) {
266
- this._field = BufferReader.fromZigZag(this.readVarInt());
267
- }
268
- else {
269
- this._field += delta;
270
- }
271
- return byte & 0x0f;
272
- }
273
- readList(size, type) {
274
- const arr = [];
275
- switch (type) {
276
- case thrift_1.ThriftTypes.TRUE:
277
- case thrift_1.ThriftTypes.FALSE: {
278
- for (let i = 0; i < size; i++) {
279
- arr[i] = this.readSByte() === thrift_1.ThriftTypes.TRUE;
280
- }
281
- break;
282
- }
283
- case thrift_1.ThriftTypes.BYTE: {
284
- for (let i = 0; i < size; i++) {
285
- arr[i] = this.readSByte();
286
- }
287
- break;
288
- }
289
- case thrift_1.ThriftTypes.INT_16:
290
- case thrift_1.ThriftTypes.INT_32:
291
- case thrift_1.ThriftTypes.INT_64: {
292
- for (let i = 0; i < size; i++) {
293
- arr[i] = BufferReader.fromZigZag(this.readVarInt());
294
- }
295
- break;
296
- }
297
- case thrift_1.ThriftTypes.BINARY: {
298
- for (let i = 0; i < size; i++) {
299
- arr[i] = this.readString(this.readVarInt());
300
- }
301
- break;
302
- }
303
- default: {
304
- throw new errors_1.ThriftError(`Type ${type} not impl.`);
305
- }
306
- }
307
- return arr;
274
+ return result;
275
+ }
276
+
277
+ readVarBigint() {
278
+ let shift = BigInt(0);
279
+ let result = BigInt(0);
280
+ while (true) {
281
+ const byte = this.readByte();
282
+ result = result | ((BigInt(byte) & BigInt(0x7f)) << shift);
283
+ if ((byte & 0x80) !== 0x80) break;
284
+ shift += BigInt(7);
308
285
  }
309
- pushStack() {
310
- this._stack.push(this.field);
311
- this._field = 0;
286
+ return result;
287
+ }
288
+
289
+ zigzagToBigint(n) {
290
+ return (n >> BigInt(1)) ^ -(n & BigInt(1));
291
+ }
292
+
293
+ readBigint() {
294
+ const int = this.zigzagToBigint(this.readVarBigint());
295
+ const num = Number(int);
296
+ // keep backward shape, add a hint without breaking callers
297
+ const safe = int <= BigInt(Number.MAX_SAFE_INTEGER) && int >= BigInt(Number.MIN_SAFE_INTEGER);
298
+ return safe ? { int, num } : { int, num, safe };
299
+ }
300
+
301
+ readSmallInt() {
302
+ return BufferReader.fromZigZag(this.readVarInt());
303
+ }
304
+
305
+ readField() {
306
+ const byte = this.readByte();
307
+ if (byte === 0) return thrift_1.ThriftTypes.STOP;
308
+
309
+ const delta = (byte & 0xf0) >> 4;
310
+ if (delta === 0) {
311
+ this._field = BufferReader.fromZigZag(this.readVarInt());
312
+ } else {
313
+ this._field += delta;
312
314
  }
313
- popStack() {
314
- this._field = this._stack.pop() ?? -1;
315
+
316
+ return byte & 0x0f;
317
+ }
318
+
319
+ readList(size, type) {
320
+ const arr = [];
321
+ switch (type) {
322
+ case thrift_1.ThriftTypes.TRUE:
323
+ case thrift_1.ThriftTypes.FALSE: {
324
+ for (let i = 0; i < size; i++) arr[i] = this.readSByte() === thrift_1.ThriftTypes.TRUE;
325
+ break;
326
+ }
327
+ case thrift_1.ThriftTypes.BYTE: {
328
+ for (let i = 0; i < size; i++) arr[i] = this.readSByte();
329
+ break;
330
+ }
331
+ case thrift_1.ThriftTypes.INT_16:
332
+ case thrift_1.ThriftTypes.INT_32: {
333
+ for (let i = 0; i < size; i++) arr[i] = BufferReader.fromZigZag(this.readVarInt());
334
+ break;
335
+ }
336
+ case thrift_1.ThriftTypes.INT_64: {
337
+ // FIX: proper bigint varint + zigzag
338
+ for (let i = 0; i < size; i++) arr[i] = this.readBigint();
339
+ break;
340
+ }
341
+ case thrift_1.ThriftTypes.BINARY: {
342
+ for (let i = 0; i < size; i++) arr[i] = this.readString(this.readVarInt());
343
+ break;
344
+ }
345
+ default: {
346
+ throw new errors_1.ThriftError(`Type ${type} not impl.`);
347
+ }
315
348
  }
349
+ return arr;
350
+ }
351
+
352
+ pushStack() {
353
+ this._stack.push(this.field);
354
+ this._field = 0;
355
+ }
356
+ popStack() {
357
+ this._field = this._stack.pop() ?? -1;
358
+ }
316
359
  }
317
360
  exports.BufferReader = BufferReader;
361
+
318
362
  BufferReader.fromZigZag = (n) => (n >> 1) ^ -(n & 1);
363
+
319
364
  function equalArrays(left, right) {
320
- if (!left || !right || left.length !== right.length)
321
- return false;
322
- for (let i = 0; i < left.length; i++)
323
- if (left[i] !== right[i])
324
- return false;
325
- return true;
365
+ if (!left || !right || left.length !== right.length) return false;
366
+ for (let i = 0; i < left.length; i++) if (left[i] !== right[i]) return false;
367
+ return true;
326
368
  }
327
- //# sourceMappingURL=thrift.reading.js.map