Even when not evaling/cache-checking, we need to lock to prepend to · SufferProgrammer/mod_python@f8aaf8e · GitHub
Skip to content

Commit f8aaf8e

Browse files
committed
Even when not evaling/cache-checking, we need to lock to prepend to
path. Fix a bug where accessing an invalid attribute in hlist would segfault. There is no need to do any directory-related stuff if we are in a Location context. Added d_is_location flag to the hlist structure, and added checks for it. Skip map-to-storage phase when we are wrapped in a Location (it attempts to do a directory_walk). The implication is that Location trumps all Directory configs which have no effect. But it's much faster this way. Track down where in core.c the trailing slash is added as part of the why-are-we-doing-this research with respect to appending trailing slashes to all directories.
1 parent 652c06b commit f8aaf8e

5 files changed

Lines changed: 56 additions & 49 deletions

File tree

lib/python/mod_python/apache.py

Lines changed: 16 additions & 6 deletions

src/hlistobject.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ static void hlist_dealloc(hlistobject *self)
9191

9292
static PyObject *hlist_getattr(hlistobject *self, char *name)
9393
{
94-
PyObject *res;
94+
PyObject *res, *md;
9595

9696
res = Py_FindMethod(hlistmethods, (PyObject *)self, name);
9797
if (res != NULL)
@@ -106,8 +106,13 @@ static PyObject *hlist_getattr(hlistobject *self, char *name)
106106
return Py_None;
107107
}
108108

109-
return PyMember_GetOne((char*)self->head,
110-
find_memberdef(hlist_memberlist, name));
109+
md = find_memberdef(hlist_memberlist, name);
110+
if (!md) {
111+
PyErr_SetString(PyExc_AttributeError, name);
112+
return NULL;
113+
}
114+
115+
return PyMember_GetOne((char*)self->head, md);
111116
}
112117

113118
/**

src/mod_python.c

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -880,14 +880,8 @@ static py_config *python_create_config(apr_pool_t *p)
880880

881881
static void *python_create_dir_config(apr_pool_t *p, char *dir)
882882
{
883-
884883
py_config *conf = python_create_config(p);
885-
886-
/* make sure directory ends with a slash (TODO: Why?) */
887-
if (dir && (dir[strlen(dir) - 1] != '/'))
888-
conf->config_dir = apr_pstrcat(p, dir, "/", NULL);
889-
else
890-
conf->config_dir = apr_pstrdup(p, dir);
884+
conf->config_dir = dir;
891885

