Skip to content

Commit 2a37147

Browse files
peeyushguptaGeert Vanderkelen
authored and
Geert Vanderkelen
committed
BUG20462427: Fix receiving large field data from server
We fix receiving a large amount of data in a field from server The connector did not process packets correctly when distributed across several packets. Also receiving text greater then 16777215 bytes raised an index out of range error. A test case has been added for BUG#20462427. (cherry picked from commit 7221b81)
1 parent 004edd0 commit 2a37147

File tree

4 files changed

+65
-13
lines changed

4 files changed

+65
-13
lines changed

lib/mysql/connector/network.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# MySQL Connector/Python - MySQL driver written in Python.
2-
# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
33

44
# MySQL Connector/Python is licensed under the terms of the GPLv2
55
# <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
@@ -221,11 +221,13 @@ def recv_plain(self):
221221
try:
222222
# Read the header of the MySQL packet, 4 bytes
223223
packet = bytearray(b'')
224-
while len(packet) < 4:
225-
chunk = self.sock.recv(4)
224+
packet_len = 0
225+
while packet_len < 4:
226+
chunk = self.sock.recv(4 - packet_len)
226227
if not chunk:
227228
raise errors.InterfaceError(errno=2013)
228229
packet += chunk
230+
packet_len = len(packet)
229231

230232
# Save the packet number and payload length
231233
self._packet_number = packet[3]
@@ -257,12 +259,13 @@ def recv_py26_plain(self):
257259
try:
258260
# Read the header of the MySQL packet, 4 bytes
259261
header = bytearray(b'')
260-
261-
while len(header) < 4:
262-
chunk = self.sock.recv(4)
262+
header_len = 0
263+
while header_len < 4:
264+
chunk = self.sock.recv(4 - header_len)
263265
if not chunk:
264266
raise errors.InterfaceError(errno=2013)
265267
header += chunk
268+
header_len = len(header)
266269

267270
# Save the packet number and payload length
268271
self._packet_number = header[3]

lib/mysql/connector/protocol.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# MySQL Connector/Python - MySQL driver written in Python.
2-
# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
33

44
# MySQL Connector/Python is licensed under the terms of the GPLv2
55
# <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
@@ -313,11 +313,8 @@ def read_text_result(self, sock, count=1):
313313
while packet.startswith(b'\xff\xff\xff'):
314314
datas.append(packet[4:])
315315
packet = sock.recv()
316-
if packet[4] == 254:
317-
eof = self.parse_eof(packet)
318-
else:
319-
datas.append(packet[4:])
320-
rowdata = utils.read_lc_string_list(b''.join(datas))
316+
datas.append(packet[4:])
317+
rowdata = utils.read_lc_string_list(bytearray(b'').join(datas))
321318
elif packet[4] == 254:
322319
eof = self.parse_eof(packet)
323320
rowdata = None

tests/test_bugs.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3056,7 +3056,6 @@ def tearDown(self):
30563056
self.cnx.close()
30573057

30583058

3059-
30603059
class BugOra19777815(tests.MySQLConnectorTests):
30613060
"""BUG#19777815: CALLPROC() DOES NOT SUPPORT WARNINGS
30623061
"""
@@ -3200,3 +3199,53 @@ def test_set(self):
32003199

32013200
cur.execute("SELECT * FROM {0}".format(self.tbl))
32023201
self.assertEqual(exp, cur.fetchall())
3202+
3203+
3204+
class BugOra20462427(tests.MySQLConnectorTests):
3205+
"""BUG#20462427: BYTEARRAY INDEX OUT OF RANGE
3206+
"""
3207+
def setUp(self):
3208+
config = tests.get_mysql_config()
3209+
config['autocommit'] = True
3210+
config['connection_timeout'] = 100
3211+
self.cnx = connection.MySQLConnection(**config)
3212+
self.cur = self.cnx.cursor()
3213+
3214+
self.tbl = 'BugOra20462427'
3215+
self.cur.execute("DROP TABLE IF EXISTS {0}".format(self.tbl))
3216+
3217+
create = ("CREATE TABLE {0} ("
3218+
"id INT PRIMARY KEY, "
3219+
"a LONGTEXT "
3220+
") ENGINE=Innodb DEFAULT CHARSET utf8".format(self.tbl))
3221+
3222+
self.cur.execute(create)
3223+
3224+
def tearDown(self):
3225+
self.cur.execute("DROP TABLE IF EXISTS {0}".format(self.tbl))
3226+
self.cur.close()
3227+
self.cnx.close()
3228+
3229+
def test_bigdata(self):
3230+
temp = 'a'*16777210
3231+
insert = "INSERT INTO {0} (a) VALUES ('{1}')".format(self.tbl, temp)
3232+
3233+
self.cur.execute(insert)
3234+
self.cur.execute("SELECT a FROM {0}".format(self.tbl))
3235+
res = self.cur.fetchall()
3236+
self.assertEqual(16777210, len(res[0][0]))
3237+
3238+
self.cur.execute("UPDATE {0} SET a = concat(a, 'a')".format(self.tbl))
3239+
self.cur.execute("SELECT a FROM {0}".format(self.tbl))
3240+
res = self.cur.fetchall()
3241+
self.assertEqual(16777211, len(res[0][0]))
3242+
3243+
self.cur.execute("UPDATE {0} SET a = concat(a, 'a')".format(self.tbl))
3244+
self.cur.execute("SELECT a FROM {0}".format(self.tbl))
3245+
res = self.cur.fetchall()
3246+
self.assertEqual(16777212, len(res[0][0]))
3247+
3248+
self.cur.execute("UPDATE {0} SET a = concat(a, 'a')".format(self.tbl))
3249+
self.cur.execute("SELECT a FROM {0}".format(self.tbl))
3250+
res = self.cur.fetchall()
3251+
self.assertEqual(16777213, len(res[0][0]))

unittests.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
language = {lc_messages_dir}/english
121121
122122
[mysqld]
123+
max_allowed_packet=26777216
123124
basedir = {basedir}
124125
datadir = {datadir}
125126
tmpdir = {tmpdir}
@@ -135,6 +136,8 @@
135136
log-bin = mysqld_{name}_bin
136137
local_infile = 1
137138
innodb_flush_log_at_trx_commit = 2
139+
innodb_log_file_size = 1Gb
140+
general_log_file = general_{name}.log
138141
ssl
139142
"""
140143

0 commit comments

Comments
 (0)