data-structure-typed 2.2.2 → 2.2.3

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.
Files changed (83) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +311 -1687
  3. package/README_CN.md +509 -0
  4. package/SECURITY.md +962 -11
  5. package/SECURITY.zh-CN.md +966 -0
  6. package/SPECIFICATION.md +689 -30
  7. package/SPECIFICATION.zh-CN.md +715 -0
  8. package/SPONSOR.zh-CN.md +62 -0
  9. package/SPONSOR_POLISHED.md +62 -0
  10. package/benchmark/report.html +1 -1
  11. package/benchmark/report.json +215 -172
  12. package/dist/cjs/index.cjs +163 -0
  13. package/dist/cjs/index.cjs.map +1 -1
  14. package/dist/cjs-legacy/index.cjs +164 -0
  15. package/dist/cjs-legacy/index.cjs.map +1 -1
  16. package/dist/esm/index.mjs +163 -0
  17. package/dist/esm/index.mjs.map +1 -1
  18. package/dist/esm-legacy/index.mjs +164 -0
  19. package/dist/esm-legacy/index.mjs.map +1 -1
  20. package/dist/types/data-structures/binary-tree/avl-tree.d.ts +96 -2
  21. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +103 -7
  22. package/dist/types/data-structures/binary-tree/bst.d.ts +156 -13
  23. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +84 -35
  24. package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
  25. package/dist/types/data-structures/graph/directed-graph.d.ts +126 -1
  26. package/dist/types/data-structures/graph/undirected-graph.d.ts +160 -1
  27. package/dist/types/data-structures/hash/hash-map.d.ts +110 -27
  28. package/dist/types/data-structures/heap/heap.d.ts +107 -58
  29. package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +72 -404
  30. package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +121 -5
  31. package/dist/types/data-structures/queue/deque.d.ts +95 -67
  32. package/dist/types/data-structures/queue/queue.d.ts +90 -34
  33. package/dist/types/data-structures/stack/stack.d.ts +58 -40
  34. package/dist/types/data-structures/trie/trie.d.ts +109 -47
  35. package/dist/types/interfaces/binary-tree.d.ts +1 -0
  36. package/dist/umd/data-structure-typed.js +164 -0
  37. package/dist/umd/data-structure-typed.js.map +1 -1
  38. package/dist/umd/data-structure-typed.min.js +3 -3
  39. package/dist/umd/data-structure-typed.min.js.map +1 -1
  40. package/package.json +3 -2
  41. package/src/data-structures/binary-tree/avl-tree.ts +96 -2
  42. package/src/data-structures/binary-tree/binary-tree.ts +117 -7
  43. package/src/data-structures/binary-tree/bst.ts +322 -13
  44. package/src/data-structures/binary-tree/red-black-tree.ts +84 -35
  45. package/src/data-structures/binary-tree/tree-multi-map.ts +2 -2
  46. package/src/data-structures/graph/directed-graph.ts +126 -1
  47. package/src/data-structures/graph/undirected-graph.ts +160 -1
  48. package/src/data-structures/hash/hash-map.ts +110 -27
  49. package/src/data-structures/heap/heap.ts +107 -58
  50. package/src/data-structures/linked-list/doubly-linked-list.ts +72 -404
  51. package/src/data-structures/linked-list/singly-linked-list.ts +121 -5
  52. package/src/data-structures/queue/deque.ts +95 -67
  53. package/src/data-structures/queue/queue.ts +90 -34
  54. package/src/data-structures/stack/stack.ts +58 -40
  55. package/src/data-structures/trie/trie.ts +109 -47
  56. package/src/interfaces/binary-tree.ts +2 -0
  57. package/test/performance/benchmark-runner.ts +14 -11
  58. package/test/performance/data-structures/binary-tree/avl-tree.test.ts +8 -8
  59. package/test/performance/data-structures/binary-tree/binary-tree-overall.test.ts +8 -8
  60. package/test/performance/data-structures/binary-tree/binary-tree.test.ts +6 -6
  61. package/test/performance/data-structures/binary-tree/bst.test.ts +5 -5
  62. package/test/performance/data-structures/binary-tree/red-black-tree.test.ts +10 -10
  63. package/test/performance/reportor.ts +2 -1
  64. package/test/performance/single-suite-runner.ts +7 -4
  65. package/test/unit/data-structures/binary-tree/avl-tree.test.ts +117 -0
  66. package/test/unit/data-structures/binary-tree/binary-tree.test.ts +166 -0
  67. package/test/unit/data-structures/binary-tree/bst.test.ts +766 -8
  68. package/test/unit/data-structures/binary-tree/red-black-tree.test.ts +89 -37
  69. package/test/unit/data-structures/graph/directed-graph.test.ts +133 -0
  70. package/test/unit/data-structures/graph/undirected-graph.test.ts +167 -0
  71. package/test/unit/data-structures/hash/hash-map.test.ts +149 -3
  72. package/test/unit/data-structures/heap/heap.test.ts +182 -47
  73. package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +118 -14
  74. package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +121 -0
  75. package/test/unit/data-structures/queue/deque.test.ts +98 -67
  76. package/test/unit/data-structures/queue/queue.test.ts +85 -51
  77. package/test/unit/data-structures/stack/stack.test.ts +142 -33
  78. package/test/unit/data-structures/trie/trie.test.ts +135 -39
  79. package/tsup.leetcode.config.js +99 -0
  80. package/typedoc.json +2 -1
  81. package/POSTS_zh-CN.md +0 -54
  82. package/README_zh-CN.md +0 -1208
  83. package/SPECIFICATION_zh-CN.md +0 -81
