Discussion:
[pyusb-users] Bug found and patched in util.py
Paul Cornelius
2015-08-08 04:14:35 UTC
Permalink
I found a bug in usb.util.py in the function get_string. This function
was failing with an "Overflow" error on my Windows 8.1 machine, using
Python 3.3 and libusb-1.0.

If this function is called with the default value for langid (None), it
first makes a call to get_descriptor to obtain a list of languages
supported by the device. This second parameter of this function call is
the size of the reply buffer, which was equal to 1024. But a comment in
the libusb-1.0 source (descriptor.c, function
libusb_get_string_descriptor_ascii) reads: /* Some devices choke on size
255 */.
And it seems to be true. When I changed the get_descriptor function
call to reduce the buffer size parameter to 255 the error disappeared.
I also thought it would be good to limit the size of any buffer passed
to get_string. My modified function now reads as follows:

defget_string(dev,length,index,langid=None):
r"""Retrieve a string descriptor from the device.

dev is the Device object to which the request will be
sent to.

length is the length of string in number of characters.

index is the string descriptor index and langid is the Language
ID of the descriptor. If langid is omitted, the string descriptor
of the first Language ID will be returned.

The return value is the unicode string present in the descriptor.
"""
fromusb.controlimportget_descriptor
iflangidisNone:
# Asking for the zero'th index is special - it returns a string
# descriptor that contains all the language IDs supported by the device.
# Typically there aren't many - often only one. The language IDs are 16
# bit numbers, and they start at the third byte in the descriptor. See
# USB 2.0 specification section 9.6.7 for more information.
#
# Note from libusb 1.0 sources (descriptor.c)
buf=get_descriptor(
dev,
255,
DESC_TYPE_STRING,
0
)
assertlen(buf)>=4
langid=buf[2]|(buf[3]<<8)

lenstr=length*2+2
iflenstr>255:
raiseValueError("String buffer length too long")
buf=get_descriptor(
dev,
length*2+2,# string is utf16 + 2 bytes of the descriptor
DESC_TYPE_STRING,
index,
langid
)
returnbuf[2:].tostring().decode('utf-16-le')

Paul Cornelius
Wander Lairson Costa
2015-08-08 19:00:55 UTC
Permalink
Hi,

Notice the code the get_string has changed:
https://github.com/walac/pyusb/blob/master/usb/util.py#L295-L340
I found a bug in usb.util.py in the function get_string. This function was
failing with an "Overflow" error on my Windows 8.1 machine, using Python 3.3
and libusb-1.0.
If this function is called with the default value for langid (None), it
first makes a call to get_descriptor to obtain a list of languages supported
by the device. This second parameter of this function call is the size of
the reply buffer, which was equal to 1024. But a comment in the libusb-1.0
source (descriptor.c, function libusb_get_string_descriptor_ascii) reads: /*
Some devices choke on size > 255 */.
And it seems to be true. When I changed the get_descriptor function call to
reduce the buffer size parameter to 255 the error disappeared. I also
thought it would be good to limit the size of any buffer passed to
r"""Retrieve a string descriptor from the device.
dev is the Device object to which the request will be
sent to.
length is the length of string in number of characters.
index is the string descriptor index and langid is the Language
ID of the descriptor. If langid is omitted, the string descriptor
of the first Language ID will be returned.
The return value is the unicode string present in the descriptor.
"""
from usb.control import get_descriptor
# Asking for the zero'th index is special - it returns a string
# descriptor that contains all the language IDs supported by the device.
# Typically there aren't many - often only one. The language IDs are 16
# bit numbers, and they start at the third byte in the descriptor. See
# USB 2.0 specification section 9.6.7 for more information.
#
# Note from libusb 1.0 sources (descriptor.c)
buf = get_descriptor(
dev,
255,
DESC_TYPE_STRING,
0
)
assert len(buf) >= 4
langid = buf[2] | (buf[3] << 8)
lenstr = length * 2 + 2
raise ValueError("String buffer length too long")
buf = get_descriptor(
dev,
length * 2 + 2, # string is utf16 + 2 bytes of the
descriptor
DESC_TYPE_STRING,
index,
langid
)
return buf[2:].tostring().decode('utf-16-le')
Paul Cornelius
------------------------------------------------------------------------------
_______________________________________________
pyusb-users mailing list
https://lists.sourceforge.net/lists/listinfo/pyusb-users
--
Best Regards,
Wander Lairson Costa

------------------------------------------------------------------------------
Paul Cornelius
2015-08-09 01:18:11 UTC
Permalink
OK I see.

I thought I had the latest release (1.0.0.a2), which I got from
sourceforge. I got to there by following the link on
http://walac.github.io/pyusb/. Also I searched exhaustively for anyone
reporting this bug before diving into the pyusb internals. What did I do
wrong?

