dcantrell / pyparted

Python bindings for GNU parted (libparted)
GNU General Public License v2.0
86 stars 43 forks source link

TypeError: argument 1 must be string without null bytes, not str #54

Closed Ragora closed 5 years ago

Ragora commented 5 years ago

I am unable to write sectors using the Geometry object with data containing \x00 bytes. It works fine otherwise, so I suspect the binding needs some adjustments to properly handle this case?

This occurs on an Ubuntu machine running Python 2.7 (and also on Python 3.5.2).

The following code reproduces it:


import parted
device = parted.getDevice("/dev/xxxxxxxxxxxxxx")
device.open()

sector_size = device.sectorSize
geometry = parted.Geometry(device=device, start=0, length=1)
geometry.write("".join(["\x00"] * sector_size), 0, 1) # Fails here
geometry.write("".join(["\x01"] * sector_size), 0, 1) # But this works fine otherwise

device.sync()
device.close()

The full output of the failure:

Traceback (most recent call last):
  File "repro.py", line 7, in <module>
    geometry.write("".join(["\x00"] * sector_size), 0, 1) # Fails here
  File "/usr/local/lib/python2.7/dist-packages/parted/decorators.py", line 42, in new
    ret = fn(*args, **kwds)
  File "/usr/local/lib/python2.7/dist-packages/parted/geometry.py", line 192, in write
    return self.__geometry.write(buf, offset, count)
TypeError: argument 1 must be string without null bytes, not str

Or perhaps I'm just not supposed to use it like this?

dcantrell commented 5 years ago

What you're doing is legal, it's the PyArg_ParseTuple() that needs fixing. I have that parsing the argument vector using "s" which is trying to take buf as a NUL-terminated string when it really needs to be reading this as a byte array where NUL is perfectly legal. Fortunately, it looks like PyArg_ParseTuple() can play along and we can use either s* or s# rather than just s. I'm going to test this locally and try to turn your example in to a test case so we don't regress on this.

dcantrell commented 5 years ago

OK, that was pretty easy to fix up. I've added a test case for it as well. The trick is with PyArg_ParseTuple() and using s# to read it as an array of bytes. It gives us the length, which we don't need to give to ped_geometry_write(), but whatever. Thanks for the report.