Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/v7.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ function v7(options, buf, offset) {
b[i++] = _msecs & 0xff;

// [byte 6] - set 4 bits of version (7) with first 4 bits seq_hi
b[i++] = ((seqHigh >>> 4) & 0x0f) | 0x70;
b[i++] = ((seqHigh >>> 8) & 0x0f) | 0x70;

// [byte 7] remaining 8 bits of seq_hi
b[i++] = seqHigh & 0xff;
Expand Down
36 changes: 35 additions & 1 deletion test/unit/v7.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import assert from 'assert';
import v7 from '../../src/v7.js';
import stringify from '../../src/stringify.js';

/**
* fixture bit layout:
Expand Down Expand Up @@ -154,7 +155,7 @@ describe('v7', () => {
seq,
});

assert.strictEqual(uuid.substr(0, 25), '017f22e2-79b0-7fff-bfff-f');
assert.strictEqual(uuid.substr(0, 25), '017f22e2-79b0-7dff-bfff-f');
});

test('internal seq is reset upon timestamp change', () => {
Expand All @@ -169,4 +170,37 @@ describe('v7', () => {

assert(uuid.indexOf('fff') !== 15);
});

test('flipping bits changes the result', () => {
const asBigInt = (buf) => buf.reduce((l, r) => (BigInt(l) << 8n) | BigInt(r));
const flip = (data, n) => data ^ (1n << (127n - n));
const optionsFrom = (data) => {
const ms = data >> (128n - 48n);
const hi = (data >> (43n + 19n + 2n)) & 0xfffn;
const lo = (data >> 43n) & 0x7ffffn;
const r = data & 0x7ff_ffff_ffffn;
return {
msecs: Number(ms),
seq: Number((hi << 19n) | lo),
random: [
...Array(10).fill(0),
...Array(6)
.fill(0)
.map((_, i) => Number((r >> (BigInt(i) * 8n)) & 0xffn))
.reverse(),
],
};
};
const buf = new Uint8Array(16);
const data = asBigInt(v7({}, buf));
const id = stringify(buf);
for (let i = 0; i < 128; ++i) {
if ([48, 49, 50, 51, 64, 65].includes(i)) {
continue;
}
const flipped = flip(data, BigInt(i));
assert(asBigInt(v7(optionsFrom(flipped), buf)) === flipped);
assert(stringify(buf) !== id);
}
});
});