You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mod_python-dev@quetz.apache.org by "Graham Dumpleton (JIRA)" <ji...@apache.org> on 2005/04/03 11:24:16 UTC

[jira] Commented: (MODPYTHON-43) mod_python.publisher auth functions access to globals

     [ http://issues.apache.org/jira/browse/MODPYTHON-43?page=comments#action_62042 ]
     
Graham Dumpleton commented on MODPYTHON-43:
-------------------------------------------

It is worth noting that the original code is fragile in other ways as well.
Specifically, the code is probably only gauranteed to work if the nested
auth functions are the first nested functions in the method. If they aren't
then any nested functions appearing before them must not have default
parameters.

Take for example the following code:

  def func1():
    def func2(a,b="b"):
      pass
    def __auth__(req,user,password):
      pass

  func_code = func1.func_code

  print func_code.co_names
  print func_code.co_consts

  print list(func_code.co_names).index("__auth__")
  print func_code.co_consts[list(func_code.co_names).index("__auth__")+1]

When run this produces:

  ('func2', '__auth__')
  (None, 'b', <code object func2 at 0x61a60, file "bug.py", line 2>, <code object __auth__ at 0x61aa0, file "bug.py", line 4>)
  1
  <code object func2 at 0x61a60, file "bug.py", line 2>

Where the code is supposed to select __auth__(), it is errornously selecting
func2() instead. This is because the constants that represent the default
parameters of the first nested functions, are throwing out the calculation
to work out which is the code object for __auth__().

Even if func2() didn't exist, the selection process would also be thrown out
if __auth__() itself had any default parameters.

So far from what I can work out, there doesn't seem to be a way of knowing
when extra constants are inserted which correspond to default parameters
of nested functions.

Thus, to be safe, one must ensure auth functions are the first things to be
defined in the function and that the auth functions themselves should not
have any default parameters.

> mod_python.publisher auth functions access to globals
> -----------------------------------------------------
>
>          Key: MODPYTHON-43
>          URL: http://issues.apache.org/jira/browse/MODPYTHON-43
>      Project: mod_python
>         Type: Improvement
>   Components: publisher
>     Versions: 3.1.4
>     Reporter: Graham Dumpleton
>     Priority: Minor

>
> In the mod_python.publisher code, the code for performing basic authentication
> has in a few spots code of the form:
>             if "__auth__" in func_code.co_names: 
>                 i = list(func_code.co_names).index("__auth__")
>                 __auth__ = func_code.co_consts[i+1]
>                 if hasattr(__auth__, "co_name"):
>                     __auth__ = new.function(__auth__, globals())
>                 found_auth = 1
> What this does is that if the target of the request is a function and that function
> contains a nested function, which in this case is called "__auth__", then that
> nested function is turned into a callable object and is subsequently called to
> determine if the user is able to perform the request.
> In making the nested function callable, it uses "globals()". By using this though
> it is using the globals from the mod_python.publisher module and not the
> module which the nested function is contained within. This means that the
> following code will actually fail.
>   import xxx
>   def function(req):
>     def __auth__(req,username,password):
>       return xxx.auth(req,username,password)
> This is because the module "xxx" imported at global scope within the module isn't
> available to the nested function when it is called as it is seeing the globals of
> mod_python.publisher instead. To get around the problem, the import has to be
> local to the nested function.
>   def function(req):
>     def __auth__(req,username,password):
>       import xxx
>       return xxx.auth(req,username,password)
> Since in this case the auth function being called is a nested function, we know that
> we can actually grab the globals for the correct module by getting "func_globals"
> from the enclosing function.
>             if "__auth__" in func_code.co_names: 
>                 i = list(func_code.co_names).index("__auth__")
>                 __auth__ = func_code.co_consts[i+1]
>                 if hasattr(__auth__, "co_name"):
>                     __auth__ = new.function(__auth__, object.func_globals)
>                 found_auth = 1
> Ie., instead of "globals()", use "object.func_globals" where "object is the enclosing
> function object.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
If you want more information on JIRA, or have a bug to report see:
   http://www.atlassian.com/software/jira