Remove all uses of alloca() from this module. The alloca() return value
isn't checked, and it *is* possible that a very large alloca() call is
made, e.g. when a large registry value is being read. I don't know if
alloca() in that case returns NULL or returns a pointer pointing outside
the stack, and I don't want to know -- I've simply replaced all calls to
alloca() with either PyMem_Malloc() or PyString_FromStringAndSize(NULL,)
as appropriate, followed by a size check. This addresses SF buf 851056.
Will backport to 2.3 next.
diff --git a/PC/_winreg.c b/PC/_winreg.c
index de66f6a..a20b09a 100644
--- a/PC/_winreg.c
+++ b/PC/_winreg.c
@@ -1031,6 +1031,7 @@
PyObject *obKey;
int index;
long rc;
+ PyObject *retStr;
char *retBuf;
DWORD len;
@@ -1045,11 +1046,17 @@
return PyErr_SetFromWindowsErrWithFunction(rc,
"RegQueryInfoKey");
++len; /* include null terminator */
- retBuf = (char *)alloca(len);
+ retStr = PyString_FromStringAndSize(NULL, len);
+ if (retStr == NULL)
+ return NULL;
+ retBuf = PyString_AS_STRING(retStr);
- if ((rc = RegEnumKey(hKey, index, retBuf, len)) != ERROR_SUCCESS)
+ if ((rc = RegEnumKey(hKey, index, retBuf, len)) != ERROR_SUCCESS) {
+ Py_DECREF(retStr);
return PyErr_SetFromWindowsErrWithFunction(rc, "RegEnumKey");
- return Py_BuildValue("s", retBuf);
+ }
+ _PyString_Resize(&retStr, strlen(retBuf));
+ return retStr;
}
static PyObject *
@@ -1080,8 +1087,14 @@
"RegQueryInfoKey");
++retValueSize; /* include null terminators */
++retDataSize;
- retValueBuf = (char *)alloca(retValueSize);
- retDataBuf = (char *)alloca(retDataSize);
+ retValueBuf = (char *)PyMem_Malloc(retValueSize);
+ if (retValueBuf == NULL)
+ return PyErr_NoMemory();
+ retDataBuf = (char *)PyMem_Malloc(retDataSize);
+ if (retDataBuf == NULL) {
+ PyMem_Free(retValueBuf);
+ return PyErr_NoMemory();
+ }
Py_BEGIN_ALLOW_THREADS
rc = RegEnumValue(hKey,
@@ -1094,14 +1107,21 @@
&retDataSize);
Py_END_ALLOW_THREADS
- if (rc != ERROR_SUCCESS)
- return PyErr_SetFromWindowsErrWithFunction(rc,
- "PyRegEnumValue");
+ if (rc != ERROR_SUCCESS) {
+ retVal = PyErr_SetFromWindowsErrWithFunction(rc,
+ "PyRegEnumValue");
+ goto fail;
+ }
obData = Reg2Py(retDataBuf, retDataSize, typ);
- if (obData == NULL)
- return NULL;
+ if (obData == NULL) {
+ retVal = NULL;
+ goto fail;
+ }
retVal = Py_BuildValue("sOi", retValueBuf, obData, typ);
Py_DECREF(obData);
+ fail:
+ PyMem_Free(retValueBuf);
+ PyMem_Free(retDataBuf);
return retVal;
}
@@ -1206,10 +1226,11 @@
HKEY hKey;
PyObject *obKey;
char *subKey;
-
long rc;
+ PyObject *retStr;
char *retBuf;
long bufSize = 0;
+
if (!PyArg_ParseTuple(args, "Oz:QueryValue", &obKey, &subKey))
return NULL;
@@ -1219,12 +1240,18 @@
!= ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc,
"RegQueryValue");
- retBuf = (char *)alloca(bufSize);
+ retStr = PyString_FromStringAndSize(NULL, bufSize);
+ if (retStr == NULL)
+ return NULL;
+ retBuf = PyString_AS_STRING(retStr);
if ((rc = RegQueryValue(hKey, subKey, retBuf, &bufSize))
- != ERROR_SUCCESS)
+ != ERROR_SUCCESS) {
+ Py_DECREF(retStr);
return PyErr_SetFromWindowsErrWithFunction(rc,
"RegQueryValue");
- return Py_BuildValue("s", retBuf);
+ }
+ _PyString_Resize(&retStr, strlen(retBuf));
+ return retStr;
}
static PyObject *
@@ -1252,13 +1279,18 @@
!= ERROR_SUCCESS)
return PyErr_SetFromWindowsErrWithFunction(rc,
"RegQueryValueEx");
- retBuf = (char *)alloca(bufSize);
+ retBuf = (char *)PyMem_Malloc(bufSize);
+ if (retBuf == NULL)
+ return PyErr_NoMemory();
if ((rc = RegQueryValueEx(hKey, valueName, NULL,
&typ, (BYTE *)retBuf, &bufSize))
- != ERROR_SUCCESS)
+ != ERROR_SUCCESS) {
+ PyMem_Free(retBuf);
return PyErr_SetFromWindowsErrWithFunction(rc,
"RegQueryValueEx");
+ }
obData = Reg2Py(retBuf, bufSize, typ);
+ PyMem_Free((void *)retBuf);
if (obData == NULL)
return NULL;
result = Py_BuildValue("Oi", obData, typ);