892886
return conf;
893887
}
@@ -1125,19 +1119,26 @@ static void determine_context(apr_pool_t *p, const cmd_parms* cmd,
11251119
* this point if no pattern matching to be done at
11261120
* a later time. */
11271121

1128-
if (!d_is_fnmatch && !regex) {
1122+
if (directory && !d_is_fnmatch && !regex && !d_is_location) {
11291123

1130-
char *newpath = 0;
1124+
char *newpath = NULL;
11311125
apr_status_t rv;
11321126

1127+
/* NB: if directory is not absolute, CWD will be prepended to
1128+
* it. If directory is NULL (we make sure it is not NULL
1129+
* above), then newpath will become CWD */
11331130
rv = apr_filepath_merge(&newpath, NULL, directory,
11341131
APR_FILEPATH_TRUENAME, p);
11351132

1136-
/* Should be able to ignore a failure as any
1137-
* problem with path should have been flagged
1138-
* when configuration was read in. */
1139-
11401133
if (rv == APR_SUCCESS || rv == APR_EPATHWILD) {
1134+
/*
1135+
* We are appending a trailing slash here to be consistent
1136+
* with what httpd's core.c does in dirsection(). I [GT]
1137+
* am not very clear why core.c does it, especially given
1138+
* that it appends the trailing slash even to things that
1139+
* aren't really directories, e.g. when directory is an
1140+
* fnmatch pattern such as "/foo/bar*"
1141+
*/
11411142
directory = newpath;
11421143
if (directory[strlen(directory) - 1] != '/') {
11431144
directory = apr_pstrcat(p, directory, "/", NULL);
@@ -1196,10 +1197,10 @@ static const char *python_directive_handler(cmd_parms *cmd, py_config* conf,
11961197
char d_is_location = 0;
11971198
ap_regex_t *regex = NULL;
11981199

1199-
/* d_is_location is used by the map_to_storage handler - there is no need for it to
1200-
run, if we are inside a Location */
1201-
12021200
determine_context(cmd->pool, cmd, &directory, &d_is_fnmatch, &d_is_location, &regex);
1201+
1202+
/* d_is_location is used by the map_to_storage handler - there is no need for it to
1203+
run, if we are inside a Location. We also do not prepend a Location to sys.path. */
12031204
conf->d_is_location = d_is_location;
12041205

12051206
/* a handler may be restricted to certain file type by
@@ -1394,22 +1395,19 @@ static const char *select_interp_name(request_rec *req, conn_rec *con,
13941395

13951396
/* base interpreter on directory where the file is found */
13961397
if (req && ap_is_directory(req->pool, req->filename)) {
1397-
/* Where req->filename is a directory, it is not guaranteed
1398-
* that it will have a trailing slash in req->filename as
1399-
* trailing slash redirection only happens in mod_dir at
1400-
* the very end of the fixup phase. Thus need to ensure
1401-
* that this is taken into consideration.
1398+
/*
1399+
* We are appending a trailing slash here to be
1400+
* consistent with what httpd's core.c does in
1401+
* dirsection(), or else we will end up with a
1402+
* different interpreter named without the slash.
14021403
*/
1403-
if (req->filename[strlen(req->filename)-1]=='/') {
1404+
if (req->filename[strlen(req->filename)-1]=='/')
14041405
return ap_make_dirstr_parent(req->pool, req->filename);
1405-
}
1406-
else {
1406+
else
14071407
return ap_make_dirstr_parent(req->pool,
1408-
apr_pstrcat(req->pool, req->filename,
1409-
"/", NULL ));
1410-
}
1411-
}
1412-
else {
1408+
apr_pstrcat(req->pool, req->filename,
1409+
"/", NULL ));
1410+
} else {
14131411
if (req && req->filename)
14141412
return ap_make_dirstr_parent(req->pool, req->filename);
14151413
else
@@ -1532,10 +1530,11 @@ static int python_handler(request_rec *req, char *phase)
15321530
hlist_extend(req->pool, hlohle, dynhle);
15331531
}
15341532

1535-
/* resolve wildcard or regex directory patterns */
1533+
/* resolve wildcard or regex directory patterns. we do not resolve
1534+
* Location patterns because there is no use case for it so far */
15361535
hle = hlohle;
15371536
while (hle) {
1538-
if (hle->d_is_fnmatch || hle->regex) {
1537+
if (!hle->d_is_location && (hle->d_is_fnmatch || hle->regex)) {
15391538
hle->directory = resolve_directory(req, hle->directory,
15401539
hle->d_is_fnmatch, hle->regex);
15411540
hle->d_is_fnmatch = 0;

test/htdocs/tests.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,14 +1270,8 @@ def PythonOption_items(req):
12701270
return apache.OK
12711271

12721272
def interpreter(req):
1273-
if req.phase == "PythonFixupHandler":
1274-
if req.filename[-1] != '/' and os.path.isdir(req.filename):
1275-
req.write(req.interpreter)
1276-
return apache.DONE
1277-
return apache.OK
1278-
else:
1279-
req.write(req.interpreter)
1280-
return apache.DONE
1273+
req.write(req.interpreter)
1274+
return apache.DONE
12811275

12821276
def index(req):
12831277
return "test ok, interpreter=%s" % req.interpreter

test/test.py

Lines changed: 0 additions & 1 deletion

0 commit comments

Comments
 (0)