Skip to content

Commit

Permalink
Fixed win32print.DeviceCapabilities() returning strings with junk in …
Browse files Browse the repository at this point in the history
…them.

Previously this code would ZeroMemory() the output buffer before passing it to DeviceCapabilities(),
and then assume that only characters in each string would be changed, i.e. the characters following
the null-terminator would remain null.
So it would only check if the last character in each string was null, to check if the string was null-terminated.

This assumption is wrong - sometimes DeviceCapabilities() sets the characters after null to junk.

Now every character in the returned buffer is checked for being null before falling back to the case where the
string takes up all available space.

#1654
  • Loading branch information
LincolnPuzey committed Jan 31, 2021
1 parent f3f55ab commit b598055
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGES.txt
Expand Up @@ -12,6 +12,10 @@ Since build 300:
* Shifted work in win32.lib.pywin32_bootstrap to Python's import system from
manual path manipulations (@wkschwartz in #1651)

* Fixed a bug where win32print.DeviceCapabilities would return strings
containing the null character followed by junk characters.
(#1654, #1660, Lincoln Puzey)

Since build 228:
----------------
* Fixed a bug where win32com.client.VARIANT params were returned in the reverse
Expand Down
20 changes: 17 additions & 3 deletions win32/src/win32print/win32print.cpp
Expand Up @@ -2048,19 +2048,33 @@ static PyObject *PyDeviceCapabilities(PyObject *self, PyObject *args)
PyErr_Format(PyExc_MemoryError, "DeviceCapabilites: Unable to allocate %d bytes", bufsize);
break;
}
ZeroMemory(buf, bufsize);
result = DeviceCapabilities(device, port, capability, buf, pdevmode);
// each string in buf can be null-terminated or take up all space and have length retsize.
// bytes after null character can be set to junk by DeviceCapabilities().
if (result == -1)
break;
ret = PyTuple_New(result);
if (ret == NULL)
break;
retname = (TCHAR *)buf;
// process each returned string
for (bufindex = 0; bufindex < result; bufindex++) {
if (*(retname + retsize - 1) == 0)
// check if returned string contains null character
bool contains_null = false;
for (retsize_index = 0; retsize_index < retsize; retsize_index++) {
if (*(retname + retsize_index) == 0) {
contains_null = true;
break;
}
}
if (contains_null) {
// string will be automatically terminated at null character.
tuple_item = PyWinObject_FromTCHAR(retname);
else // won't be null-terminated if string occupies entire space
}
else {
// specify string length.
tuple_item = PyWinObject_FromTCHAR(retname, retsize);
}
if (tuple_item == NULL) {
Py_DECREF(ret);
ret = NULL;
Expand Down

0 comments on commit b598055

Please sign in to comment.