Skip to content

bpo-29649: struct.pack_into check boundary error message didn't respect offset #424

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

Merged
merged 5 commits into from
Apr 4, 2017
Merged

bpo-29649: struct.pack_into check boundary error message didn't respect offset #424

merged 5 commits into from
Apr 4, 2017

Conversation

andrewnester
Copy link
Contributor

@mention-bot
Copy link

@andrewnester, thanks for your PR! By analyzing the history of the files in this pull request, we identified @Haypo, @mdickinson, @Yhg1s, @serhiy-storchaka and @benjaminp to be potential reviewers.

@@ -578,6 +578,14 @@ def test__sizeof__(self):
self.check_sizeof('0s', 1)
self.check_sizeof('0c', 0)

def test_boundary_error_message(self):
import ctypes
Copy link
Member

Choose a reason for hiding this comment

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

I'd suggest moving this import module level and use the following pattern:

try:
    import ctypes
except ImportError:
    ctypes = None

then add

@unittest.skipUnless(ctypes, 'requires ctypes')
def test_boundary_error_message(self):
    ...

byte_list = ctypes.create_string_buffer(1)
try:
struct.pack_into('b', byte_list, 5, 1)
except struct.error as e:
Copy link
Member

Choose a reason for hiding this comment

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

Using assertRaises would be better:

with self.assertRaises(struct.error) as cm:
    struct.pack_into('b', byte_list, 5, 1)

self.assertEqual(str(cm.exception), '...')

Copy link
Member

Choose a reason for hiding this comment

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

Or assertRaisesRegex() if we want to be more lenient to error message.

Misc/NEWS Outdated
@@ -9,6 +9,7 @@ What's New in Python 3.7.0 alpha 1?

Core and Builtins
-----------------
- bpo-29649: struct.pack_into check boundary error message didn't respect offset.
Copy link
Member

Choose a reason for hiding this comment

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

This needs to be moved to "Library" section. And please add an empty line after the section header.

@@ -578,6 +578,14 @@ def test__sizeof__(self):
self.check_sizeof('0s', 1)
self.check_sizeof('0c', 0)

def test_boundary_error_message(self):
import ctypes
byte_list = ctypes.create_string_buffer(1)
Copy link
Member

Choose a reason for hiding this comment

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

Using ctypes looks unnecessary here. Why not use bytearray?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@serhiy-storchaka absolutely agree, thanks!

byte_list = ctypes.create_string_buffer(1)
try:
struct.pack_into('b', byte_list, 5, 1)
except struct.error as e:
Copy link
Member

Choose a reason for hiding this comment

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

Or assertRaisesRegex() if we want to be more lenient to error message.

def test_boundary_error_message(self):
byte_list = bytearray(1)
with self.assertRaisesRegex(struct.error,
'pack_into requires a buffer of at least 6 bytes for packing 1 bytes at offset 5'):
Copy link
Member

Choose a reason for hiding this comment

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

Too long line.

Misc/NEWS Outdated
@@ -261,6 +261,7 @@ Library

- bpo-29623: Allow use of path-like object as a single argument in
ConfigParser.read(). Patch by David Ellis.
- bpo-29649: struct.pack_into check boundary error message didn't respect offset.
Copy link
Member

Choose a reason for hiding this comment

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

The entry should be added at the start of corresponding section. Separate it with empty lines from other text.

Add () after struct.pack_into. Add "Patch by ".

@@ -1937,8 +1937,8 @@ s_pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames
/* Check boundaries */
if (offset < 0 || (buffer.len - offset) < soself->s_size) {
PyErr_Format(StructError,
"pack_into requires a buffer of at least %zd bytes",
soself->s_size);
"pack_into requires a buffer of at least %zd bytes for packing %zd bytes at offset %zd)",
Copy link
Member

Choose a reason for hiding this comment

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

Too long lines.

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

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

Please also address my comment on the tracker.

Misc/NEWS Outdated
@@ -259,6 +259,9 @@ Extension Modules
Library
-------

- bpo-29649: struct.pack_into() check boundary error message
didn't respect offset. Patch by Andrew Nester.
Copy link
Member

Choose a reason for hiding this comment

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

Use two spaces after sentence ending period.

@andrewnester
Copy link
Contributor Author

Thanks @serhiy-storchaka ! I've just added changes you requested + new error messages based on your comment from tracker. Thanks a lot!

@@ -1930,15 +1930,40 @@ s_pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames
return NULL;
}

