Skip to content

Commit

Permalink
Merge pull request #1004 from sidorares/fix/session-track
Browse files Browse the repository at this point in the history
Fix crashing when session info packet does not start with length-coded string
  • Loading branch information
sidorares authored Aug 20, 2019
2 parents caa9000 + 8b83316 commit 7b08d91
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 7 deletions.
11 changes: 11 additions & 0 deletions lib/constants/session_track.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use strict';

exports.SYSTEM_VARIABLES = 0;
exports.SCHEMA = 1;
exports.STATE_CHANGE = 2;
exports.STATE_GTIDS = 3;
exports.TRANSACTION_CHARACTERISTICS = 4;
exports.TRANSACTION_STATE = 5;

exports.FIRST_KEY = exports.SYSTEM_VARIABLES;
exports.LAST_KEY = exports.TRANSACTION_STATE;
15 changes: 8 additions & 7 deletions lib/packets/resultset_header.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ class ResultSetHeader {
}
let stateChanges = null;
if (isSet('SESSION_TRACK') && packet.offset < packet.end) {
const sessionInfoTypes = require('../constants/session_track.js');
this.info = packet.readLengthCodedString(encoding);

if (this.serverStatus && ServerSatusFlags.SERVER_SESSION_STATE_CHANGED) {
// session change info record - see
// https://dev.mysql.com/doc/internals/en/packet-OK_Packet.html#cs-sect-packet-ok-sessioninfo
Expand All @@ -48,31 +50,30 @@ class ResultSetHeader {
stateChanges = {
systemVariables: {},
schema: null,
// gtids: {},
trackStateChange: null
};
}
while (packet.offset < end) {
type = packet.readInt8();
len = packet.readLengthCodedNumber();
stateEnd = packet.offset + len;
key = packet.readLengthCodedString(encoding);
if (type === 0) {
if (type === sessionInfoTypes.SYSTEM_VARIABLES) {
key = packet.readLengthCodedString(encoding);
const val = packet.readLengthCodedString(encoding);
stateChanges.systemVariables[key] = val;
if (key === 'character_set_client') {
const charsetNumber = EncodingToCharset[val];
connection.config.charsetNumber = charsetNumber;
}
} else if (type === 1) {
// TODO double check it's supposed to be the only value, not a list.
} else if (type === sessionInfoTypes.SCHEMA) {
key = packet.readLengthCodedString(encoding);
stateChanges.schema = key;
} else if (type === 2) {
} else if (type === sessionInfoTypes.STATE_CHANGE) {
stateChanges.trackStateChange = packet.readLengthCodedString(
encoding
);
} else {
// GTIDs (type == 3) or unknown type - just skip for now
// unsupported session track type. For now just ignore
}
packet.offset = stateEnd;
}
Expand Down
38 changes: 38 additions & 0 deletions test/unit/packets/test-ok-sessiontrack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use strict';

const assert = require('assert');
const Packet = require('../../../lib/packets/packet');
const ResultSetHeader = require('../../../lib/packets/resultset_header.js');
const clientConstants = require('../../../lib/constants/client');

const mockConnection = {
config: {},
serverEncoding: 'utf8',
_handshakePacket: {
capabilityFlags: clientConstants.PROTOCOL_41 + clientConstants.SESSION_TRACK
}
};

const mkpacket = str => {
const buf = Buffer.from(str.split(/[ \n]+/).join(''), 'hex');
return new Packet(0, buf, 0, buf.length);
};

// regression examples from https://github.com/sidorares/node-mysql2/issues/989

assert.doesNotThrow(() => {
const packet = mkpacket(
`1b 00 00 01
00
01 fe 65 96 fc 02 00 00 00 00 03 40 00 00 00 0a 14 08 fe 60 63 9b 05 00 00 00
`
);
new ResultSetHeader(packet, mockConnection);
});

assert.doesNotThrow(() => {
const packet = mkpacket(
`13 00 00 01 00 01 00 02 40 00 00 00 0a 14 08 fe 18 25 e7 06 00 00 00`
);
new ResultSetHeader(packet, mockConnection);
});

0 comments on commit 7b08d91

Please sign in to comment.