@@ -0,0 +1,966 @@
1
+ # 安全指南:data-structure-typed 安全手册
2
+
3
+ **版本:** 2.0.4
4
+ **最后更新:** 2026年1月
5
+ **状态:** ✅ 积极维护中
6
+
7
+ ---
8
+
9
+ ## 目录
10
+
11
+ 1. [安全概述](#安全概述)
12
+ 2. [威胁模型](#威胁模型)
13
+ 3. [安全保证](#安全保证)
14
+ 4. [输入验证](#输入验证)
15
+ 5. [比较器安全](#比较器安全)
16
+ 6. [内存管理](#内存管理)
17
+ 7. [类型安全](#类型安全)
18
+ 8. [迭代安全](#迭代安全)
19
+ 9. [拒绝服务(DoS)防护](#拒绝服务dos防护)
20
+ 10. [依赖安全](#依赖安全)
21
+ 11. [安全使用模式](#安全使用模式)
22
+ 12. [已知限制](#已知限制)
23
+ 13. [安全更新策略](#安全更新策略)
24
+ 14. [报告安全问题](#报告安全问题)
25
+
26
+ ---
27
+
28
+ ## 安全概述
29
+
30
+ **data-structure-typed** 是一个专注于性能和可用性的数据结构库。安全考虑主要围绕**资源耗尽**、**类型安全**和**安全迭代**。
31
+
32
+ ### 范围界定
33
+
34
+ **本库不设计用于:**
35
+ - ❌ 加密或哈希数据
36
+ - ❌ 验证不受信任的输入
37
+ - ❌ 防止时序攻击
38
+ - ❌ 防护侧信道攻击
39
+ - ❌ 清理用户输入
40
+
41
+ **本库确实防护:**
42
+ - ✅ 缓冲区溢出(JavaScript 中不可能)
43
+ - ✅ 类型混淆攻击(TypeScript 在编译时防止)
44
+ - ✅ Null/undefined 解引用(防御性检查)
45
+ - ✅ 不受控的内存增长(清晰的 API)
46
+ - ✅ 不安全的迭代模式(文档化行为)
47
+
48
+ ### 设计哲学
49
+
50
+ 库遵循**快速失败**原则:
51
+ - **响亮**:指示 bug 的错误抛出异常
52
+ - **静默**:缺失的键返回 undefined(标准行为)
53
+ - **安全**:类型系统在编译时防止类别错误
54
+
55
+ ---
56
+
57
+ ## 威胁模型
58
+
59
+ ### 攻击向量(在范围内)
60
+
61
+ #### 1. 意外内存增长
62
+
63
+ **风险:** 攻击者添加数百万项,导致内存耗尽(OOM)
64
+
65
+ ```typescript
66
+ const tree = new RedBlackTree();
67
+ for (let i = 0; i < 1000000000; i++) {
68
+ tree.set(i, 'data'); // 无界增长
69
+ }
70
+ // 进程内存耗尽
71
+ ```
72
+
73
+ **缓解措施:**
74
+ - 监控 `structure.size` 属性
75
+ - 在应用程序逻辑中实现大小限制
76
+ - 使用完毕后清除结构:`structure.clear()`
77
+
78
+ ```typescript
79
+ // ✅ 安全模式
80
+ const tree = new RedBlackTree();
81
+ const MAX_SIZE = 100000;
82
+
83
+ function addSafe(key, value) {
84
+ if (tree.size >= MAX_SIZE) {
85
+ throw new Error('结构已达容量上限');
86
+ }
87
+ tree.set(key, value);
88
+ }
89
+ ```
90
+
91
+ #### 2. 比较器异常
92
+
93
+ **风险:** 恶意比较器抛出异常或崩溃
94
+
95
+ ```typescript
96
+ const tree = new RedBlackTree<number>(
97
+ (a, b) => {
98
+ if (a === null) throw new Error('被黑了!');
99
+ return a - b;
100
+ }
101
+ );
102
+
103
+ tree.set(null, 'value'); // 抛出未处理的异常
104
+ ```
105
+
106
+ **缓解措施:**
107
+ - 如果不受信任,总是用 try-catch 包装比较器
108
+ - 使用纯函数(无副作用)
109
+ - 在树操作之前验证输入
110
+
111
+ ```typescript
112
+ // ✅ 安全模式
113
+ function safeComparator(a, b) {
114
+ try {
115
+ if (!isNumber(a) || !isNumber(b)) {
116
+ throw new TypeError('期望是数字');
117
+ }
118
+ return a - b;
119
+ } catch (error) {
120
+ logger.error('比较器失败:', error);
121
+ throw error; // 显式错误处理
122
+ }
123
+ }
124
+
125
+ const tree = new RedBlackTree<number>(safeComparator);
126
+ ```
127
+
128
+ #### 3. 迭代器变更
129
+
130
+ **风险:** 在迭代期间变更结构导致状态不一致
131
+
132
+ ```typescript
133
+ const tree = new RedBlackTree([1, 2, 3]);
134
+
135
+ for (const item of tree) {
136
+ tree.delete(item); // 在迭代时修改
137
+ // 行为未定义
138
+ }
139
+ ```
140
+
141
+ **缓解措施:**
142
+ - 不要在迭代期间变更
143
+ - 收集变更并在之后应用
144
+ - 如果需要,使用快照迭代
145
+
146
+ ```typescript
147
+ // ✅ 安全模式
148
+ const tree = new RedBlackTree([1, 2, 3]);
149
+
150
+ // 方法 1:首先收集变更
151
+ const toDelete = [];
152
+ for (const item of tree) {
153
+ if (shouldDelete(item)) toDelete.push(item);
154
+ }
155
+ toDelete.forEach(item => tree.delete(item));
156
+
157
+ // 方法 2:快照迭代
158
+ const items = [...tree]; // 创建快照
159
+ items.forEach(item => tree.delete(item));
160
+ ```
161
+
162
+ #### 4. 类型混淆
163
+
164
+ **风险:** 传递错误类型在运行时绕过类型系统
165
+
166
+ ```typescript
167
+ const tree = new RedBlackTree<number>();
168
+
169
+ // 在运行时,TypeScript 类型被擦除
170
+ tree.set('not-a-number' as any, 'value');
171
+ // 类型系统没有阻止这个
172
+ ```
173
+
174
+ **缓解措施:**
175
+ - 使用严格的 TypeScript 设置:`strict: true`
176
+ - 在不受信任的代码中避免 `as any` 断言
177
+ - 在运行时边界验证类型
178
+
179
+ ```typescript
180
+ // ✅ 安全模式
181
+ interface ValidInput {
182
+ id: number;
183
+ name: string;
184
+ }
185
+
186
+ function addFromUntrustedSource(input: unknown) {
187
+ if (!isValidInput(input)) {
188
+ throw new TypeError('无效输入');
189
+ }
190
+
191
+ const tree = new RedBlackTree<number, ValidInput>();
192
+ tree.set(input.id, input); // 现在是类型安全的
193
+ }
194
+
195
+ function isValidInput(input: unknown): input is ValidInput {
196
+ return (
197
+ typeof input === 'object' &&
198
+ input !== null &&
199
+ typeof (input as any).id === 'number' &&
200
+ typeof (input as any).name === 'string'
201
+ );
202
+ }
203
+ ```
204
+
205
+ #### 5. 无限循环
206
+
207
+ **风险:** 比较器在树操作期间导致无限循环
208
+
209
+ ```typescript
210
+ const tree = new RedBlackTree<number>(
211
+ (a, b) => {
212
+ // 故意破坏的比较器
213
+ return 0; // 总是相等
214
+ }
215
+ );
216
+
217
+ tree.addMany([1, 2, 3, 4, 5]);
218
+ // 可能导致无限循环或栈溢出
219
+ ```
220
+
221
+ **缓解措施:**
222
+ - 使用严格的比较器:一致且确定性
223
+ - 用大数据集测试比较器
224
+ - 为树操作设置超时限制
225
+
226
+ ```typescript
227
+ // ✅ 安全模式
228
+ function strictComparator<T>(a: T, b: T): number {
229
+ if (a < b) return -1;
230
+ if (a > b) return 1;
231
+ return 0; // 只返回 -1、0 或 1
232
+ }
233
+
234
+ const tree = new RedBlackTree<number>(strictComparator);
235
+
236
+ // 带超时包装器(应用程序级别)
237
+ function withTimeout<T>(fn: () => T, ms: number): T {
238
+ const controller = new AbortController();
239
+ const timeout = setTimeout(() => controller.abort(), ms);
240
+
241
+ try {
242
+ return fn();
243
+ } finally {
244
+ clearTimeout(timeout);
245
+ }
246
+ }
247
+
248
+ withTimeout(() => tree.addMany(items), 1000);
249
+ ```
250
+
251
+ ---
252
+
253
+ ## 安全保证
254
+
255
+ ### 本库保证的内容
256
+
257
+ | 保证 | 状态 | 详细信息 |
258
+ |-----------|--------|---------|
259
+ | **无任意代码执行** | ✅ 100% | 只运行提供的比较器 |
260
+ | **无数据泄漏** | ✅ 100% | 无外部通信 |
261
+ | **无不受控的内存增长** | ⚠️ 部分 | 应用程序必须设置大小限制 |
262
+ | **类型安全** | ✅ 100% | TypeScript 防止类型混淆 |
263
+ | **迭代器安全** | ✅ 100% | 清晰记录的行为 |
264
+ | **防护无效输入** | ⚠️ 部分 | 应用程序验证输入 |
265
+
266
+ ### 本库不保证的内容
267
+
268
+ | 保证 | 状态 | 详细信息 |
269
+ |-----------|--------|---------|
270
+ | **恒定时间操作** | ❌ 否 | 可能存在时序攻击(仅限加密使用) |
271
+ | **DoS 防护** | ⚠️ 否 | 应用程序必须限速 |
272
+ | **不受信任输入处理** | ❌ 否 | 输入验证是应用程序的责任 |
273
+ | **安全随机数** | ❌ 否 | 不适用(无随机性) |
274
+ | **加密安全** | ❌ 否 | 不是加密库 |
275
+
276
+ ---
277
+
278
+ ## 输入验证
279
+
280
+ ### 比较器必须是纯函数
281
+
282
+ **不安全:有副作用或外部状态**
283
+
284
+ ```typescript
285
+ // ❌ 不要这样做
286
+ let callCount = 0;
287
+ const tree = new RedBlackTree<number>((a, b) => {
288
+ callCount++; // 副作用!
289
+ return a - b;
290
+ });
291
+
292
+ // ❌ 不要这样做
293
+ const config = getConfig();
294
+ const tree = new RedBlackTree<number>((a, b) => {
295
+ const weight = config.weight; // 可变的外部状态
296
+ return (a - b) * weight;
297
+ });
298
+
299
+ // ✅ 这样做
300
+ const tree = new RedBlackTree<number>((a, b) => {
301
+ return a - b; // 纯函数
302
+ });
303
+
304
+ const weightedTree = new RedBlackTree<number>((a, b) => {
305
+ return (a - b) * FIXED_WEIGHT; // 固定常量
306
+ });
307
+ ```
308
+
309
+ ### 提前验证比较器
310
+
311
+ ```typescript
312
+ // ✅ 使用前验证比较器
313
+ function validateComparator<T>(comp: (a: T, b: T) => number, samples: T[]): boolean {
314
+ for (let i = 0; i < samples.length; i++) {
315
+ for (let j = i + 1; j < samples.length; j++) {
316
+ const result = comp(samples[i], samples[j]);
317
+
318
+ // 比较器必须返回 -1、0 或 1(或至少一致)
319
+ if (Math.abs(result) > 1 && result !== 0) {
320
+ return false; // 无效的比较器
321
+ }
322
+
323
+ // 传递性检查
324
+ for (let k = j + 1; k < samples.length; k++) {
325
+ const ij = comp(samples[i], samples[j]);
326
+ const jk = comp(samples[j], samples[k]);
327
+ const ik = comp(samples[i], samples[k]);
328
+
329
+ if (!isTransitive(ij, jk, ik)) {
330
+ return false; // 比较器违反传递性
331
+ }
332
+ }
333
+ }
334
+ }
335
+ return true;
336
+ }
337
+
338
+ // 使用经过验证的比较器
339
+ const myComparator = (a: number, b: number) => a - b;
340
+ if (!validateComparator(myComparator, [1, 2, 3])) {
341
+ throw new Error('无效的比较器');
342
+ }
343
+
344
+ const tree = new RedBlackTree<number>(myComparator);
345
+ ```
346
+
347
+ ### 限制结构大小
348
+
349
+ ```typescript
350
+ // ✅ 强制最大大小
351
+ class BoundedTree<K, V> extends RedBlackTree<K, V> {
352
+ private maxSize: number;
353
+
354
+ constructor(maxSize: number = 100000) {
355
+ super();
356
+ this.maxSize = maxSize;
357
+ }
358
+
359
+ set(key: K, value: V): this {
360
+ if (this.size >= this.maxSize && !this.has(key)) {
361
+ throw new Error(`树超过最大大小 ${this.maxSize}`);
362
+ }
363
+ return super.set(key, value);
364
+ }
365
+ }
366
+
367
+ // 放心使用
368
+ const tree = new BoundedTree(10000);
369
+ ```
370
+
371
+ ---
372
+
373
+ ## 比较器安全
374
+
375
+ ### 比较器要求
376
+
377
+ **有效的比较器必须:**
378
+
379
+ 1. **返回一致的值**
380
+ ```typescript
381
+ const comp = (a, b) => {
382
+ // ✅ 对相同输入总是返回相同的值
383
+ return a - b;
384
+ };
385
+ ```
386
+
387
+ 2. **尊重传递性**
388
+ ```typescript
389
+ // 如果 a < b 且 b < c,那么 a < c
390
+ const a = 1, b = 2, c = 3;
391
+ comp(a, b) < 0 // true
392
+ comp(b, c) < 0 // true
393
+ comp(a, c) < 0 // 必须为 true
394
+ ```
395
+
396
+ 3. **处理所有输入类型**
397
+ ```typescript
398
+ const comp = (a, b) => {
399
+ // 处理 null、undefined、NaN
400
+ if (a == null || b == null) return 0;
401
+ if (isNaN(a) || isNaN(b)) return 0;
402
+ return a - b;
403
+ };
404
+ ```
405
+
406
+ ### 危险的比较器
407
+
408
+ ```typescript
409
+ // ❌ 不要:随机比较器
410
+ const random = (a, b) => Math.random() - 0.5;
411
+
412
+ // ❌ 不要:非确定性
413
+ const nonDet = (() => {
414
+ let x = 0;
415
+ return (a, b) => (x++, a - b);
416
+ })();
417
+
418
+ // ❌ 不要:副作用
419
+ const withSideEffect = (a, b) => {
420
+ console.log(a, b); // 副作用
421
+ return a - b;
422
+ };
423
+
424
+ // ❌ 不要:抛出错误
425
+ const throws = (a, b) => {
426
+ throw new Error('糟糕');
427
+ };
428
+
429
+ // ❌ 不要:不一致的逻辑
430
+ const inconsistent = (a, b) => {
431
+ return Math.random() > 0.5 ? a - b : b - a;
432
+ };
433
+ ```
434
+
435
+ ---
436
+
437
+ ## 内存管理
438
+
439
+ ### 结构生命周期
440
+
441
+ ```typescript
442
+ // ✅ 正确的生命周期管理
443
+
444
+ // 1. 创建预期大小
445
+ const tree = new RedBlackTree<number, object>();
446
+
447
+ // 2. 添加项目
448
+ for (const item of items) {
449
+ tree.set(item.id, item);
450
+ }
451
+
452
+ // 3. 使用结构
453
+ const value = tree.get(key);
454
+
455
+ // 4. 使用完毕后清理
456
+ tree.clear(); // O(n) 操作
457
+
458
+ // 5. 允许垃圾回收
459
+ tree = null; // 或让它超出作用域
460
+ ```
461
+
462
+ ### 垃圾回收
463
+
464
+ **库不阻止垃圾回收:**
465
+
466
+ ```typescript
467
+ // JavaScript 会对未使用的结构进行 GC
468
+ {
469
+ const tree = new RedBlackTree();
470
+ tree.addMany([...]);
471
+ // tree 超出作用域
472
+ // JavaScript 自动释放内存
473
+ }
474
+
475
+ // 对于浏览器内存管理
476
+ function processLargeDataset() {
477
+ const tree = new RedBlackTree();
478
+
479
+ try {
480
+ // 处理数据
481
+ for (const item of dataset) {
482
+ tree.set(item.id, item);
483
+ }
484
+ return tree.size;
485
+ } finally {
486
+ tree.clear(); // 显式清理
487
+ }
488
+ }
489
+ ```
490
+
491
+ ### 节点引用
492
+
493
+ **小心缓存的引用:**
494
+
495
+ ```typescript
496
+ // ❌ 潜在的内存泄漏
497
+ const nodes = [];
498
+ for (const item of items) {
499
+ const node = tree.getNode(item.id);
500
+ nodes.push(node); // 保持引用
501
+ }
502
+
503
+ // 树节点持有对其邻居的引用
504
+ // 这阻止垃圾回收
505
+
506
+ // ✅ 不要保留对内部节点的引用
507
+ for (const item of items) {
508
+ const value = tree.get(item.id); // 获取值,不是节点
509
+ // 处理值
510
+ }
511
+ ```
512
+
513
+ ---
514
+
515
+ ## 类型安全
516
+
517
+ ### 严格的 TypeScript 配置
518
+
519
+ **推荐的 tsconfig.json:**
520
+
521
+ ```json
522
+ {
523
+ "compilerOptions": {
524
+ "strict": true,
525
+ "strictNullChecks": true,
526
+ "strictFunctionTypes": true,
527
+ "strictPropertyInitialization": true,
528
+ "strictBindCallApply": true,
529
+ "alwaysStrict": true,
530
+ "noImplicitAny": true,
531
+ "noImplicitThis": true,
532
+ "noImplicitReturns": true,
533
+ "noFallthroughCasesInSwitch": true,
534
+ "noImplicitReturns": true
535
+ }
536
+ }
537
+ ```
538
+
539
+ ### 类型安全使用
540
+
541
+ ```typescript
542
+ // ✅ 类型安全
543
+ const tree = new RedBlackTree<number, string>();
544
+ tree.set(1, 'Alice');
545
+ const name = tree.get(1); // 类型:string | undefined
546
+
547
+ // ❌ 不安全(严格模式下避免)
548
+ const anyTree = new RedBlackTree() as any;
549
+ anyTree.set('wrong type', 123); // TypeScript 不会捕获这个
550
+ ```
551
+
552
+ ### 泛型约束
553
+
554
+ ```typescript
555
+ // ✅ 约束类型
556
+ interface Comparable {
557
+ compareTo(other: this): number;
558
+ }
559
+
560
+ const tree = new RedBlackTree<Comparable>((a, b) => {
561
+ return a.compareTo(b);
562
+ });
563
+
564
+ // ✅ 联合类型以获得灵活性
565
+ type ValidKey = number | string | symbol;
566
+ const tree = new RedBlackTree<ValidKey, unknown>();
567
+ ```
568
+
569
+ ---
570
+
571
+ ## 迭代安全
572
+
573
+ ### 安全迭代模式
574
+
575
+ **模式 1:变更前快照**
576
+
577
+ ```typescript
578
+ // ✅ 安全:首先创建快照
579
+ const tree = new RedBlackTree([1, 2, 3, 4, 5]);
580
+
581
+ const items = [...tree]; // 快照
582
+ items.forEach(item => {
583
+ tree.delete(item); // 现在变更是安全的
584
+ });
585
+ ```
586
+
587
+ **模式 2:收集后应用**
588
+
589
+ ```typescript
590
+ // ✅ 安全:首先收集变更
591
+ const tree = new RedBlackTree([1, 2, 3, 4, 5]);
592
+
593
+ const toDelete = [];
594
+ for (const item of tree) {
595
+ if (shouldDelete(item)) {
596
+ toDelete.push(item);
597
+ }
598
+ }
599
+
600
+ toDelete.forEach(item => tree.delete(item)); // 应用变更
601
+ ```
602
+
603
+ **模式 3:函数式方法**
604
+
605
+ ```typescript
606
+ // ✅ 安全:函数式转换
607
+ const tree = new RedBlackTree([1, 2, 3, 4, 5]);
608
+
609
+ const filtered = tree
610
+ .filter(x => x > 2)
611
+ .map(x => x * 2);
612
+
613
+ // 结果是新结构,原始结构未改变
614
+ ```
615
+
616
+ ### 不安全的迭代
617
+
618
+ ```typescript
619
+ // ❌ 不要这样做
620
+ const tree = new RedBlackTree([1, 2, 3]);
621
+
622
+ for (const item of tree) {
623
+ if (condition(item)) {
624
+ tree.delete(item); // 未定义的行为!
625
+ }
626
+ }
627
+
628
+ // ❌ 不要这样做
629
+ const tree = new RedBlackTree([1, 2, 3]);
630
+
631
+ [...tree].forEach(item => {
632
+ tree.set(item, 'new'); // 可能导致问题
633
+ });
634
+ ```
635
+
636
+ ---
637
+
638
+ ## 拒绝服务(DoS)防护
639
+
640
+ ### 攻击向量:昂贵的比较
641
+
642
+ **风险:** 比较器非常慢
643
+
644
+ ```typescript
645
+ // ❌ 攻击者提供慢速比较器
646
+ const tree = new RedBlackTree<number>((a, b) => {
647
+ // 模拟昂贵的操作
648
+ for (let i = 0; i < 1000000; i++) {
649
+ Math.sqrt(i);
650
+ }
651
+ return a - b;
652
+ });
653
+
654
+ tree.addMany([...1000 个项目...]); // 永远完成不了
655
+ ```
656
+
657
+ **缓解措施:**
658
+
659
+ ```typescript
660
+ // ✅ 为树操作设置超时
661
+ function withTimeout<T>(fn: () => T, timeoutMs: number): T {
662
+ const start = Date.now();
663
+ const result = fn();
664
+
665
+ if (Date.now() - start > timeoutMs) {
666
+ throw new Error('树操作超时');
667
+ }
668
+
669
+ return result;
670
+ }
671
+
672
+ // 使用
673
+ withTimeout(() => tree.addMany(items), 1000);
674
+ ```
675
+
676
+ ### 攻击向量:哈希冲突
677
+
678
+ **风险:** 恶意键导致类似哈希的冲突
679
+
680
+ ```typescript
681
+ // 这不适用于基于比较的树
682
+ // 跳表和其他基于哈希的结构面临风险
683
+ ```
684
+
685
+ ### 攻击向量:栈溢出
686
+
687
+ **风险:** 非常深的递归结构
688
+
689
+ ```typescript
690
+ // ❌ 创建深度不平衡的树(如果使用不平衡的 BST)
691
+ const bst = new BST();
692
+ for (let i = 0; i < 10000; i++) {
693
+ bst.add(i); // 创建线性链,不是平衡树
694
+ }
695
+
696
+ // 对于平衡树(RedBlackTree、AVLTree):
697
+ // ✅ 自动平衡
698
+ const rbTree = new RedBlackTree();
699
+ for (let i = 0; i < 10000; i++) {
700
+ rbTree.set(i, i); // 总是平衡的,对数深度
701
+ }
702
+ ```
703
+
704
+ ---
705
+
706
+ ## 依赖安全
707
+
708
+ ### 无运行时依赖
709
+
710
+ ✅ **零运行时依赖**
711
+
712
+ ```json
713
+ {
714
+ "name": "data-structure-typed",
715
+ "dependencies": {},
716
+ "devDependencies": {
717
+ "typescript": "^5.0.0",
718
+ "jest": "^29.0.0"
719
+ }
720
+ }
721
+ ```
722
+
723
+ **好处:**
724
+ - 无依赖项的供应链攻击
725
+ - 无需依赖项的安全更新
726
+ - 更小的打包大小
727
+ - 无传递依赖问题
728
+
729
+ ### 开发依赖
730
+
731
+ 所有开发依赖都经过安全审计:
732
+
733
+ ```bash
734
+ npm audit # 始终干净(零漏洞)
735
+ ```
736
+
737
+ ---
738
+
739
+ ## 安全使用模式
740
+
741
+ ### 模式 1:有界集合
742
+
743
+ ```typescript
744
+ class SafeTree<K, V> extends RedBlackTree<K, V> {
745
+ private readonly maxSize: number;
746
+
747
+ constructor(maxSize: number = 100000) {
748
+ super();
749
+ this.maxSize = maxSize;
750
+ }
751
+
752
+ set(key: K, value: V): this {
753
+ if (this.size >= this.maxSize && !this.has(key)) {
754
+ throw new Error(`集合超过最大大小:${this.maxSize}`);
755
+ }
756
+ return super.set(key, value);
757
+ }
758
+ }
759
+ ```
760
+
761
+ ### 模式 2:验证输入
762
+
763
+ ```typescript
764
+ function processUntrustedData(data: unknown): void {
765
+ // 1. 验证结构
766
+ if (!isArray(data)) {
767
+ throw new TypeError('期望是数组');
768
+ }
769
+
770
+ // 2. 验证项目
771
+ const validItems = data.filter(isValidItem);
772
+
773
+ // 3. 在结构中使用
774
+ const tree = new RedBlackTree<number, string>();
775
+
776
+ for (const item of validItems) {
777
+ tree.set(item.id, item.name);
778
+ }
779
+ }
780
+
781
+ function isValidItem(item: unknown): item is { id: number; name: string } {
782
+ return (
783
+ typeof item === 'object' &&
784
+ item !== null &&
785
+ typeof (item as any).id === 'number' &&
786
+ typeof (item as any).name === 'string'
787
+ );
788
+ }
789
+ ```
790
+
791
+ ### 模式 3:超时保护
792
+
793
+ ```typescript
794
+ async function processWithTimeout<T>(
795
+ fn: () => T,
796
+ timeoutMs: number
797
+ ): Promise<T> {
798
+ return Promise.race([
799
+ Promise.resolve(fn()),
800
+ new Promise<never>((_, reject) =>
801
+ setTimeout(() => reject(new Error('超时')), timeoutMs)
802
+ )
803
+ ]);
804
+ }
805
+
806
+ // 使用
807
+ const tree = new RedBlackTree();
808
+ await processWithTimeout(() => {
809
+ tree.addMany(items);
810
+ }, 5000); // 5 秒超时
811
+ ```
812
+
813
+ ### 模式 4:快照操作
814
+
815
+ ```typescript
816
+ function batchDelete<K, V>(
817
+ tree: RedBlackTree<K, V>,
818
+ predicate: (v: V, k?: K) => boolean
819
+ ): number {
820
+ const snapshot = [...tree.entries()];
821
+ let deleted = 0;
822
+
823
+ for (const [key, value] of snapshot) {
824
+ if (predicate(value, key)) {
825
+ if (tree.delete(key)) {
826
+ deleted++;
827
+ }
828
+ }
829
+ }
830
+
831
+ return deleted;
832
+ }
833
+ ```
834
+
835
+ ---
836
+
837
+ ## 已知限制
838
+
839
+ ### 时序攻击
840
+
841
+ **库不是恒定时间的:**
842
+
843
+ ```typescript
844
+ // 搜索时间取决于树深度(对数但可变)
845
+ tree.get(key); // 可能需要不同的时间
846
+
847
+ // 仅在非加密上下文中使用
848
+ // 不要用于加密密钥存储
849
+ ```
850
+
851
+ ### 栈深度
852
+
853
+ **非常大的结构可能导致基于递归的操作的栈问题:**
854
+
855
+ ```typescript
856
+ // ❌ 风险:使用 DFS 的深树
857
+ const largeTree = new RedBlackTree();
858
+ for (let i = 0; i < 1000000; i++) {
859
+ largeTree.set(i, i); // 可能很深的树
860
+ }
861
+
862
+ // RedBlackTree 维护 O(log n) 深度,所以安全
863
+ // 没有平衡的 BST 可能达到 O(n) 深度
864
+ ```
865
+
866
+ ### 弱比较器
867
+
868
+ **库信任提供的比较器:**
869
+
870
+ ```typescript
871
+ // ❌ 用户错误:错误的比较器
872
+ const tree = new RedBlackTree((a, b) => {
873
+ return Math.random() - 0.5; // 随机!
874
+ });
875
+
876
+ // 库假设比较器是确定性的
877
+ // 提供有效比较器是用户的责任
878
+ ```
879
+
880
+ ---
881
+
882
+ ## 安全更新策略
883
+
884
+ ### 报告漏洞
885
+
886
+ **不要为安全漏洞打开公开的 GitHub 问题。**
887
+
888
+ 相反:
889
+ 1. 电子邮件:security@example.com(如果适用)
890
+ 2. 或使用 GitHub Security Advisories 私密报告
891
+ 3. 包括:描述、影响、概念证明、建议修复
892
+
893
+ ### 响应时间表
894
+
895
+ - **第 0 天**:初步确认
896
+ - **第 1-3 天**:分类和影响评估
897
+ - **第 3-7 天**:修复开发
898
+ - **第 7-14 天**:测试和验证
899
+ - **第 14 天**:发布安全版本
900
+
901
+ ### 披露策略
902
+
903
+ **负责任的披露:**
904
+ - 公开披露前 90 天禁运期
905
+ - 在公开声明前发布修复
906
+ - 向报告者致谢(如果需要)
907
+ - 为关键问题分配 CVE
908
+
909
+ ### 补丁发布计划
910
+
911
+ 安全补丁立即发布为:
912
+ - **2.0.x** - 当前稳定版本
913
+ - **1.x.x** - 扩展支持(如果适用)
914
+
915
+ ---
916
+
917
+ ## 安全检查清单
918
+
919
+ ### 对于库开发者
920
+
921
+ - ✅ 定期运行 `npm audit`
922
+ - ✅ 保持 TypeScript 更新
923
+ - ✅ 审查所有公共 API
924
+ - ✅ 测试错误处理
925
+ - ✅ 记录安全考虑
926
+ - ✅ 监控 GitHub Security Advisories
927
+
928
+ ### 对于库用户
929
+
930
+ - ✅ 使用严格的 TypeScript(`strict: true`)
931
+ - ✅ 验证所有外部输入
932
+ - ✅ 限制结构大小
933
+ - ✅ 不要在迭代期间变更
934
+ - ✅ 提供有效的纯比较器
935
+ - ✅ 保持 TypeScript 更新
936
+
937
+ ---
938
+
939
+ ## 其他资源
940
+
941
+ - **[SPECIFICATION.md](./SPECIFICATION.zh-CN.md)** - 技术规范
942
+ - **[ARCHITECTURE.md](./ARCHITECTURE.md)** - 设计决策
943
+ - **[PERFORMANCE.md](./PERFORMANCE.md)** - 性能特征
944
+ - **[GUIDES.md](./GUIDES.md)** - 使用示例
945
+ - **OWASP** - https://owasp.org(安全最佳实践)
946
+ - **CWE** - https://cwe.mitre.org(弱点分类)
947
+
948
+ ---
949
+
950
+ ## 总结
951
+
952
+ **data-structure-typed 通过以下原则对一般用途是安全的:**
953
+
954
+ 1. **信任 TypeScript** - 使用严格模式实现类型安全
955
+ 2. **限制输入** - 在应用程序级别强制执行最大大小
956
+ 3. **验证比较器** - 确保它们是纯的和确定性的
957
+ 4. **快照变更** - 永远不要在迭代期间变更
958
+ 5. **监控使用** - 跟踪结构大小和操作时间
959
+
960
+ **对于加密安全:** 这不是正确的库。使用专用的加密库,如 TweetNaCl.js、libsodium 或 crypto-js。
961
+
962
+ ---
963
+
964
+ **维护者:** [@zrwusa](https://github.com/zrwusa)
965
+ **许可证:** MIT
966
+ **最后更新:** 2026年1月