Issue Details (XML | Word | Printable)

Key: MODPYTHON-187
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Graham Dumpleton
Reporter: Alan Kennedy
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
mod_python

Hang on subscripted access to request.subprocess_env.

Created: 28/Aug/06 03:40 PM   Updated: 01/May/07 10:46 AM
Return to search
Component/s: core
Affects Version/s: 3.2.10
Fix Version/s: 3.3.1

Time Tracking:
Not Specified

File Attachments:
  Size
File Licensed for inclusion in ASF works MP187-2006-08-28-jgallacher-1.diff 2006-08-29 12:51 AM Jim Gallacher 0.7 kB
Environment:
Apache: 2.0.59
ModPython: 3.2.10
Python: 2.4
OS: Windows Server 2003

Resolution Date: 02/Oct/06 04:51 AM


 Description  « Hide
When subscripted access is used to access variable 'SCRIPT_FILENAME' in the request.subprocess_env table/mapping, the code hangs.

The following snippet illustrates the problem.

# -=-=-=-=-=-=

def postreadrequesthandler(request):
  request.add_common_vars()
  value = request.subprocess_env['SCRIPT_FILENAME'] # This hangs
# value = request.subprocess_env.get('SCRIPT_FILENAME')# This works
  return apache.OK

# -=-=-=-=-=-=

The strange thing is that the .get() access works fine: only the subscript hangs?

If anyone is wondering about a use-case, I don't actually have one. I was just iterating over the contents of the request.subprocess_env using a for loop (code below), and found that the code hung when accessing 'SCRIPT_FILENAME', and not for any other variable.

# -=-=-=
request.add_common_vars()
d = {}
for sek in request.subprocess_env.keys():
  d[sek] = request.subprocess_env[sek]
# -=-=-=


 All   Comments   Work Log   Change History   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Jim Gallacher added a comment - 29/Aug/06 12:01 AM
Confirmed for Apache 2.0.55 mpm-worker (Linux Ubuntu 6.0.6), execpt I get a segfault rather than a hang.

Note that the Post Read Request phase occurs before apache translates the URI to a filename. request.subprocess_env.get('SCRIPT_FILENAME') seems to do the right thing by returning None.

Jim Gallacher added a comment - 29/Aug/06 12:48 AM
The problem seems to be in the tableobject.c function table_subscript().

subprocess_env.get['SCRIPT_FILENAME'] is being evaluated in the post read request phase. It would seem that req.add_common_vars adds a key for SCRIPT_FILENAME to the table, but since the filename has not been translated yet its value is NULL.

table_subscript() retrieves the value with the following bit of code:

   while (i--)
        if (elts[i].key) {
            if (apr_strnatcasecmp(elts[i].key, k) == 0) {
                PyObject *v = PyString_FromString(elts[i].val);
                PyList_Insert(list, 0, v);
                Py_DECREF(v);
            }
        }

The problem is with the PyString_FromString. According to the python docs, the parameter passed must not be NULL and it will not be checked. I assume this is the origin of the segfault.

Something like the following seems to fix the problem.

The following code snippet seems to fix the problem, and is attached as MP187-2006-08-28-jgallacher-1.diff. Am I correct in doing the PY_INCREF(v)??

     while (i--)
         if (elts[i].key) {
             if (apr_strnatcasecmp(elts[i].key, k) == 0) {
- PyObject *v = PyString_FromString(elts[i].val);
+ PyObject *v = NULL;
+ if (elts[i].val != NULL) {
+ v = PyString_FromString(elts[i].val);
+ } else {
+ v = Py_None;
+ Py_INCREF(v);
+ }
                 PyList_Insert(list, 0, v);
                 Py_DECREF(v);




Jim Gallacher added a comment - 29/Aug/06 12:51 AM
I hope I have the reference count right!

Jim Gallacher made changes - 29/Aug/06 12:51 AM
Field Original Value New Value
Attachment MP187-2006-08-28-jgallacher-1.diff [ 12339728 ]
Jim Gallacher added a comment - 30/Aug/06 10:41 AM
I've audited tableobject.c for other lines where NULL is being passed to PyString_FromString and found a few functions that may segfault if they are called in the post read request phase where SCRIPT_FILENAME is NULL.

Line numbers are for version 3.3.0-dev-20060827, r437300.

line 178 in table_repr()
            PyString_ConcatAndDel(&s, PyString_FromString(elts[i].val));


line 366 in function table_values()
            PyObject *val = PyString_FromString(elts[i].val);

line 792 in function table_traverse()
            PyObject *v = PyString_FromString(elts[i].val);

line 845 in function select_value()
    return PyString_FromString(elts->val);

We should audit all our code to make sure we are not making the same mistake with PyString_FromString elsewhere.

Graham Dumpleton made changes - 11/Sep/06 10:28 AM
Fix Version/s 3.3 [ 12310101 ]
Graham Dumpleton made changes - 02/Oct/06 03:21 AM
Assignee Graham Dumpleton [ grahamd ]
Graham Dumpleton made changes - 02/Oct/06 03:21 AM
Status Open [ 1 ] In Progress [ 3 ]
Repository Revision Date User Message
ASF #451878 Mon Oct 02 04:49:35 UTC 2006 grahamd (MODPYTHON-187) Table objects could crash in various ways when the value of
an item was NULL. This could occur for SCRIPT_FILENAME when the
req.subprocess_env table was accessed in the post read request handler
phase.
Files Changed
MODIFY /httpd/mod_python/trunk/test/htdocs/tests.py
MODIFY /httpd/mod_python/trunk/src/tableobject.c
MODIFY /httpd/mod_python/trunk/Doc/appendixc.tex

Graham Dumpleton added a comment - 02/Oct/06 04:51 AM
Although table_traverse() was changed, not sure it is every called as garbage collecting not enabled for this class type.

Graham Dumpleton made changes - 02/Oct/06 04:51 AM
Resolution Fixed [ 1 ]
Status In Progress [ 3 ] Resolved [ 5 ]
Repository Revision Date User Message
ASF #451881 Mon Oct 02 04:56:19 UTC 2006 grahamd (MODPYTHON-189) Fixed representation returned by calling repr() on a table
object. Note this was committed as part of change for MODPYTHON-187.
Files Changed
MODIFY /httpd/mod_python/trunk/Doc/appendixc.tex

Graham Dumpleton made changes - 01/May/07 10:46 AM
Status Resolved [ 5 ] Closed [ 6 ]