Thanks,
Paul Cornelius
Post by Wander Lairson Costa
Hi,
https://github.com/walac/pyusb/blob/master/usb/util.py#L295-L340
I found a bug in usb.util.py in the function get_string. This function was
failing with an "Overflow" error on my Windows 8.1 machine, using Python 3.3
and libusb-1.0.
If this function is called with the default value for langid (None), it
first makes a call to get_descriptor to obtain a list of languages supported
by the device. This second parameter of this function call is the size of
the reply buffer, which was equal to 1024. But a comment in the libusb-1.0
source (descriptor.c, function libusb_get_string_descriptor_ascii) reads: /*
Some devices choke on size > 255 */.
And it seems to be true. When I changed the get_descriptor function call to
reduce the buffer size parameter to 255 the error disappeared. I also
thought it would be good to limit the size of any buffer passed to
r"""Retrieve a string descriptor from the device.
dev is the Device object to which the request will be
sent to.
length is the length of string in number of characters.
index is the string descriptor index and langid is the Language
ID of the descriptor. If langid is omitted, the string descriptor
of the first Language ID will be returned.
The return value is the unicode string present in the descriptor.
"""
from usb.control import get_descriptor
# Asking for the zero'th index is special - it returns a string
# descriptor that contains all the language IDs supported by the device.
# Typically there aren't many - often only one. The language IDs are 16
# bit numbers, and they start at the third byte in the descriptor. See
# USB 2.0 specification section 9.6.7 for more information.
#
# Note from libusb 1.0 sources (descriptor.c)
buf = get_descriptor(
dev,
255,
DESC_TYPE_STRING,
0
)
assert len(buf) >= 4
langid = buf[2] | (buf[3] << 8)
lenstr = length * 2 + 2
raise ValueError("String buffer length too long")
buf = get_descriptor(
dev,
length * 2 + 2, # string is utf16 + 2 bytes of the
descriptor
DESC_TYPE_STRING,
index,
langid
)
return buf[2:].tostring().decode('utf-16-le')
Paul Cornelius
------------------------------------------------------------------------------
_______________________________________________
pyusb-users mailing list
https://lists.sourceforge.net/lists/listinfo/pyusb-users
------------------------------------------------------------------------------
Wander Lairson Costa
2015-08-09 15:22:03 UTC
Permalink
Post by Paul Cornelius
OK I see.
I thought I had the latest release (1.0.0.a2), which I got from
sourceforge. I got to there by following the link on
http://walac.github.io/pyusb/. Also I searched exhaustively for anyone
reporting this bug before diving into the pyusb internals. What did I do
wrong?
The point is that this change was not released yet. When you find a
bug, it is better to check against git HEAD to see if it happens in
the latest code.
Post by Paul Cornelius
Thanks,
Paul Cornelius
Post by Wander Lairson Costa
Hi,
https://github.com/walac/pyusb/blob/master/usb/util.py#L295-L340
I found a bug in usb.util.py in the function get_string. This function was
failing with an "Overflow" error on my Windows 8.1 machine, using Python 3.3
and libusb-1.0.
If this function is called with the default value for langid (None), it
first makes a call to get_descriptor to obtain a list of languages supported
by the device. This second parameter of this function call is the size of
the reply buffer, which was equal to 1024. But a comment in the libusb-1.0
source (descriptor.c, function libusb_get_string_descriptor_ascii) reads: /*
Some devices choke on size > 255 */.
And it seems to be true. When I changed the get_descriptor function call to
reduce the buffer size parameter to 255 the error disappeared. I also
thought it would be good to limit the size of any buffer passed to
r"""Retrieve a string descriptor from the device.
dev is the Device object to which the request will be
sent to.
length is the length of string in number of characters.
index is the string descriptor index and langid is the Language
ID of the descriptor. If langid is omitted, the string descriptor
of the first Language ID will be returned.
The return value is the unicode string present in the descriptor.
"""
from usb.control import get_descriptor
# Asking for the zero'th index is special - it returns a string
# descriptor that contains all the language IDs supported by the device.
# Typically there aren't many - often only one. The language IDs are 16
# bit numbers, and they start at the third byte in the descriptor. See
# USB 2.0 specification section 9.6.7 for more information.
#
# Note from libusb 1.0 sources (descriptor.c)
buf = get_descriptor(
dev,
255,
DESC_TYPE_STRING,
0
)
assert len(buf) >= 4
langid = buf[2] | (buf[3] << 8)
lenstr = length * 2 + 2
raise ValueError("String buffer length too long")
buf = get_descriptor(
dev,
length * 2 + 2, # string is utf16 + 2 bytes of the
descriptor
DESC_TYPE_STRING,
index,
langid
)
return buf[2:].tostring().decode('utf-16-le')
Paul Cornelius
------------------------------------------------------------------------------
_______________________________________________
pyusb-users mailing list
https://lists.sourceforge.net/lists/listinfo/pyusb-users
------------------------------------------------------------------------------
_______________________________________________
pyusb-users mailing list
https://lists.sourceforge.net/lists/listinfo/pyusb-users
--
Best Regards,
Wander Lairson Costa

------------------------------------------------------------------------------
Loading...