data-structure-typed 2.2.1 → 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.
- package/CHANGELOG.md +3 -1
- package/README.md +440 -1190
- package/README_CN.md +509 -0
- package/SECURITY.md +962 -11
- package/SECURITY.zh-CN.md +966 -0
- package/SPECIFICATION.md +689 -30
- package/SPECIFICATION.zh-CN.md +715 -0
- package/SPONSOR.zh-CN.md +62 -0
- package/SPONSOR_POLISHED.md +62 -0
- package/benchmark/report.html +1 -1
- package/benchmark/report.json +215 -172
- package/dist/cjs/index.cjs +163 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +164 -0
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +163 -0
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +164 -0
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +96 -2
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +103 -7
- package/dist/types/data-structures/binary-tree/bst.d.ts +156 -13
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +84 -35
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
- package/dist/types/data-structures/graph/directed-graph.d.ts +126 -1
- package/dist/types/data-structures/graph/undirected-graph.d.ts +160 -1
- package/dist/types/data-structures/hash/hash-map.d.ts +110 -27
- package/dist/types/data-structures/heap/heap.d.ts +107 -58
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +72 -404
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +121 -5
- package/dist/types/data-structures/queue/deque.d.ts +95 -67
- package/dist/types/data-structures/queue/queue.d.ts +90 -34
- package/dist/types/data-structures/stack/stack.d.ts +58 -40
- package/dist/types/data-structures/trie/trie.d.ts +109 -47
- package/dist/types/interfaces/binary-tree.d.ts +1 -0
- package/dist/umd/data-structure-typed.js +164 -0
- package/dist/umd/data-structure-typed.js.map +1 -1
- package/dist/umd/data-structure-typed.min.js +3 -3
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +3 -2
- package/src/data-structures/binary-tree/avl-tree.ts +96 -2
- package/src/data-structures/binary-tree/binary-tree.ts +117 -7
- package/src/data-structures/binary-tree/bst.ts +322 -13
- package/src/data-structures/binary-tree/red-black-tree.ts +84 -35
- package/src/data-structures/binary-tree/tree-multi-map.ts +2 -2
- package/src/data-structures/graph/directed-graph.ts +126 -1
- package/src/data-structures/graph/undirected-graph.ts +160 -1
- package/src/data-structures/hash/hash-map.ts +110 -27
- package/src/data-structures/heap/heap.ts +107 -58
- package/src/data-structures/linked-list/doubly-linked-list.ts +72 -404
- package/src/data-structures/linked-list/singly-linked-list.ts +121 -5
- package/src/data-structures/queue/deque.ts +95 -67
- package/src/data-structures/queue/queue.ts +90 -34
- package/src/data-structures/stack/stack.ts +58 -40
- package/src/data-structures/trie/trie.ts +109 -47
- package/src/interfaces/binary-tree.ts +2 -0
- package/test/performance/benchmark-runner.ts +14 -11
- package/test/performance/data-structures/binary-tree/avl-tree.test.ts +8 -8
- package/test/performance/data-structures/binary-tree/binary-tree-overall.test.ts +8 -8
- package/test/performance/data-structures/binary-tree/binary-tree.test.ts +6 -6
- package/test/performance/data-structures/binary-tree/bst.test.ts +5 -5
- package/test/performance/data-structures/binary-tree/red-black-tree.test.ts +10 -10
- package/test/performance/reportor.ts +2 -1
- package/test/performance/single-suite-runner.ts +7 -4
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +117 -0
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +166 -0
- package/test/unit/data-structures/binary-tree/bst.test.ts +766 -8
- package/test/unit/data-structures/binary-tree/red-black-tree.test.ts +89 -37
- package/test/unit/data-structures/graph/directed-graph.test.ts +133 -0
- package/test/unit/data-structures/graph/undirected-graph.test.ts +167 -0
- package/test/unit/data-structures/hash/hash-map.test.ts +149 -3
- package/test/unit/data-structures/heap/heap.test.ts +182 -47
- package/test/unit/data-structures/linked-list/doubly-linked-list.test.ts +118 -14
- package/test/unit/data-structures/linked-list/singly-linked-list.test.ts +121 -0
- package/test/unit/data-structures/queue/deque.test.ts +98 -67
- package/test/unit/data-structures/queue/queue.test.ts +85 -51
- package/test/unit/data-structures/stack/stack.test.ts +142 -33
- package/test/unit/data-structures/trie/trie.test.ts +135 -39
- package/tsup.leetcode.config.js +99 -0
- package/typedoc.json +2 -1
- package/POSTS_zh-CN.md +0 -54
- package/README_zh-CN.md +0 -1208
- package/SPECIFICATION_zh-CN.md +0 -81
package/SECURITY.md
CHANGED
|
@@ -1,15 +1,966 @@
|
|
|
1
|
-
# Security
|
|
1
|
+
# SECURITY: data-structure-typed Security Guide
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Version:** 2.0.4
|
|
4
|
+
**Last Updated:** January 2026
|
|
5
|
+
**Status:** ✅ Actively Maintained
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|---------|--------------------|
|
|
7
|
-
| 1.30.x | :white_check_mark: |
|
|
8
|
-
| < 3.0 | :x: |
|
|
7
|
+
---
|
|
9
8
|
|
|
10
|
-
##
|
|
9
|
+
## Table of Contents
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
1. [Security Overview](#security-overview)
|
|
12
|
+
2. [Threat Model](#threat-model)
|
|
13
|
+
3. [Security Guarantees](#security-guarantees)
|
|
14
|
+
4. [Input Validation](#input-validation)
|
|
15
|
+
5. [Comparator Safety](#comparator-safety)
|
|
16
|
+
6. [Memory Management](#memory-management)
|
|
17
|
+
7. [Type Safety](#type-safety)
|
|
18
|
+
8. [Iteration Safety](#iteration-safety)
|
|
19
|
+
9. [Denial of Service (DoS) Protection](#denial-of-service-dos-protection)
|
|
20
|
+
10. [Dependency Security](#dependency-security)
|
|
21
|
+
11. [Secure Usage Patterns](#secure-usage-patterns)
|
|
22
|
+
12. [Known Limitations](#known-limitations)
|
|
23
|
+
13. [Security Update Policy](#security-update-policy)
|
|
24
|
+
14. [Reporting Security Issues](#reporting-security-issues)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Security Overview
|
|
29
|
+
|
|
30
|
+
**data-structure-typed** is a data structure library focused on performance and usability. Security considerations are primarily around **resource exhaustion**, **type safety**, and **safe iteration**.
|
|
31
|
+
|
|
32
|
+
### Scope
|
|
33
|
+
|
|
34
|
+
**This library is NOT designed to:**
|
|
35
|
+
- ❌ Encrypt or hash data
|
|
36
|
+
- ❌ Validate untrusted input
|
|
37
|
+
- ❌ Prevent timing attacks
|
|
38
|
+
- ❌ Protect against side-channel attacks
|
|
39
|
+
- ❌ Sanitize user input
|
|
40
|
+
|
|
41
|
+
**This library DOES protect against:**
|
|
42
|
+
- ✅ Buffer overflows (impossible in JavaScript)
|
|
43
|
+
- ✅ Type confusion attacks (TypeScript prevents at compile time)
|
|
44
|
+
- ✅ Null/undefined dereferences (defensive checks)
|
|
45
|
+
- ✅ Uncontrolled memory growth (clear APIs)
|
|
46
|
+
- ✅ Unsafe iteration patterns (documented behavior)
|
|
47
|
+
|
|
48
|
+
### Design Philosophy
|
|
49
|
+
|
|
50
|
+
Library follows **fail-fast** principle:
|
|
51
|
+
- **Loud**: Errors that indicate bugs throw exceptions
|
|
52
|
+
- **Silent**: Missing keys return undefined (standard behavior)
|
|
53
|
+
- **Safe**: Type system prevents category errors at compile time
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Threat Model
|
|
58
|
+
|
|
59
|
+
### Attack Vectors (In Scope)
|
|
60
|
+
|
|
61
|
+
#### 1. Unintended Memory Growth
|
|
62
|
+
|
|
63
|
+
**Risk:** Attacker adds millions of items, causing OOM
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
const tree = new RedBlackTree();
|
|
67
|
+
for (let i = 0; i < 1000000000; i++) {
|
|
68
|
+
tree.set(i, 'data'); // Unbounded growth
|
|
69
|
+
}
|
|
70
|
+
// Process runs out of memory
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Mitigation:**
|
|
74
|
+
- Monitor `structure.size` property
|
|
75
|
+
- Implement size limits in application logic
|
|
76
|
+
- Clear structures when done: `structure.clear()`
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// ✅ Safe pattern
|
|
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('Structure at capacity');
|
|
86
|
+
}
|
|
87
|
+
tree.set(key, value);
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### 2. Comparator Exceptions
|
|
92
|
+
|
|
93
|
+
**Risk:** Malicious comparator throws or crashes
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
const tree = new RedBlackTree<number>(
|
|
97
|
+
(a, b) => {
|
|
98
|
+
if (a === null) throw new Error('Hacked!');
|
|
99
|
+
return a - b;
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
tree.set(null, 'value'); // Throws unhandled exception
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Mitigation:**
|
|
107
|
+
- Always wrap comparators in try-catch if untrusted
|
|
108
|
+
- Use pure functions (no side effects)
|
|
109
|
+
- Validate inputs before tree operations
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// ✅ Safe pattern
|
|
113
|
+
function safeComparator(a, b) {
|
|
114
|
+
try {
|
|
115
|
+
if (!isNumber(a) || !isNumber(b)) {
|
|
116
|
+
throw new TypeError('Expected numbers');
|
|
117
|
+
}
|
|
118
|
+
return a - b;
|
|
119
|
+
} catch (error) {
|
|
120
|
+
logger.error('Comparator failed:', error);
|
|
121
|
+
throw error; // Explicit error handling
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const tree = new RedBlackTree<number>(safeComparator);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### 3. Iterator Mutation
|
|
129
|
+
|
|
130
|
+
**Risk:** Mutating structure during iteration causes inconsistent state
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
const tree = new RedBlackTree([1, 2, 3]);
|
|
134
|
+
|
|
135
|
+
for (const item of tree) {
|
|
136
|
+
tree.delete(item); // Modifying while iterating
|
|
137
|
+
// Behavior is undefined
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Mitigation:**
|
|
142
|
+
- Don't mutate during iteration
|
|
143
|
+
- Collect mutations and apply after
|
|
144
|
+
- Use snapshot iteration if needed
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
// ✅ Safe pattern
|
|
148
|
+
const tree = new RedBlackTree([1, 2, 3]);
|
|
149
|
+
|
|
150
|
+
// Method 1: Collect mutations
|
|
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
|
+
// Method 2: Snapshot iteration
|
|
158
|
+
const items = [...tree]; // Create snapshot
|
|
159
|
+
items.forEach(item => tree.delete(item));
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### 4. Type Confusion
|
|
163
|
+
|
|
164
|
+
**Risk:** Passing wrong types bypasses type system at runtime
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
const tree = new RedBlackTree<number>();
|
|
168
|
+
|
|
169
|
+
// At runtime, TypeScript types are erased
|
|
170
|
+
tree.set('not-a-number' as any, 'value');
|
|
171
|
+
// Type system didn't prevent this
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Mitigation:**
|
|
175
|
+
- Use strict TypeScript settings: `strict: true`
|
|
176
|
+
- Avoid `as any` assertions in untrusted code
|
|
177
|
+
- Validate types at runtime boundaries
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
// ✅ Safe pattern
|
|
181
|
+
interface ValidInput {
|
|
182
|
+
id: number;
|
|
183
|
+
name: string;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function addFromUntrustedSource(input: unknown) {
|
|
187
|
+
if (!isValidInput(input)) {
|
|
188
|
+
throw new TypeError('Invalid input');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const tree = new RedBlackTree<number, ValidInput>();
|
|
192
|
+
tree.set(input.id, input); // Now type-safe
|
|
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. Infinite Loops
|
|
206
|
+
|
|
207
|
+
**Risk:** Comparator causes infinite loop during tree operations
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
const tree = new RedBlackTree<number>(
|
|
211
|
+
(a, b) => {
|
|
212
|
+
// Intentionally broken comparator
|
|
213
|
+
return 0; // Always equal
|
|
214
|
+
}
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
tree.addMany([1, 2, 3, 4, 5]);
|
|
218
|
+
// May cause infinite loops or stack overflow
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Mitigation:**
|
|
222
|
+
- Use strict comparators: consistent and deterministic
|
|
223
|
+
- Test comparators with large datasets
|
|
224
|
+
- Set timeout limits for tree operations
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
// ✅ Safe pattern
|
|
228
|
+
function strictComparator<T>(a: T, b: T): number {
|
|
229
|
+
if (a < b) return -1;
|
|
230
|
+
if (a > b) return 1;
|
|
231
|
+
return 0; // Only returns -1, 0, or 1
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const tree = new RedBlackTree<number>(strictComparator);
|
|
235
|
+
|
|
236
|
+
// With timeout wrapper (application level)
|
|
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
|
+
## Security Guarantees
|
|
254
|
+
|
|
255
|
+
### What This Library Guarantees
|
|
256
|
+
|
|
257
|
+
| Guarantee | Status | Details |
|
|
258
|
+
|-----------|--------|---------|
|
|
259
|
+
| **No arbitrary code execution** | ✅ 100% | Only runs provided comparators |
|
|
260
|
+
| **No data leaks** | ✅ 100% | No external communication |
|
|
261
|
+
| **No uncontrolled memory growth** | ⚠️ Partial | Application must set size limits |
|
|
262
|
+
| **Type safety** | ✅ 100% | TypeScript prevents type confusion |
|
|
263
|
+
| **Iterator safety** | ✅ 100% | Clear documented behavior |
|
|
264
|
+
| **Protection from invalid input** | ⚠️ Partial | Application validates input |
|
|
265
|
+
|
|
266
|
+
### What This Library Does NOT Guarantee
|
|
267
|
+
|
|
268
|
+
| Guarantee | Status | Details |
|
|
269
|
+
|-----------|--------|---------|
|
|
270
|
+
| **Constant-time operations** | ❌ No | Timing attacks possible (crypto use only) |
|
|
271
|
+
| **Protection from DoS** | ⚠️ No | Application must rate-limit |
|
|
272
|
+
| **Untrusted input handling** | ❌ No | Input validation is application's responsibility |
|
|
273
|
+
| **Secure random numbers** | ❌ No | Not applicable (no randomness) |
|
|
274
|
+
| **Cryptographic security** | ❌ No | Not a crypto library |
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Input Validation
|
|
279
|
+
|
|
280
|
+
### Comparators Must Be Pure
|
|
281
|
+
|
|
282
|
+
**Unsafe: Side effects or external state**
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
// ❌ DO NOT DO THIS
|
|
286
|
+
let callCount = 0;
|
|
287
|
+
const tree = new RedBlackTree<number>((a, b) => {
|
|
288
|
+
callCount++; // Side effect!
|
|
289
|
+
return a - b;
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
// ❌ DO NOT DO THIS
|
|
293
|
+
const config = getConfig();
|
|
294
|
+
const tree = new RedBlackTree<number>((a, b) => {
|
|
295
|
+
const weight = config.weight; // Mutable external state
|
|
296
|
+
return (a - b) * weight;
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// ✅ DO THIS
|
|
300
|
+
const tree = new RedBlackTree<number>((a, b) => {
|
|
301
|
+
return a - b; // Pure function
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
const weightedTree = new RedBlackTree<number>((a, b) => {
|
|
305
|
+
return (a - b) * FIXED_WEIGHT; // Fixed constant
|
|
306
|
+
});
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Validate Comparators Upfront
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
// ✅ Validate comparator before using
|
|
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
|
+
// Comparator must return -1, 0, or 1 (or at least consistent)
|
|
319
|
+
if (Math.abs(result) > 1 && result !== 0) {
|
|
320
|
+
return false; // Invalid comparator
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Transitivity check
|
|
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; // Comparator violates transitivity
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Use validated comparator
|
|
339
|
+
const myComparator = (a: number, b: number) => a - b;
|
|
340
|
+
if (!validateComparator(myComparator, [1, 2, 3])) {
|
|
341
|
+
throw new Error('Invalid comparator');
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const tree = new RedBlackTree<number>(myComparator);
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Bound Structure Size
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
// ✅ Enforce maximum size
|
|
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(`Tree exceeds max size of ${this.maxSize}`);
|
|
362
|
+
}
|
|
363
|
+
return super.set(key, value);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Use with confidence
|
|
368
|
+
const tree = new BoundedTree(10000);
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Comparator Safety
|
|
374
|
+
|
|
375
|
+
### Comparator Requirements
|
|
376
|
+
|
|
377
|
+
**A valid comparator must:**
|
|
378
|
+
|
|
379
|
+
1. **Return consistent values**
|
|
380
|
+
```typescript
|
|
381
|
+
const comp = (a, b) => {
|
|
382
|
+
// ✅ Always returns same value for same inputs
|
|
383
|
+
return a - b;
|
|
384
|
+
};
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
2. **Respect transitivity**
|
|
388
|
+
```typescript
|
|
389
|
+
// If a < b and b < c, then 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 // must be true
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
3. **Handle all input types**
|
|
397
|
+
```typescript
|
|
398
|
+
const comp = (a, b) => {
|
|
399
|
+
// Handle 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
|
+
### Dangerous Comparators
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
// ❌ DO NOT: Random comparators
|
|
410
|
+
const random = (a, b) => Math.random() - 0.5;
|
|
411
|
+
|
|
412
|
+
// ❌ DO NOT: Non-deterministic
|
|
413
|
+
const nonDet = (() => {
|
|
414
|
+
let x = 0;
|
|
415
|
+
return (a, b) => (x++, a - b);
|
|
416
|
+
})();
|
|
417
|
+
|
|
418
|
+
// ❌ DO NOT: Side effects
|
|
419
|
+
const withSideEffect = (a, b) => {
|
|
420
|
+
console.log(a, b); // Side effect
|
|
421
|
+
return a - b;
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
// ❌ DO NOT: Throwing errors
|
|
425
|
+
const throws = (a, b) => {
|
|
426
|
+
throw new Error('Oops');
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
// ❌ DO NOT: Inconsistent logic
|
|
430
|
+
const inconsistent = (a, b) => {
|
|
431
|
+
return Math.random() > 0.5 ? a - b : b - a;
|
|
432
|
+
};
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## Memory Management
|
|
438
|
+
|
|
439
|
+
### Structure Lifecycle
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
// ✅ Proper lifecycle management
|
|
443
|
+
|
|
444
|
+
// 1. Create with expected size
|
|
445
|
+
const tree = new RedBlackTree<number, object>();
|
|
446
|
+
|
|
447
|
+
// 2. Add items
|
|
448
|
+
for (const item of items) {
|
|
449
|
+
tree.set(item.id, item);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// 3. Use structure
|
|
453
|
+
const value = tree.get(key);
|
|
454
|
+
|
|
455
|
+
// 4. Clean up when done
|
|
456
|
+
tree.clear(); // O(n) operation
|
|
457
|
+
|
|
458
|
+
// 5. Allow garbage collection
|
|
459
|
+
tree = null; // Or let it go out of scope
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### Garbage Collection
|
|
463
|
+
|
|
464
|
+
**Library does NOT prevent garbage collection:**
|
|
465
|
+
|
|
466
|
+
```typescript
|
|
467
|
+
// JavaScript will GC unused structures
|
|
468
|
+
{
|
|
469
|
+
const tree = new RedBlackTree();
|
|
470
|
+
tree.addMany([...]);
|
|
471
|
+
// tree goes out of scope
|
|
472
|
+
// JavaScript automatically frees memory
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// For browser memory management
|
|
476
|
+
function processLargeDataset() {
|
|
477
|
+
const tree = new RedBlackTree();
|
|
478
|
+
|
|
479
|
+
try {
|
|
480
|
+
// Process data
|
|
481
|
+
for (const item of dataset) {
|
|
482
|
+
tree.set(item.id, item);
|
|
483
|
+
}
|
|
484
|
+
return tree.size;
|
|
485
|
+
} finally {
|
|
486
|
+
tree.clear(); // Explicit cleanup
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### Node References
|
|
492
|
+
|
|
493
|
+
**Be careful with cached references:**
|
|
494
|
+
|
|
495
|
+
```typescript
|
|
496
|
+
// ❌ Potential memory leak
|
|
497
|
+
const nodes = [];
|
|
498
|
+
for (const item of items) {
|
|
499
|
+
const node = tree.getNode(item.id);
|
|
500
|
+
nodes.push(node); // Keeps reference
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// Tree nodes hold references to their neighbors
|
|
504
|
+
// This prevents garbage collection
|
|
505
|
+
|
|
506
|
+
// ✅ Don't keep references to internal nodes
|
|
507
|
+
for (const item of items) {
|
|
508
|
+
const value = tree.get(item.id); // Get value, not node
|
|
509
|
+
// Process value
|
|
510
|
+
}
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
## Type Safety
|
|
516
|
+
|
|
517
|
+
### Strict TypeScript Configuration
|
|
518
|
+
|
|
519
|
+
**Recommended 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
|
+
### Type-Safe Usage
|
|
540
|
+
|
|
541
|
+
```typescript
|
|
542
|
+
// ✅ Type-safe
|
|
543
|
+
const tree = new RedBlackTree<number, string>();
|
|
544
|
+
tree.set(1, 'Alice');
|
|
545
|
+
const name = tree.get(1); // Type: string | undefined
|
|
546
|
+
|
|
547
|
+
// ❌ Unsafe (avoided with strict mode)
|
|
548
|
+
const anyTree = new RedBlackTree() as any;
|
|
549
|
+
anyTree.set('wrong type', 123); // TypeScript won't catch this
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### Generic Constraints
|
|
553
|
+
|
|
554
|
+
```typescript
|
|
555
|
+
// ✅ Constrain types
|
|
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
|
+
// ✅ Union types for flexibility
|
|
565
|
+
type ValidKey = number | string | symbol;
|
|
566
|
+
const tree = new RedBlackTree<ValidKey, unknown>();
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
---
|
|
570
|
+
|
|
571
|
+
## Iteration Safety
|
|
572
|
+
|
|
573
|
+
### Safe Iteration Patterns
|
|
574
|
+
|
|
575
|
+
**Pattern 1: Snapshot before mutation**
|
|
576
|
+
|
|
577
|
+
```typescript
|
|
578
|
+
// ✅ SAFE: Create snapshot first
|
|
579
|
+
const tree = new RedBlackTree([1, 2, 3, 4, 5]);
|
|
580
|
+
|
|
581
|
+
const items = [...tree]; // Snapshot
|
|
582
|
+
items.forEach(item => {
|
|
583
|
+
tree.delete(item); // Safe to mutate now
|
|
584
|
+
});
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
**Pattern 2: Collect then apply**
|
|
588
|
+
|
|
589
|
+
```typescript
|
|
590
|
+
// ✅ SAFE: Collect mutations first
|
|
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)); // Apply mutations
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
**Pattern 3: Functional approach**
|
|
604
|
+
|
|
605
|
+
```typescript
|
|
606
|
+
// ✅ SAFE: Functional transformations
|
|
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
|
+
// Result is new structure, original unchanged
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
### Unsafe Iteration
|
|
617
|
+
|
|
618
|
+
```typescript
|
|
619
|
+
// ❌ DO NOT DO THIS
|
|
620
|
+
const tree = new RedBlackTree([1, 2, 3]);
|
|
621
|
+
|
|
622
|
+
for (const item of tree) {
|
|
623
|
+
if (condition(item)) {
|
|
624
|
+
tree.delete(item); // Undefined behavior!
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// ❌ DO NOT DO THIS
|
|
629
|
+
const tree = new RedBlackTree([1, 2, 3]);
|
|
630
|
+
|
|
631
|
+
[...tree].forEach(item => {
|
|
632
|
+
tree.set(item, 'new'); // May cause issues
|
|
633
|
+
});
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
---
|
|
637
|
+
|
|
638
|
+
## Denial of Service (DoS) Protection
|
|
639
|
+
|
|
640
|
+
### Attack Vector: Expensive Comparisons
|
|
641
|
+
|
|
642
|
+
**Risk:** Comparator is very slow
|
|
643
|
+
|
|
644
|
+
```typescript
|
|
645
|
+
// ❌ Attacker provides slow comparator
|
|
646
|
+
const tree = new RedBlackTree<number>((a, b) => {
|
|
647
|
+
// Simulate expensive operation
|
|
648
|
+
for (let i = 0; i < 1000000; i++) {
|
|
649
|
+
Math.sqrt(i);
|
|
650
|
+
}
|
|
651
|
+
return a - b;
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
tree.addMany([...1000 items...]); // Takes forever
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
**Mitigation:**
|
|
658
|
+
|
|
659
|
+
```typescript
|
|
660
|
+
// ✅ Set timeout for tree operations
|
|
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('Tree operation exceeded timeout');
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
return result;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// Usage
|
|
673
|
+
withTimeout(() => tree.addMany(items), 1000);
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
### Attack Vector: Hash Collision
|
|
677
|
+
|
|
678
|
+
**Risk:** Malicious keys cause hash-like collisions
|
|
679
|
+
|
|
680
|
+
```typescript
|
|
681
|
+
// This is not applicable to comparison-based trees
|
|
682
|
+
// Skip lists and other hash-based structures at risk
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
### Attack Vector: Stack Overflow
|
|
686
|
+
|
|
687
|
+
**Risk:** Very deep recursive structure
|
|
688
|
+
|
|
689
|
+
```typescript
|
|
690
|
+
// ❌ Create deeply unbalanced tree (if using unbalanced BST)
|
|
691
|
+
const bst = new BST();
|
|
692
|
+
for (let i = 0; i < 10000; i++) {
|
|
693
|
+
bst.add(i); // Creates linear chain, not balanced tree
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// For balanced trees (RedBlackTree, AVLTree):
|
|
697
|
+
// ✅ Automatically balanced
|
|
698
|
+
const rbTree = new RedBlackTree();
|
|
699
|
+
for (let i = 0; i < 10000; i++) {
|
|
700
|
+
rbTree.set(i, i); // Always balanced, logarithmic depth
|
|
701
|
+
}
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
---
|
|
705
|
+
|
|
706
|
+
## Dependency Security
|
|
707
|
+
|
|
708
|
+
### No Runtime Dependencies
|
|
709
|
+
|
|
710
|
+
✅ **Zero runtime dependencies**
|
|
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
|
+
**Benefit:**
|
|
724
|
+
- No supply chain attacks from dependencies
|
|
725
|
+
- No security updates needed for dependencies
|
|
726
|
+
- Smaller bundle size
|
|
727
|
+
- No transitive dependency issues
|
|
728
|
+
|
|
729
|
+
### Development Dependencies
|
|
730
|
+
|
|
731
|
+
All dev dependencies are security-audited:
|
|
732
|
+
|
|
733
|
+
```bash
|
|
734
|
+
npm audit # Always clean (zero vulnerabilities)
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
---
|
|
738
|
+
|
|
739
|
+
## Secure Usage Patterns
|
|
740
|
+
|
|
741
|
+
### Pattern 1: Bounded Collections
|
|
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(`Collection exceeds max size: ${this.maxSize}`);
|
|
755
|
+
}
|
|
756
|
+
return super.set(key, value);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
### Pattern 2: Validated Input
|
|
762
|
+
|
|
763
|
+
```typescript
|
|
764
|
+
function processUntrustedData(data: unknown): void {
|
|
765
|
+
// 1. Validate structure
|
|
766
|
+
if (!isArray(data)) {
|
|
767
|
+
throw new TypeError('Expected array');
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// 2. Validate items
|
|
771
|
+
const validItems = data.filter(isValidItem);
|
|
772
|
+
|
|
773
|
+
// 3. Use in structure
|
|
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
|
+
### Pattern 3: Timeout Protection
|
|
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('Timeout')), timeoutMs)
|
|
802
|
+
)
|
|
803
|
+
]);
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// Usage
|
|
807
|
+
const tree = new RedBlackTree();
|
|
808
|
+
await processWithTimeout(() => {
|
|
809
|
+
tree.addMany(items);
|
|
810
|
+
}, 5000); // 5 second timeout
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
### Pattern 4: Snapshot Operations
|
|
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
|
+
## Known Limitations
|
|
838
|
+
|
|
839
|
+
### Timing Attacks
|
|
840
|
+
|
|
841
|
+
**Library is NOT constant-time:**
|
|
842
|
+
|
|
843
|
+
```typescript
|
|
844
|
+
// Search time depends on tree depth (logarithmic but variable)
|
|
845
|
+
tree.get(key); // May take different times
|
|
846
|
+
|
|
847
|
+
// Use only in non-cryptographic contexts
|
|
848
|
+
// DO NOT use for cryptographic key storage
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
### Stack Depth
|
|
852
|
+
|
|
853
|
+
**Very large structures may cause stack issues with recursion-based operations:**
|
|
854
|
+
|
|
855
|
+
```typescript
|
|
856
|
+
// ❌ Risk: Deep tree with DFS
|
|
857
|
+
const largeTree = new RedBlackTree();
|
|
858
|
+
for (let i = 0; i < 1000000; i++) {
|
|
859
|
+
largeTree.set(i, i); // Very deep tree possible
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// RedBlackTree maintains O(log n) depth, so safe
|
|
863
|
+
// BST without balancing could reach O(n) depth
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
### Weak Comparators
|
|
867
|
+
|
|
868
|
+
**Library trusts provided comparators:**
|
|
869
|
+
|
|
870
|
+
```typescript
|
|
871
|
+
// ❌ User error: Bad comparator
|
|
872
|
+
const tree = new RedBlackTree((a, b) => {
|
|
873
|
+
return Math.random() - 0.5; // Random!
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
// Library assumes comparator is deterministic
|
|
877
|
+
// User responsibility to provide valid comparator
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
---
|
|
881
|
+
|
|
882
|
+
## Security Update Policy
|
|
883
|
+
|
|
884
|
+
### Reporting Vulnerabilities
|
|
885
|
+
|
|
886
|
+
**DO NOT open public GitHub issues for security vulnerabilities.**
|
|
887
|
+
|
|
888
|
+
Instead:
|
|
889
|
+
1. Email: security@example.com (if applicable)
|
|
890
|
+
2. Or use GitHub Security Advisories private reporting
|
|
891
|
+
3. Include: Description, Impact, Proof of Concept, Suggested Fix
|
|
892
|
+
|
|
893
|
+
### Response Timeline
|
|
894
|
+
|
|
895
|
+
- **Day 0**: Initial acknowledgment
|
|
896
|
+
- **Day 1-3**: Triage and impact assessment
|
|
897
|
+
- **Day 3-7**: Fix development
|
|
898
|
+
- **Day 7-14**: Testing and validation
|
|
899
|
+
- **Day 14**: Security release published
|
|
900
|
+
|
|
901
|
+
### Disclosure Policy
|
|
902
|
+
|
|
903
|
+
**Responsible Disclosure:**
|
|
904
|
+
- 90-day embargo before public disclosure
|
|
905
|
+
- Fix released before public announcement
|
|
906
|
+
- Credit to reporter (if desired)
|
|
907
|
+
- CVE assignment for critical issues
|
|
908
|
+
|
|
909
|
+
### Patch Release Schedule
|
|
910
|
+
|
|
911
|
+
Security patches released immediately as:
|
|
912
|
+
- **2.0.x** - Current stable version
|
|
913
|
+
- **1.x.x** - Extended support (if applicable)
|
|
914
|
+
|
|
915
|
+
---
|
|
916
|
+
|
|
917
|
+
## Security Checklist
|
|
918
|
+
|
|
919
|
+
### For Library Developers
|
|
920
|
+
|
|
921
|
+
- ✅ Run `npm audit` regularly
|
|
922
|
+
- ✅ Keep TypeScript updated
|
|
923
|
+
- ✅ Review all public APIs
|
|
924
|
+
- ✅ Test error handling
|
|
925
|
+
- ✅ Document security considerations
|
|
926
|
+
- ✅ Monitor GitHub Security Advisories
|
|
927
|
+
|
|
928
|
+
### For Library Users
|
|
929
|
+
|
|
930
|
+
- ✅ Use strict TypeScript (`strict: true`)
|
|
931
|
+
- ✅ Validate all external input
|
|
932
|
+
- ✅ Bound structure sizes
|
|
933
|
+
- ✅ Don't mutate during iteration
|
|
934
|
+
- ✅ Provide valid, pure comparators
|
|
935
|
+
- ✅ Keep TypeScript updated
|
|
936
|
+
|
|
937
|
+
---
|
|
938
|
+
|
|
939
|
+
## Additional Resources
|
|
940
|
+
|
|
941
|
+
- **[SPECIFICATION.md](./SPECIFICATION.md)** - Technical specifications
|
|
942
|
+
- **[ARCHITECTURE.md](./ARCHITECTURE.md)** - Design decisions
|
|
943
|
+
- **[PERFORMANCE.md](./PERFORMANCE.md)** - Performance characteristics
|
|
944
|
+
- **[GUIDES.md](./GUIDES.md)** - Usage examples
|
|
945
|
+
- **OWASP** - https://owasp.org (security best practices)
|
|
946
|
+
- **CWE** - https://cwe.mitre.org (weakness taxonomy)
|
|
947
|
+
|
|
948
|
+
---
|
|
949
|
+
|
|
950
|
+
## Summary
|
|
951
|
+
|
|
952
|
+
**data-structure-typed is secure for general-purpose use with these principles:**
|
|
953
|
+
|
|
954
|
+
1. **Trust TypeScript** - Use strict mode for type safety
|
|
955
|
+
2. **Bound Inputs** - Enforce maximum sizes at application level
|
|
956
|
+
3. **Validate Comparators** - Ensure they're pure and deterministic
|
|
957
|
+
4. **Snapshot Mutations** - Never mutate during iteration
|
|
958
|
+
5. **Monitor Usage** - Track structure sizes and operation times
|
|
959
|
+
|
|
960
|
+
**For cryptographic security:** This is NOT the right library. Use dedicated crypto libraries like TweetNaCl.js, libsodium, or crypto-js.
|
|
961
|
+
|
|
962
|
+
---
|
|
963
|
+
|
|
964
|
+
**Maintained By:** [@zrwusa](https://github.com/zrwusa)
|
|
965
|
+
**License:** MIT
|
|
966
|
+
**Last Updated:** January 2026
|