-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
runtime error: slice bounds out of range in packets.go #587
Comments
I was digging a bit around. These are the three bits of code involved (from highest to lowest level):
// Length coded Binary Strings
case fieldTypeDecimal, fieldTypeNewDecimal, fieldTypeVarChar,
fieldTypeBit, fieldTypeEnum, fieldTypeSet, fieldTypeTinyBLOB,
fieldTypeMediumBLOB, fieldTypeLongBLOB, fieldTypeBLOB,
fieldTypeVarString, fieldTypeString, fieldTypeGeometry, fieldTypeJSON:
var isNull bool
var n int
dest[i], isNull, n, err = readLengthEncodedString(data[pos:])
rs.lastcols = make([]driver.Value, len(rs.rowsi.Columns())) Is it possible that either UPDATE 1: I checked by modifying |
By the way, I am also getting (from few to many) errors like:
You can check with https://play.golang.org/p/N0AeL32n8R that such big numbers (all instances I got in logs and I tried) are really pieces of ASCII text e.g. So my theory is that the two errors are related, and somehow one field gets "eaten"/skipped and causes the problem. |
@gm42 can you make sure that this is a problem somehow caused by concurrency?
|
It's hard to imagine might be causing the problems. The driver itself keeps all the connections completely isolated from each other, so concurrency shouldn't be an issue. The pooling logic in the database/sql package has some weird and complex implementations but I also can't imagine any scenario where it might cause problems like that. The last suspect might be the MySQL server itself, but then it should also cause problems with other clients. And considering the size of the MySQL community, I think this problem would have been detected already. The only remaining reason I can imagine is that we do not reset some state properly somewhere. |
@julienschmidt an update:
Just to be clear about (3), there are times that a full sequential read does not trigger the conversion error at all, and times that it does, even immediately; this is also unexpected for me, and puzzling, but compatible with some internal state problem because I do not restart the Go process between runs e.g. the server side API stays running (this is the side connecting to MySQL), and from client-side I can trigger (either sequentially or concurrently) full scans via (synchronous) API calls. Now I will run some more tests with concurrency and try to reduce this to a testcase for MySQL 5.7. UPDATE: @julienschmidt I have managed to reduce the data/query parts and the Go parts of the testcase: https://gist.github.com/gm42/2fa0693d9a9aea81f1dce1f1b65679af You can reproduce the issue with MySQL 5.6 by running: go run go-mysql-587-testcase.go (You will need the sqlx package and to populate a localhost MySQL instance, or change the connection string accordingly) Some interesting facts I found out:
When trying to reduce the testcase (so that less tables would be involved), the provided query was really the smallest testcase I could find, please let me know if bug can be reproduced and/or if you manage to reduce it further. |
I've been able to reproduce this on my laptop with @gm42 submitted test case. mysql version: mysqld Ver 5.7.18 for osx10.12 on x86_64 (Homebrew) go version: 1.8.1 result: it seems to fail randomly in a different iteration
|
The next step would be to reproduce it without sqlx, as the error might also be happening there. |
Reproduced (same scenario as above) without sqlx, using regular database/sql package (with @gm42's original test case + his database.sql). https://gist.github.com/cdesousa/95775bb6dbf67480084d770475addb19 The test does pass when I remove the IFNULL function from the SELECT and just select either plc.parent_id or plc.id. Still doing some additional debugging as to what the cause is.
|
Update:
|
This sounds a lot like a bug in the pooling logic of the database/sql package |
But on the other hand, this shouldn't cause a bug like this. |
See here: Lines 117 to 125 in e5cc7f3
Is this bug reproducible when removed this line?
|
(slightly off topic) |
@methane the bug is not reproducible when I comment out that line. |
OK. So we should check column definition packet are exactly same bytes before reusing |
BTW, Oracle removed protocol document. WTF! We can see archived page here: Or we can refer MariaDB's document. |
Thanks guys for the progress here. IMO the driver should release a patch that fixes this serious problem first, then caching is studied later with a regression test for this in mind. Imagine how this could be used as an attack vector to increase the balance or some other number in a column by making many API calls with text-setting fiields like Shall I attempt a PR or you already have something in progress? I also think #444 might be affected |
I tried #587 (comment) I found fieldType of nullable_id is sometimes fieldTypeLong and sometimes fieldTypeLongLong. |
Great find, thanks for the work! |
@methane might be explained by the fact that an |
Thanks to everyone involved here for the swift support & patching. 👍 |
Issue description
When using many concurrent SQL queries (same pool), I get a slice out of bounds error.
The corresponding logic in jmoiron/sqlx seems fine. It's just a call to
(*Rows).Next()
which is causing this.Similar to #36 perhaps?
Error log
Configuration
Driver version (or git SHA): 1421caf
Go version: go version go1.8.1 linux/amd64
Server version: MySQL 5.6.27
Server OS: Ubuntu 16
The text was updated successfully, but these errors were encountered: