Skip to content
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
42 changes: 42 additions & 0 deletions src/__tests__/fixtures/json/large-floats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Large floating point numbers and edge cases that should be handled correctly
* by JSON decoders, especially those with scientific notation (e+/e-).
*/
export default {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use these fixtures in JsonDecoder tests.

// Maximum finite representable value in JavaScript
maxValue: 1.7976931348623157e308,

// Same value with different notations
maxValueUppercase: '1.7976931348623157E+308',
maxValueImplicitPlus: '1.7976931348623157e308',

// Values that become Infinity
overflowToInfinity: 2e308,

// Medium range scientific notation
mediumLarge: 1.2345e50,
mediumSmall: 1.2345e-50,

// Very small numbers
verySmall: 5e-324,
smallestNormal: 2.2250738585072014e-308,

// Edge cases in arrays and objects
arrayWithLargeFloats: [1.7976931348623157e308, 2e308, 1.2345e-50],
objectWithLargeFloat: {
maxValue: 1.7976931348623157e308,
infinity: 2e308,
tiny: 5e-324,
},

// Mixed with other types
mixedData: {
numbers: [1, -1, 0, 1.7976931348623157e308, 5e-324],
strings: ['normal', 'with spaces'],
nested: {
largeFloat: 1.2345e100,
boolean: true,
nullValue: null,
},
},
};
32 changes: 16 additions & 16 deletions src/json/JsonDecoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,95 +349,95 @@ export class JsonDecoder implements BinaryJsonDecoder {
}
const c9 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9);
if (num !== num) throw new Error('Invalid JSON');
return num;
}
const c10 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10);
if (num !== num) throw new Error('Invalid JSON');
return num;
}
const c11 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11);
if (num !== num) throw new Error('Invalid JSON');
return num;
}
const c12 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12);
if (num !== num) throw new Error('Invalid JSON');
return num;
}
const c13 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13);
if (num !== num) throw new Error('Invalid JSON');
return num;
}
const c14 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14);
if (num !== num) throw new Error('Invalid JSON');
return num;
}
const c15 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15);
if (num !== num) throw new Error('Invalid JSON');
return num;
}
const c16 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16);
if (num !== num) throw new Error('Invalid JSON');
return num;
}
const c17 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17);
if (num !== num) throw new Error('Invalid JSON');
return num;
}
const c18 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18);
if (num !== num) throw new Error('Invalid JSON');
return num;
}
const c19 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
if (num !== num) throw new Error('Invalid JSON');
return num;
}
const c20 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(
c1,
Expand Down Expand Up @@ -466,7 +466,7 @@ export class JsonDecoder implements BinaryJsonDecoder {
}
const c21 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(
c1,
Expand Down Expand Up @@ -496,7 +496,7 @@ export class JsonDecoder implements BinaryJsonDecoder {
}
const c22 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(
c1,
Expand Down Expand Up @@ -527,7 +527,7 @@ export class JsonDecoder implements BinaryJsonDecoder {
}
const c23 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(
c1,
Expand Down Expand Up @@ -559,7 +559,7 @@ export class JsonDecoder implements BinaryJsonDecoder {
}
const c24 = c;
c = uint8[x++];
if (!c || ((c < 45 || c > 57) && c !== 69 && c !== 101)) {
if (!c || ((c < 45 || c > 57) && c !== 43 && c !== 69 && c !== 101)) {
reader.x = x - 1;
const num = +fromCharCode(
c1,
Expand Down
64 changes: 64 additions & 0 deletions src/json/__tests__/JsonDecoder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,70 @@ describe('number', () => {
const value = decoder.readAny();
expect(value).toBe(smallFloat);
});

test('large float with e+ notation - Number.MAX_VALUE', () => {
const data = Buffer.from('1.7976931348623157e+308', 'utf-8');
decoder.reader.reset(data);
const value = decoder.readAny();
expect(value).toBe(1.7976931348623157e308);
expect(value).toBe(Number.MAX_VALUE);
});

test('large float with E+ notation - uppercase', () => {
const data = Buffer.from('1.7976931348623157E+308', 'utf-8');
decoder.reader.reset(data);
const value = decoder.readAny();
expect(value).toBe(1.7976931348623157e308);
});

test('large float without explicit + sign', () => {
const data = Buffer.from('1.7976931348623157e308', 'utf-8');
decoder.reader.reset(data);
const value = decoder.readAny();
expect(value).toBe(1.7976931348623157e308);
});

test('infinity with e+ notation', () => {
const data = Buffer.from('2e+308', 'utf-8');
decoder.reader.reset(data);
const value = decoder.readAny();
expect(value).toBe(Infinity);
});

test('medium large float with e+ notation', () => {
const data = Buffer.from('1.2345e+50', 'utf-8');
decoder.reader.reset(data);
const value = decoder.readAny();
expect(value).toBe(1.2345e50);
});

test('very small float with e- notation', () => {
const data = Buffer.from('5e-324', 'utf-8');
decoder.reader.reset(data);
const value = decoder.readAny();
expect(value).toBe(5e-324);
});

test('smallest normal positive float', () => {
const data = Buffer.from('2.2250738585072014e-308', 'utf-8');
decoder.reader.reset(data);
const value = decoder.readAny();
expect(value).toBe(2.2250738585072014e-308);
});

test('large float in JSON array', () => {
const data = Buffer.from('[1.7976931348623157e+308]', 'utf-8');
decoder.reader.reset(data);
const value = decoder.readAny();
expect(value).toEqual([1.7976931348623157e308]);
});

test('large float in JSON object', () => {
const data = Buffer.from('{"value": 1.7976931348623157e+308}', 'utf-8');
decoder.reader.reset(data);
const value = decoder.readAny();
expect(value).toEqual({value: 1.7976931348623157e308});
});
});

describe('string', () => {
Expand Down