Skip to content

Commit 5f99b1b

Browse files
authored
fix(NODE-3662): error checking to make sure that ObjectId results in object with correct properties (#467)
1 parent d388f1e commit 5f99b1b

File tree

2 files changed

+248
-69
lines changed

2 files changed

+248
-69
lines changed

src/objectid.ts

+35-35
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class ObjectId {
3131
_bsontype!: 'ObjectId';
3232

3333
/** @internal */
34-
static index = ~~(Math.random() * 0xffffff);
34+
static index = Math.floor(Math.random() * 0xffffff);
3535

3636
static cacheHexString: boolean;
3737

@@ -43,54 +43,54 @@ export class ObjectId {
4343
/**
4444
* Create an ObjectId type
4545
*
46-
* @param id - Can be a 24 character hex string, 12 byte binary Buffer, or a number.
46+
* @param inputId - Can be a 24 character hex string, 12 byte binary Buffer, or a number.
4747
*/
48-
constructor(id?: string | Buffer | number | ObjectIdLike | ObjectId) {
49-
if (!(this instanceof ObjectId)) return new ObjectId(id);
48+
constructor(inputId?: string | Buffer | number | ObjectIdLike | ObjectId) {
49+
if (!(this instanceof ObjectId)) return new ObjectId(inputId);
5050

51-
// Duck-typing to support ObjectId from different npm packages
52-
if (id instanceof ObjectId) {
53-
this[kId] = id.id;
54-
this.__id = id.__id;
55-
}
56-
57-
if (typeof id === 'object' && id && 'id' in id) {
58-
if ('toHexString' in id && typeof id.toHexString === 'function') {
59-
this[kId] = Buffer.from(id.toHexString(), 'hex');
51+
// workingId is set based on type of input and whether valid id exists for the input
52+
let workingId;
53+
if (typeof inputId === 'object' && inputId && 'id' in inputId) {
54+
if (typeof inputId.id !== 'string' && !ArrayBuffer.isView(inputId.id)) {
55+
throw new BSONTypeError(
56+
'Argument passed in must have an id that is of type string or Buffer'
57+
);
58+
}
59+
if ('toHexString' in inputId && typeof inputId.toHexString === 'function') {
60+
workingId = Buffer.from(inputId.toHexString(), 'hex');
6061
} else {
61-
this[kId] = typeof id.id === 'string' ? Buffer.from(id.id) : id.id;
62+
workingId = inputId.id;
6263
}
64+
} else {
65+
workingId = inputId;
6366
}
6467

65-
// The most common use case (blank id, new objectId instance)
66-
if (id == null || typeof id === 'number') {
68+
// the following cases use workingId to construct an ObjectId
69+
if (workingId == null || typeof workingId === 'number') {
70+
// The most common use case (blank id, new objectId instance)
6771
// Generate a new id
68-
this[kId] = ObjectId.generate(typeof id === 'number' ? id : undefined);
69-
// If we are caching the hex string
70-
if (ObjectId.cacheHexString) {
71-
this.__id = this.id.toString('hex');
72-
}
73-
}
74-
75-
if (ArrayBuffer.isView(id) && id.byteLength === 12) {
76-
this[kId] = ensureBuffer(id);
77-
}
78-
79-
if (typeof id === 'string') {
80-
if (id.length === 12) {
81-
const bytes = Buffer.from(id);
72+
this[kId] = ObjectId.generate(typeof workingId === 'number' ? workingId : undefined);
73+
} else if (ArrayBuffer.isView(workingId) && workingId.byteLength === 12) {
74+
this[kId] = ensureBuffer(workingId);
75+
} else if (typeof workingId === 'string') {
76+
if (workingId.length === 12) {
77+
const bytes = Buffer.from(workingId);
8278
if (bytes.byteLength === 12) {
8379
this[kId] = bytes;
80+
} else {
81+
throw new BSONTypeError('Argument passed in must be a string of 12 bytes');
8482
}
85-
} else if (id.length === 24 && checkForHexRegExp.test(id)) {
86-
this[kId] = Buffer.from(id, 'hex');
83+
} else if (workingId.length === 24 && checkForHexRegExp.test(workingId)) {
84+
this[kId] = Buffer.from(workingId, 'hex');
8785
} else {
8886
throw new BSONTypeError(
89-
'Argument passed in must be a Buffer or string of 12 bytes or a string of 24 hex characters'
87+
'Argument passed in must be a string of 12 bytes or a string of 24 hex characters'
9088
);
9189
}
90+
} else {
91+
throw new BSONTypeError('Argument passed in does not match the accepted types');
9292
}
93-
93+
// If we are caching the hex string
9494
if (ObjectId.cacheHexString) {
9595
this.__id = this.id.toString('hex');
9696
}
@@ -156,7 +156,7 @@ export class ObjectId {
156156
*/
157157
static generate(time?: number): Buffer {
158158
if ('number' !== typeof time) {
159-
time = ~~(Date.now() / 1000);
159+
time = Math.floor(Date.now() / 1000);
160160
}
161161

162162
const inc = ObjectId.getInc();

0 commit comments

Comments
 (0)