Skip to content
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

fixing bad connection error when reading large compressed packets #863

Merged
merged 12 commits into from
May 7, 2024

Conversation

dvilaverde
Copy link
Contributor

This is a fix for #862

@jnewmano
Copy link
Contributor

jnewmano commented May 4, 2024

I tried running your fork and got a panic, I'll work on getting a test case that I can share to reproduce.

[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x49d587]

goroutine 1 [running]:
io.ReadAtLeast({0x0, 0x0}, {0xc000000000, 0x4, 0x4000}, 0x4)
        /usr/local/go/src/io/io.go:335 +0x67
github.com/go-mysql-org/go-mysql/packet.(*Conn).copyN(0xc00013e070, {0x8bd0e0, 0xc001f0e030}, {0x7fe96f835c00, 0xc00007a550}, 0x1ac000?)
        /go/pkg/mod/github.com/dvilaverde/[email protected]/packet/conn.go:209 +0x206
github.com/go-mysql-org/go-mysql/packet.(*Conn).ReadPacketTo(0xc00013e070, {0x8bd0e0, 0xc001f0e000})
        /go/pkg/mod/github.com/dvilaverde/[email protected]/packet/conn.go:237 +0xc5
github.com/go-mysql-org/go-mysql/packet.(*Conn).ReadPacketReuseMem(0xc00013e070, {0xc000b8e000, 0x1570cb, 0x1ac000})
        /go/pkg/mod/github.com/dvilaverde/[email protected]/packet/conn.go:121 +0x165
github.com/go-mysql-org/go-mysql/client.(*Conn).readResultRows(0xc0000a0340, 0xc000106060, 0x1)

@dvilaverde
Copy link
Contributor Author

I tried running your fork and got a panic, I'll work on getting a test case that I can share to reproduce.

[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x49d587]

goroutine 1 [running]:
io.ReadAtLeast({0x0, 0x0}, {0xc000000000, 0x4, 0x4000}, 0x4)
        /usr/local/go/src/io/io.go:335 +0x67
github.com/go-mysql-org/go-mysql/packet.(*Conn).copyN(0xc00013e070, {0x8bd0e0, 0xc001f0e030}, {0x7fe96f835c00, 0xc00007a550}, 0x1ac000?)
        /go/pkg/mod/github.com/dvilaverde/[email protected]/packet/conn.go:209 +0x206
github.com/go-mysql-org/go-mysql/packet.(*Conn).ReadPacketTo(0xc00013e070, {0x8bd0e0, 0xc001f0e000})
        /go/pkg/mod/github.com/dvilaverde/[email protected]/packet/conn.go:237 +0xc5
github.com/go-mysql-org/go-mysql/packet.(*Conn).ReadPacketReuseMem(0xc00013e070, {0xc000b8e000, 0x1570cb, 0x1ac000})
        /go/pkg/mod/github.com/dvilaverde/[email protected]/packet/conn.go:121 +0x165
github.com/go-mysql-org/go-mysql/client.(*Conn).readResultRows(0xc0000a0340, 0xc000106060, 0x1)

That would be great. I'll take a look when you provide that.

@dvilaverde
Copy link
Contributor Author

dvilaverde commented May 4, 2024

I've pushed one more change that may address the panic you found in your testing. There was a gap that could cause io.ReadAtLeast to be called with a nil reader when the compressed packet header had an uncompressed length with value zero.

Also not sure why golangci-lint checks are failing now, they pass when i run locally using version 1.57.2. The GitHub Action is using 1.58.0 and when i tried with that version it never completes and seems to consume 60gb+ of my system memory.

@jnewmano
Copy link
Contributor

jnewmano commented May 4, 2024

The latest commit fixed the panic I was seeing. Thank you.

@dvilaverde
Copy link
Contributor Author

dvilaverde commented May 5, 2024

Fixed the golangci-lint issue as well. The latest version 1.58.0 removed 3 linters, so i removed those from the config file.

Copy link
Collaborator

@lance6716 lance6716 left a comment

Choose a reason for hiding this comment

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

will review later (on vacation)

packet/conn.go Outdated
// if we've read to EOF, and we have compression then advance the sequence number
// and reset the compressed reader to continue reading the remaining bytes
// in the next compressed packet.
if c.Compression != MYSQL_COMPRESS_NONE && rd < bcap &&
Copy link
Collaborator

Choose a reason for hiding this comment

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

I just read the comment of ReadAtLeast, seems for goErrors.Is(err, io.ErrUnexpectedEOF) || goErrors.Is(err, io.EOF) we don't need to check rd < bcap

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes agree with you after reviewing the ReadAtLeast documentation. I've applied the change suggested.

packet/conn.go Outdated
}

// now read the remaining bytes into the buffer containing the first read bytes
rd, err = io.ReadAtLeast(c.currentPacketReader(), buf[rd:], bcap-rd)
Copy link
Collaborator

Choose a reason for hiding this comment

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

should we delete this reading and let the outer loop read it? because it may still meet the EOF error like line 191.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes terrific suggestion, i've applied this change.

return nil, nil
}

func (c *Conn) currentPacketReader() io.Reader {
Copy link
Collaborator

Choose a reason for hiding this comment

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

there're

	compressedReaderActive bool

	compressedReader io.Reader

in Conn. Seems we can directly check c.compressedReader == nil as the returned reader for currentPacketReader. And compressedReaderActive always has the same value for c.compressedReader == nil so we can delete it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When I attempted to delete compressedReaderActive the tests in the client package all began failing when I ran them with compression enabled. I think this is because compressedReaderActive is reset to false in WritePacket after writing the compressed packet. So I don't think I can delete it, or at least I feel deleting it is out of scope for this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've updated this PR with your suggestion. It was 2am for me and I wasn't thinking clearly, but after more sleep, I realized I could easily remove the compressedReaderActive boolean property from Conn.

Copy link
Collaborator

Choose a reason for hiding this comment

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

take care of your health ❤️

return nil, nil
}

func (c *Conn) currentPacketReader() io.Reader {
Copy link
Collaborator

Choose a reason for hiding this comment

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

take care of your health ❤️

@lance6716 lance6716 merged commit 007f306 into go-mysql-org:master May 7, 2024
13 checks passed
@dvilaverde dvilaverde deleted the compressed_packet branch May 7, 2024 11:10
@jnewmano
Copy link
Contributor

jnewmano commented May 7, 2024

One of the commits after 22dbb42 has led to broken connections when using compression with the error message invalid compressed sequence 2 != 1

@dvilaverde
Copy link
Contributor Author

One of the commits after 22dbb42 has led to broken connections when using compression with the error message invalid compressed sequence 2 != 1

Do you happen to have a way to reproduce? Any other info that could help in diagnosing the issue?

@jnewmano
Copy link
Contributor

jnewmano commented May 7, 2024

One of the commits after 22dbb42 has led to broken connections when using compression with the error message invalid compressed sequence 2 != 1

Do you happen to have a way to reproduce? Any other info that could help in diagnosing the issue?

I'll get more information together and open an issue.

@jnewmano
Copy link
Contributor

jnewmano commented May 7, 2024

One of the commits after 22dbb42 has led to broken connections when using compression with the error message invalid compressed sequence 2 != 1

Do you happen to have a way to reproduce? Any other info that could help in diagnosing the issue?

Details posted in issue #871

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants