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

expression: handle max_allowed_packet warnings for from_base64 function. #7409

Merged

Conversation

supernan1994
Copy link
Contributor

What problem does this PR solve?

Return NULL and a warning when the result of from_base64 exceeds max_allowed_packetbs.
to #7153

What is changed and how it works?

Before this PR:

mysql> show variables like 'max_allowed_packet';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| max_allowed_packet | 2     |
+--------------------+-------+
1 row in set (0.01 sec)

mysql> select from_base64("YWJj");
+---------------------+
| from_base64("YWJj") |
+---------------------+
| abc                 |
+---------------------+
1 row in set (0.04 sec)

After this PR:

mysql> show variables like 'max_allowed_packet';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| max_allowed_packet | 2     |
+--------------------+-------+
1 row in set (0.01 sec)

mysql> select from_base64("YWJj");
+---------------------+
| from_base64("YWJj") |
+---------------------+
| NULL                |
+---------------------+
1 row in set, 1 warning (0.00 sec)

mysql> show warnings;
+---------+------+----------------------------------------------------------------------------+
| Level   | Code | Message                                                                    |
+---------+------+----------------------------------------------------------------------------+
| Warning | 1301 | Result of from_base64() was larger than max_allowed_packet (2) - truncated |
+---------+------+----------------------------------------------------------------------------+
1 row in set (0.00 sec)

This PR adds base64NeededDecodedLength function. This function calculates the length of from_base64's result before executing core of from_base64 logic, and compares the length with global variable max_allowed_packet.

Check List

Tests

  • Unit test

Related changes

  • Need to be included in the release note
    please note:
Return `NULL` when the result of function `FROM_BASE64` is larger than `max_allowed_packet`

@sre-bot
Copy link
Contributor

sre-bot commented Aug 15, 2018

Hi contributor, thanks for your PR.

This patch needs to be approved by someone of admins. They should reply with "/ok-to-test" to accept this PR for running test automatically.

@supernan1994
Copy link
Contributor Author

/run-all-tests

@supernan1994
Copy link
Contributor Author

@zz-jason PTAL

@shenli
Copy link
Member

shenli commented Aug 15, 2018

@supernan1994 Thanks!

func base64NeededDecodedLength(n int) int {
// Returns -1 indicate the result will overflow.
if strconv.IntSize == 64 {
if n > 3074457345618258602 {
Copy link
Member

Choose a reason for hiding this comment

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

Is this value equal to math.MaxInt64?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, it's equals to 0x2AAAAAAAAAAAAAAALL, I copy it from mysql.
https://github.com/mysql/mysql-server/blob/5.7/mysys/base64.c#L69
I haven't figured out how it works, do you have any ideas?

Copy link
Member

@shenli shenli Aug 16, 2018

Choose a reason for hiding this comment

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

It is better to define a constant than use a magic number.

Copy link
Member

Choose a reason for hiding this comment

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

It is math.MaxInt64/3

Copy link
Member

Choose a reason for hiding this comment

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

how about:

if strconv.IntSize == 64 && n > math.MaxInt64/3 {
	return -1
}
if strconv.IntSize == 32 && n > math.MaxInt32/3 {
	return -1
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, Thanks a lot!! I will correct it.
I still confuse about why it is math.MaxInt64/3. Does that mean base64_decode function malloc 3 times of source string length during the process? It doesn't make sense.

Copy link
Member

@zz-jason zz-jason Aug 16, 2018

Choose a reason for hiding this comment

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

This check is to guarantee that the later n*3 instruction, which is part of n*3/4, does not overflow the max int64 or int32 value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, I get it, thanks~

Copy link
Member

Choose a reason for hiding this comment

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

😄

return -1
}
}
return n * 3 / 4
Copy link
Member

Choose a reason for hiding this comment

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

How about n/4*3, then the above validation can be removed?

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 n%4 > 4/3 , n/4*3 is not equal to n*3/4.
mysql calculates decode length by n*3/4, I think we'd better use the same formula.

Copy link
Member

Choose a reason for hiding this comment

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

ok

return -1
}
} else {
if n > 715827882 {
Copy link
Member

Choose a reason for hiding this comment

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

How did you get this number?

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 copy it from mysql.
https://github.com/mysql/mysql-server/blob/5.7/mysys/base64.c#L69
I haven't figured out how it works, do you have any ideas?

Copy link
Member

Choose a reason for hiding this comment

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

It is math.MaxInt32/3

@supernan1994
Copy link
Contributor Author

/run-all-tests

@supernan1994
Copy link
Contributor Author

@zz-jason DONE. PTAL

Copy link
Member

@zz-jason zz-jason left a comment

Choose a reason for hiding this comment

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

LGTM

@zz-jason zz-jason added the status/LGT1 Indicates that a PR has LGTM 1. label Aug 17, 2018
input := chunk.NewChunkWithCapacity(colTypes, 1)
input.AppendString(0, test.args)
res, isNull, err := fromBase64.evalString(input.GetRow(0))
c.Assert(err, IsNil)
Copy link
Contributor

Choose a reason for hiding this comment

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

add c.Assert(isNull, Equals, test.isNil)
then we can remove line #1653 and else branch in line #1662

@supernan1994
Copy link
Contributor Author

/run-all-tests

@supernan1994
Copy link
Contributor Author

/run-all-tests

Copy link
Contributor

@crazycs520 crazycs520 left a comment

Choose a reason for hiding this comment

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

LGTM

@zz-jason zz-jason added status/LGT2 Indicates that a PR has LGTM 2. and removed status/LGT1 Indicates that a PR has LGTM 1. labels Aug 17, 2018
@zz-jason zz-jason merged commit 4624785 into pingcap:master Aug 17, 2018
@supernan1994 supernan1994 deleted the feature/maxAllowPacketFromBase64 branch August 17, 2018 15:14
@zz-jason
Copy link
Member

@supernan1994 It would be great if you can cherrypick this bugfix to the release-2.0 branch 😸

@supernan1994
Copy link
Contributor Author

@zz-jason OK!

@sre-bot sre-bot added the contribution This PR is from a community contributor. label Dec 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component/expression contribution This PR is from a community contributor. status/LGT2 Indicates that a PR has LGTM 2. type/compatibility
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants