Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
dcebe0f2
Commit
dcebe0f2
authored
Mar 15, 2011
by
Michael Foord
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Closes issue 11133. Fixes two cases where inspect.getattr_static could trigger code execution
parent
c867239a
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
75 additions
and
13 deletions
+75
-13
Doc/library/inspect.rst
Doc/library/inspect.rst
+3
-6
Lib/inspect.py
Lib/inspect.py
+21
-6
Lib/test/test_inspect.py
Lib/test/test_inspect.py
+47
-0
Misc/NEWS
Misc/NEWS
+4
-1
No files found.
Doc/library/inspect.rst
View file @
dcebe0f2
...
...
@@ -589,13 +589,10 @@ but avoids executing code when it fetches attributes.
that raise AttributeError). It can also return descriptors objects
instead of instance members.
.. versionadded:: 3.2
If the instance `__dict__` is shadowed by another member (for example a
property) then this function will be unable to find instance members.
The only known case that can cause `getattr_static` to trigger code execution,
and cause it to return incorrect results (or even break), is where a class uses
:data:`~object.__slots__` and provides a `__dict__` member using a property or
descriptor. If you find other cases please report them so they can be fixed
or documented.
.. versionadded:: 3.2
`getattr_static` does not resolve descriptors, for example slot descriptors or
getset descriptors on objects implemented in C. The descriptor object
...
...
Lib/inspect.py
View file @
dcebe0f2
...
...
@@ -1069,15 +1069,16 @@ def _check_instance(obj, attr):
instance_dict
=
object
.
__getattribute__
(
obj
,
"__dict__"
)
except
AttributeError
:
pass
return
instance_dict
.
get
(
attr
,
_sentinel
)
return
dict
.
get
(
instance_dict
,
attr
,
_sentinel
)
def
_check_class
(
klass
,
attr
):
for
entry
in
_static_getmro
(
klass
):
try
:
return
entry
.
__dict__
[
attr
]
except
KeyError
:
pass
if
not
_shadowed_dict
(
type
(
entry
)):
try
:
return
entry
.
__dict__
[
attr
]
except
KeyError
:
pass
return
_sentinel
def
_is_type
(
obj
):
...
...
@@ -1087,6 +1088,19 @@ def _is_type(obj):
return
False
return
True
def
_shadowed_dict
(
klass
):
dict_attr
=
type
.
__dict__
[
"__dict__"
]
for
entry
in
_static_getmro
(
klass
):
try
:
class_dict
=
dict_attr
.
__get__
(
entry
)[
"__dict__"
]
except
KeyError
:
pass
else
:
if
not
(
type
(
class_dict
)
is
types
.
GetSetDescriptorType
and
class_dict
.
__name__
==
"__dict__"
and
class_dict
.
__objclass__
is
entry
):
return
True
return
False
def
getattr_static
(
obj
,
attr
,
default
=
_sentinel
):
"""Retrieve attributes without triggering dynamic lookup via the
...
...
@@ -1101,8 +1115,9 @@ def getattr_static(obj, attr, default=_sentinel):
"""
instance_result
=
_sentinel
if
not
_is_type
(
obj
):
instance_result
=
_check_instance
(
obj
,
attr
)
klass
=
type
(
obj
)
if
not
_shadowed_dict
(
klass
):
instance_result
=
_check_instance
(
obj
,
attr
)
else
:
klass
=
obj
...
...
Lib/test/test_inspect.py
View file @
dcebe0f2
...
...
@@ -906,6 +906,53 @@ class TestGetattrStatic(unittest.TestCase):
self
.
assertEqual
(
inspect
.
getattr_static
(
Something
(),
'foo'
),
3
)
self
.
assertEqual
(
inspect
.
getattr_static
(
Something
,
'foo'
),
3
)
def
test_dict_as_property
(
self
):
test
=
self
test
.
called
=
False
class
Foo
(
dict
):
a
=
3
@
property
def
__dict__
(
self
):
test
.
called
=
True
return
{}
foo
=
Foo
()
foo
.
a
=
4
self
.
assertEqual
(
inspect
.
getattr_static
(
foo
,
'a'
),
3
)
self
.
assertFalse
(
test
.
called
)
def
test_custom_object_dict
(
self
):
test
=
self
test
.
called
=
False
class
Custom
(
dict
):
def
get
(
self
,
key
,
default
=
None
):
test
.
called
=
True
super
().
get
(
key
,
default
)
class
Foo
(
object
):
a
=
3
foo
=
Foo
()
foo
.
__dict__
=
Custom
()
self
.
assertEqual
(
inspect
.
getattr_static
(
foo
,
'a'
),
3
)
self
.
assertFalse
(
test
.
called
)
def
test_metaclass_dict_as_property
(
self
):
class
Meta
(
type
):
@
property
def
__dict__
(
self
):
self
.
executed
=
True
class
Thing
(
metaclass
=
Meta
):
executed
=
False
def
__init__
(
self
):
self
.
spam
=
42
instance
=
Thing
()
self
.
assertEqual
(
inspect
.
getattr_static
(
instance
,
"spam"
),
42
)
self
.
assertFalse
(
Thing
.
executed
)
class
TestGetGeneratorState
(
unittest
.
TestCase
):
...
...
Misc/NEWS
View file @
dcebe0f2
...
...
@@ -40,6 +40,9 @@ Core and Builtins
Library
-------
-
Issue
#
11133
:
fix
two
cases
where
inspect
.
getattr_static
can
trigger
code
execution
.
Patch
by
Daniel
Urban
.
-
Issue
#
11501
:
disutils
.
archive_utils
.
make_zipfile
no
longer
fails
if
zlib
is
not
installed
.
Instead
,
the
zipfile
.
ZIP_STORED
compression
is
used
to
create
the
ZipFile
.
Patch
by
Natalia
B
.
Bidart
.
...
...
@@ -48,7 +51,7 @@ Library
encoding
was
not
done
if
euc
-
jp
or
shift
-
jis
was
specified
as
the
charset
.
-
Issue
#
11500
:
Fixed
a
bug
in
the
os
x
proxy
bypass
code
for
fully
qualified
IP
addresses
in
the
proxy
exception
list
.
IP
addresses
in
the
proxy
exception
list
.
-
Issue
#
11491
:
dbm
.
error
is
no
longer
raised
when
dbm
.
open
is
called
with
the
"n"
as
the
flag
argument
and
the
file
exists
.
The
behavior
matches
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment