Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(NODE-3629): correct corpus runner and add null checks #464

Merged
merged 5 commits into from
Sep 28, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
582 changes: 582 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@rollup/plugin-typescript": "^6.0.0",
"@typescript-eslint/eslint-plugin": "^3.10.1",
"@typescript-eslint/parser": "^3.10.1",
"array-includes": "^3.1.3",
"benchmark": "^2.1.4",
"chai": "^4.2.0",
"downlevel-dts": "^0.7.0",
Expand All @@ -54,6 +55,7 @@
"mocha": "5.2.0",
"node-fetch": "^2.6.1",
"nyc": "^15.1.0",
"object.entries": "^1.1.4",
"prettier": "^2.1.1",
"rimraf": "^3.0.2",
"rollup": "^2.26.5",
Expand Down
13 changes: 7 additions & 6 deletions src/binary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ensureBuffer } from './ensure_buffer';
import { uuidHexStringToBuffer } from './uuid_utils';
import { UUID, UUIDExtended } from './uuid';
import type { EJSONOptions } from './extended_json';
import { BSONError, BSONTypeError } from './error';

/** @public */
export type BinarySequence = Uint8Array | Buffer | number[];
Expand Down Expand Up @@ -73,7 +74,7 @@ export class Binary {
!(buffer instanceof ArrayBuffer) &&
!Array.isArray(buffer)
) {
throw new TypeError(
throw new BSONTypeError(
'Binary can only be constructed from string, Buffer, TypedArray, or Array<number>'
);
}
Expand Down Expand Up @@ -108,9 +109,9 @@ export class Binary {
put(byteValue: string | number | Uint8Array | Buffer | number[]): void {
// If it's a string and a has more than one character throw an error
if (typeof byteValue === 'string' && byteValue.length !== 1) {
throw new TypeError('only accepts single character String');
throw new BSONTypeError('only accepts single character String');
} else if (typeof byteValue !== 'number' && byteValue.length !== 1)
throw new TypeError('only accepts single character Uint8Array or Array');
throw new BSONTypeError('only accepts single character Uint8Array or Array');

// Decode the byte value once
let decodedByte: number;
Expand All @@ -123,7 +124,7 @@ export class Binary {
}

if (decodedByte < 0 || decodedByte > 255) {
throw new TypeError('only accepts number in a valid unsigned byte range 0-255');
throw new BSONTypeError('only accepts number in a valid unsigned byte range 0-255');
}

if (this.buffer.length > this.position) {
Expand Down Expand Up @@ -238,7 +239,7 @@ export class Binary {
return new UUID(this.buffer.slice(0, this.position));
}

throw new Error(
throw new BSONError(
`Binary sub_type "${this.sub_type}" is not supported for converting to UUID. Only "${Binary.SUBTYPE_UUID}" is currently supported.`
);
}
Expand Down Expand Up @@ -266,7 +267,7 @@ export class Binary {
data = uuidHexStringToBuffer(doc.$uuid);
}
if (!data) {
throw new TypeError(`Unexpected Binary Extended JSON format ${JSON.stringify(doc)}`);
throw new BSONTypeError(`Unexpected Binary Extended JSON format ${JSON.stringify(doc)}`);
}
return new Binary(data, type);
}
Expand Down
6 changes: 5 additions & 1 deletion src/bson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Map } from './map';
import { MaxKey } from './max_key';
import { MinKey } from './min_key';
import { ObjectId } from './objectid';
import { BSONError, BSONTypeError } from './error';
import { calculateObjectSize as internalCalculateObjectSize } from './parser/calculate_size';
// Parts of the parser
import { deserialize as internalDeserialize, DeserializeOptions } from './parser/deserializer';
Expand Down Expand Up @@ -98,6 +99,7 @@ export {
// later builds we changed it back to ObjectID (capital D) to match legacy implementations.
ObjectId as ObjectID
};
export { BSONError, BSONTypeError } from './error';

/** @public */
export interface Document {
Expand Down Expand Up @@ -326,6 +328,8 @@ const BSON = {
serializeWithBufferAndIndex,
deserialize,
calculateObjectSize,
deserializeStream
deserializeStream,
BSONError,
BSONTypeError
};
export default BSON;
9 changes: 5 additions & 4 deletions src/decimal128.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Buffer } from 'buffer';
import { BSONTypeError } from './error';
import { Long } from './long';

const PARSE_STRING_REGEXP = /^(\+|-)?(\d+|(\d*\.\d*))?(E|e)?([-+])?(\d+)?$/;
Expand Down Expand Up @@ -105,7 +106,7 @@ function lessThan(left: Long, right: Long): boolean {
}

function invalidErr(string: string, message: string) {
throw new TypeError(`"${string}" is not a valid Decimal128 string - ${message}`);
throw new BSONTypeError(`"${string}" is not a valid Decimal128 string - ${message}`);
}

/** @public */
Expand Down Expand Up @@ -187,7 +188,7 @@ export class Decimal128 {
// TODO: implementing a custom parsing for this, or refactoring the regex would yield
// further gains.
if (representation.length >= 7000) {
throw new TypeError('' + representation + ' not a valid Decimal128 string');
throw new BSONTypeError('' + representation + ' not a valid Decimal128 string');
}

// Results
Expand All @@ -197,7 +198,7 @@ export class Decimal128 {

// Validate the string
if ((!stringMatch && !infMatch && !nanMatch) || representation.length === 0) {
throw new TypeError('' + representation + ' not a valid Decimal128 string');
throw new BSONTypeError('' + representation + ' not a valid Decimal128 string');
}

if (stringMatch) {
Expand Down Expand Up @@ -269,7 +270,7 @@ export class Decimal128 {
}

if (sawRadix && !nDigitsRead)
throw new TypeError('' + representation + ' not a valid Decimal128 string');
throw new BSONTypeError('' + representation + ' not a valid Decimal128 string');

// Read exponent if exists
if (representation[index] === 'e' || representation[index] === 'E') {
Expand Down
3 changes: 2 additions & 1 deletion src/ensure_buffer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Buffer } from 'buffer';
import { BSONTypeError } from './error';
import { isAnyArrayBuffer } from './parser/utils';

/**
Expand All @@ -22,5 +23,5 @@ export function ensureBuffer(potentialBuffer: Buffer | ArrayBufferView | ArrayBu
return Buffer.from(potentialBuffer);
}

throw new TypeError('Must use either Buffer or TypedArray');
throw new BSONTypeError('Must use either Buffer or TypedArray');
}
13 changes: 13 additions & 0 deletions src/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/** @public */
export class BSONError extends Error {
get name(): string {
return 'BSONError';
}
}

/** @public */
export class BSONTypeError extends TypeError {
get name(): string {
return 'BSONTypeError';
}
}
18 changes: 13 additions & 5 deletions src/extended_json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Code } from './code';
import { DBRef, isDBRefLike } from './db_ref';
import { Decimal128 } from './decimal128';
import { Double } from './double';
import { BSONError, BSONTypeError } from './error';
import { Int32 } from './int_32';
import { Long } from './long';
import { MaxKey } from './max_key';
Expand Down Expand Up @@ -185,7 +186,7 @@ function serializeValue(value: any, options: EJSONSerializeOptions): any {
circularPart.length + (alreadySeen.length + current.length) / 2 - 1
);

throw new TypeError(
throw new BSONTypeError(
'Converting circular structure to EJSON:\n' +
` ${leadingPart}${alreadySeen}${circularPart}${current}\n` +
` ${leadingSpace}\\${dashes}/`
Expand Down Expand Up @@ -274,7 +275,7 @@ const BSON_TYPE_MAPPINGS = {

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function serializeDocument(doc: any, options: EJSONSerializeOptions) {
if (doc == null || typeof doc !== 'object') throw new Error('not an object instance');
if (doc == null || typeof doc !== 'object') throw new BSONError('not an object instance');

const bsontype: BSONType['_bsontype'] = doc._bsontype;
if (typeof bsontype === 'undefined') {
Expand All @@ -300,7 +301,7 @@ function serializeDocument(doc: any, options: EJSONSerializeOptions) {
// Copy the object into this library's version of that type.
const mapper = BSON_TYPE_MAPPINGS[doc._bsontype];
if (!mapper) {
throw new TypeError('Unrecognized or invalid _bsontype: ' + doc._bsontype);
throw new BSONTypeError('Unrecognized or invalid _bsontype: ' + doc._bsontype);
}
outDoc = mapper(outDoc);
}
Expand All @@ -319,7 +320,7 @@ function serializeDocument(doc: any, options: EJSONSerializeOptions) {

return outDoc.toExtendedJSON(options);
} else {
throw new Error('_bsontype must be a string, but was: ' + typeof bsontype);
throw new BSONError('_bsontype must be a string, but was: ' + typeof bsontype);
}
}

Expand Down Expand Up @@ -366,7 +367,14 @@ export namespace EJSON {
if (typeof finalOptions.relaxed === 'boolean') finalOptions.strict = !finalOptions.relaxed;
if (typeof finalOptions.strict === 'boolean') finalOptions.relaxed = !finalOptions.strict;

return JSON.parse(text, (_key, value) => deserializeValue(value, finalOptions));
return JSON.parse(text, (key, value) => {
if (key.indexOf('\x00') !== -1) {
throw new BSONError(
`BSON Document field names cannot contain null bytes, found: ${JSON.stringify(key)}`
);
}
return deserializeValue(value, finalOptions);
});
}

export type JSONPrimitive = string | number | boolean | null;
Expand Down
5 changes: 3 additions & 2 deletions src/objectid.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Buffer } from 'buffer';
import { ensureBuffer } from './ensure_buffer';
import { BSONTypeError } from './error';
import { deprecate, isUint8Array, randomBytes } from './parser/utils';

// Regular expression that checks for hex value
Expand Down Expand Up @@ -84,7 +85,7 @@ export class ObjectId {
} else if (id.length === 24 && checkForHexRegExp.test(id)) {
this[kId] = Buffer.from(id, 'hex');
} else {
throw new TypeError(
throw new BSONTypeError(
'Argument passed in must be a Buffer or string of 12 bytes or a string of 24 hex characters'
);
}
Expand Down Expand Up @@ -276,7 +277,7 @@ export class ObjectId {
static createFromHexString(hexString: string): ObjectId {
// Throw an error if it's not a valid setup
if (typeof hexString === 'undefined' || (hexString != null && hexString.length !== 24)) {
throw new TypeError(
throw new BSONTypeError(
'Argument passed in must be a single String of 12 bytes or a string of 24 hex characters'
);
}
Expand Down
Loading