Update Fix
This commit is contained in:
82
node_modules/mysql2/lib/packets/packet.js
generated
vendored
82
node_modules/mysql2/lib/packets/packet.js
generated
vendored
@@ -406,8 +406,8 @@ class Packet {
|
||||
readNullTerminatedString(encoding) {
|
||||
const start = this.offset;
|
||||
let end = this.offset;
|
||||
while (this.buffer[end]) {
|
||||
end = end + 1; // TODO: handle OOB check
|
||||
while (end < this.end && this.buffer[end] !== 0x00) {
|
||||
end = end + 1;
|
||||
}
|
||||
this.offset = end + 1;
|
||||
return StringParser.decode(this.buffer, encoding, start, end);
|
||||
@@ -516,16 +516,20 @@ class Packet {
|
||||
return result * sign;
|
||||
}
|
||||
|
||||
// copy-paste from https://github.com/mysqljs/mysql/blob/master/lib/protocol/Parser.js
|
||||
// adapted from https://github.com/mysqljs/mysql/blob/dc9c152a87ec51a1f647447268917243d2eab1fd/lib/protocol/Parser.js
|
||||
parseGeometryValue() {
|
||||
const buffer = this.readLengthCodedBuffer();
|
||||
let offset = 4;
|
||||
if (buffer === null || !buffer.length) {
|
||||
return null;
|
||||
}
|
||||
const bufferLength = buffer.length;
|
||||
function parseGeometry() {
|
||||
let x, y, i, j, numPoints, line;
|
||||
let x, y, i, j, numPoints, numRings, num, line;
|
||||
let result = null;
|
||||
if (offset + 5 > bufferLength) {
|
||||
return null;
|
||||
}
|
||||
const byteOrder = buffer.readUInt8(offset);
|
||||
offset += 1;
|
||||
const wkbType = byteOrder
|
||||
@@ -534,6 +538,9 @@ class Packet {
|
||||
offset += 4;
|
||||
switch (wkbType) {
|
||||
case 1: // WKBPoint
|
||||
if (offset + 16 > bufferLength) {
|
||||
return null;
|
||||
}
|
||||
x = byteOrder
|
||||
? buffer.readDoubleLE(offset)
|
||||
: buffer.readDoubleBE(offset);
|
||||
@@ -545,12 +552,21 @@ class Packet {
|
||||
result = { x: x, y: y };
|
||||
break;
|
||||
case 2: // WKBLineString
|
||||
if (offset + 4 > bufferLength) {
|
||||
return null;
|
||||
}
|
||||
numPoints = byteOrder
|
||||
? buffer.readUInt32LE(offset)
|
||||
: buffer.readUInt32BE(offset);
|
||||
offset += 4;
|
||||
if (numPoints > (bufferLength - offset) / 16) {
|
||||
return null;
|
||||
}
|
||||
result = [];
|
||||
for (i = numPoints; i > 0; i--) {
|
||||
if (offset + 16 > bufferLength) {
|
||||
break;
|
||||
}
|
||||
x = byteOrder
|
||||
? buffer.readDoubleLE(offset)
|
||||
: buffer.readDoubleBE(offset);
|
||||
@@ -563,19 +579,30 @@ class Packet {
|
||||
}
|
||||
break;
|
||||
case 3: // WKBPolygon
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
const numRings = byteOrder
|
||||
if (offset + 4 > bufferLength) {
|
||||
return null;
|
||||
}
|
||||
numRings = byteOrder
|
||||
? buffer.readUInt32LE(offset)
|
||||
: buffer.readUInt32BE(offset);
|
||||
offset += 4;
|
||||
if (numRings > (bufferLength - offset) / 4) {
|
||||
return null;
|
||||
}
|
||||
result = [];
|
||||
for (i = numRings; i > 0; i--) {
|
||||
if (offset + 4 > bufferLength) {
|
||||
break;
|
||||
}
|
||||
numPoints = byteOrder
|
||||
? buffer.readUInt32LE(offset)
|
||||
: buffer.readUInt32BE(offset);
|
||||
offset += 4;
|
||||
line = [];
|
||||
for (j = numPoints; j > 0; j--) {
|
||||
if (offset + 16 > bufferLength) {
|
||||
break;
|
||||
}
|
||||
x = byteOrder
|
||||
? buffer.readDoubleLE(offset)
|
||||
: buffer.readDoubleBE(offset);
|
||||
@@ -593,11 +620,16 @@ class Packet {
|
||||
case 5: // WKBMultiLineString
|
||||
case 6: // WKBMultiPolygon
|
||||
case 7: // WKBGeometryCollection
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
const num = byteOrder
|
||||
if (offset + 4 > bufferLength) {
|
||||
return null;
|
||||
}
|
||||
num = byteOrder
|
||||
? buffer.readUInt32LE(offset)
|
||||
: buffer.readUInt32BE(offset);
|
||||
offset += 4;
|
||||
if (num > (bufferLength - offset) / 9) {
|
||||
return null;
|
||||
}
|
||||
result = [];
|
||||
for (i = num; i > 0; i--) {
|
||||
result.push(parseGeometry());
|
||||
@@ -660,14 +692,27 @@ class Packet {
|
||||
if (len === null) {
|
||||
return null;
|
||||
}
|
||||
if (len === 0) {
|
||||
return 0; // TODO: assert? exception?
|
||||
}
|
||||
|
||||
// For numbers with many digits (>17), use built-in parseFloat to avoid
|
||||
// precision loss from accumulated rounding errors in repeated *10 operations.
|
||||
// This fixes issues #2928 (MAX_VALUE doubles) and #3690 (DECIMAL(36,18))
|
||||
// where very large numbers or numbers with many fractional digits lose precision.
|
||||
// The threshold of 17 is based on IEEE 754 double precision (~15-17 significant digits).
|
||||
// Testing shows minimal performance impact as most real-world numbers are shorter.
|
||||
if (len > 17) {
|
||||
const str = this.buffer.toString('utf8', this.offset, this.offset + len);
|
||||
this.offset += len;
|
||||
return Number.parseFloat(str);
|
||||
}
|
||||
|
||||
let result = 0;
|
||||
const end = this.offset + len;
|
||||
let factor = 1;
|
||||
let pastDot = false;
|
||||
let charCode = 0;
|
||||
if (len === 0) {
|
||||
return 0; // TODO: assert? exception?
|
||||
}
|
||||
if (this.buffer[this.offset] === minus) {
|
||||
this.offset++;
|
||||
factor = -1;
|
||||
@@ -681,9 +726,13 @@ class Packet {
|
||||
pastDot = true;
|
||||
this.offset++;
|
||||
} else if (charCode === exponent || charCode === exponentCapital) {
|
||||
this.offset++;
|
||||
const exponentValue = this.parseInt(end - this.offset);
|
||||
return (result / factor) * Math.pow(10, exponentValue);
|
||||
// Scientific notation detected - bail out to parseFloat for exact match.
|
||||
// Manual calculation with Math.pow(10, exp) cannot match parseFloat()
|
||||
// exactly for most non-zero exponents due to accumulated rounding errors.
|
||||
const start = end - len;
|
||||
const str = this.buffer.toString('utf8', start, end);
|
||||
this.offset = end;
|
||||
return Number.parseFloat(str);
|
||||
} else {
|
||||
result *= 10;
|
||||
result += this.buffer[this.offset] - 48;
|
||||
@@ -831,11 +880,10 @@ class Packet {
|
||||
if (n === null) {
|
||||
return this.writeInt8(0xfb);
|
||||
}
|
||||
// TODO: check that n is out of int precision
|
||||
this.writeInt8(0xfe);
|
||||
this.buffer.writeUInt32LE(n, this.offset);
|
||||
this.buffer.writeUInt32LE(n >>> 0, this.offset);
|
||||
this.offset += 4;
|
||||
this.buffer.writeUInt32LE(n >> 32, this.offset);
|
||||
this.buffer.writeUInt32LE(Math.floor(n / 0x100000000), this.offset);
|
||||
this.offset += 4;
|
||||
return this.offset;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user