/* Check that negative offset is low enough to fit data */
if (offset < 0 && offset + soself->s_size > 0) {
Copy link
Member

Choose a reason for hiding this comment

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

I think three following if's can be merged into one if (offset < 0). This will speed up common case of non-negative offset.

/* Check that negative offset is low enough to fit data */
if (offset < 0 && offset + soself->s_size > 0) {
PyErr_Format(StructError,
"pack_into requires negative offset not higher than %zd "
Copy link
Member

Choose a reason for hiding this comment

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

This just repeats the same number two times (but with different signs). It would be more helpful to output an actual value of offset.

soself->s_size);
"pack_into requires a buffer of at least %zd bytes for "
"packing %zd bytes at offset %zd",
soself->s_size + (offset > 0 ? offset : 0),
Copy link
Member

Choose a reason for hiding this comment

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

I think it would be more helpful to output an actual size of the buffer rather of soself->s_size + offset. The user can add two reported numbers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@serhiy-storchaka I would like to leave required size indicated explicitly but will add actual buffer size to this error message. Thanks!

@andrewnester
Copy link
Contributor Author

thanks @serhiy-storchaka for review, I just made couple of additional changes you requested.

@andrewnester
Copy link
Contributor Author

@serhiy-storchaka @berkerpeksag any updates on this?

@serhiy-storchaka serhiy-storchaka requested a review from vadmium March 9, 2017 09:59
@serhiy-storchaka
Copy link
Member

"not higher/lower than some negative value" doesn't look pretty clear. I afraid it can cause confusion. I prefer to output the offset and the size of the buffer or data. Something like

pack_into() can't pack into buffer of size 10 at offset -11
pack_into() can't pack the data of size 11 at offset -10
pack_into() can't pack the data of size 11 into buffer of size 20 at offset 10

Maybe other developers can suggest better wording.

Copy link
Member

@vadmium vadmium left a comment

Choose a reason for hiding this comment

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

@andrewnester’s current proposals are

1: pack_into requires a buffer of at least R bytes for packing P bytes at offset O (actual buffer size is B)
2: pack_into requires negative offset not higher than H (actual offset is O)
3: pack_into requires negative offset not lower than L (actual offset is O)

I agree the negative offset ones are awkward. My suggestions:

2: No space to pack 11 bytes at offset −10
3: Offset −11 out of range for 10-byte buffer

struct.error,
'pack_into requires a buffer of at least 6 '
'bytes for packing 1 bytes at offset 5 '
'\(actual buffer size is 1\)'):
Copy link
Member

Choose a reason for hiding this comment

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

I think it would be good to use a raw string here: r'\(. . .\)'

@andrewnester
Copy link
Contributor Author

thanks @vadmium @serhiy-storchaka
I just changed error messages to ones proposed by @vadmium
Thanks!

struct.error,
r'pack_into requires a buffer of at least 6 '
'bytes for packing 1 bytes at offset 5 '
'\(actual buffer size is 1\)'):
Copy link
Member

Choose a reason for hiding this comment

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

Correct me if I am wrong (I haven’t caught up with Python after the Git Hub changeover), but I think you need to make the final part of the string a raw string:

>>> (r'pack_into requires a buffer of at least 6 '
... 'bytes for packing 1 bytes at offset 5 '
... '\(actual buffer size is 1\)')
<stdin>:3: DeprecationWarning: invalid escape sequence \(

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@vadmium Thanks! you're right, I updated my PR.

@@ -578,6 +578,26 @@ def test__sizeof__(self):
self.check_sizeof('0s', 1)
self.check_sizeof('0c', 0)

def test_boundary_error_message(self):
byte_list = bytearray(1)
Copy link
Member

Choose a reason for hiding this comment

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

Do we need byte_list? Can't we just pass bytearray(1) to pack_into()?

byte_list = bytearray(1)
with self.assertRaisesRegex(
struct.error,
'pack_into requires a buffer of at least 6 '
Copy link
Member

Choose a reason for hiding this comment

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

This is just a style nit, but I find this style is a bit ugly. I prefer something like this:

regex = (
    r'multi'
    r'line'
    r'regex'
)

with self.assertRaisesRegex(struct.error, regex):
    ...

/* Check that negative offset is low enough to fit data */
if (offset + soself->s_size > 0) {
PyErr_Format(StructError,
"No space to pack %zd bytes at offset %zd",
Copy link
Member

Choose a reason for hiding this comment

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

I admit that we are pretty inconsistent with the styles of our exception messages, but I think these two should start with lowercase letters.

Misc/NEWS Outdated
@@ -322,7 +325,7 @@ Library
Now using them emits a deprecation warning.

- bpo-27863: Fixed multiple crashes in ElementTree caused by race conditions
and wrong types.
and wrong types.
Copy link
Member

Choose a reason for hiding this comment

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

This looks like an unrelated change to me.

Misc/NEWS Outdated
@@ -303,6 +303,9 @@ Extension Modules
Library
-------

- bpo-29649: struct.pack_into() check boundary error message
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps something like "Exception message of struct.pack_into() now respects [...]" might be better. It's 4am here so perhaps @vadmium can come up with a better wording :)

Copy link
Member

Choose a reason for hiding this comment

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

It’s 1 p.m. here! Maybe something like “Improve ‘struct.pack_into’ exception messages for problems with the buffer size and offset”.

@andrewnester
Copy link
Contributor Author

@berkerpeksag @vadmium thanks for the review, seems reasonable. All changes done. Could you please review it again? Thanks!

Copy link
Member

@berkerpeksag berkerpeksag left a comment

Choose a reason for hiding this comment

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

LGTM, thanks! I will let Serhiy do the merging since he knows this part of CPython better than myself.

@serhiy-storchaka serhiy-storchaka merged commit f78b119 into python:master Apr 4, 2017
jaraco pushed a commit that referenced this pull request Dec 2, 2022
Bumps [celery](https://github.com/celery/celery) from 5.0.4 to 5.0.5.
- [Release notes](https://github.com/celery/celery/releases)
- [Changelog](https://github.com/celery/celery/blob/master/Changelog.rst)
- [Commits](celery/celery@v5.0.4...v5.0.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
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.

6 participants