119 lines
3.5 KiB
Plaintext
119 lines
3.5 KiB
Plaintext
|
|
Accessing attributes on `None` is almost always a logical error and will raise
|
|
an `AttributeError`.
|
|
To fix this issue, make sure not to access an attribute or method on a value
|
|
that can be `None`.
|
|
|
|
== Why is this an issue?
|
|
|
|
`None` is a built-in object that represents the absence of a value.
|
|
It is often used as a placeholder value for variables that only sometimes hold a
|
|
value or as a return value for method calls that have no result.
|
|
|
|
Attributes and methods of symbols that sometimes can be `None` should only be
|
|
accessed in circumstances where it is certain that they are not set to `None`.
|
|
Otherwise, an `AttributeError` is raised, and the program is interrupted.
|
|
Hence, this issue indicates a logical error as it results from incorrect
|
|
assumptions about the state of variables or the results of computations.
|
|
|
|
=== What is the potential impact?
|
|
|
|
include::../../../shared_content/layc/exception-impact.adoc[]
|
|
|
|
If a `None` value can be induced by user input, this issue may even be
|
|
exploited by attackers to disrupt your application or gain information from
|
|
stack traces.
|
|
|
|
=== Exceptions
|
|
|
|
`None` does support a fixed set of special attributes like `++__class__++` or
|
|
`++__bool__++`, and this issue is not raised when accessing these attributes.
|
|
|
|
== How to fix it
|
|
|
|
If your code contains `if-else` statements or similar constructs where some
|
|
branches potentially assign the `None` value to a variable, you must ensure
|
|
that this variable is handled safely afterwards.
|
|
I.e., its attributes should not be accessed at all or only after explicitly
|
|
confirming that it is not `None`.
|
|
|
|
Similarly, for any function calls that can return `None` under certain
|
|
conditions, carefully confirm that your code avoids these conditions.
|
|
Again, the safest approach is to check for a `None` return value explicitly.
|
|
|
|
=== Code examples
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,python,diff-id=1,diff-type=noncompliant]
|
|
----
|
|
def render(file_path):
|
|
if os.path.isfile(file_path):
|
|
data = interpret_csv(file_path)
|
|
else:
|
|
data = None
|
|
|
|
# ...
|
|
|
|
data.plot_graph() # Noncompliant
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,python,diff-id=1,diff-type=compliant]
|
|
----
|
|
def render(file_path):
|
|
if os.path.isfile(file_path):
|
|
data = interpret_csv(file_path)
|
|
else:
|
|
data = None
|
|
|
|
# ...
|
|
|
|
if data is not None:
|
|
data.plot_graph()
|
|
else:
|
|
print("No data available.")
|
|
----
|
|
|
|
=== How does this work?
|
|
|
|
In the given example, the function `render` tries to load information into a
|
|
variable `data`, depending on whether `file_path` is a path to a file.
|
|
If this is not the case, `None` is assigned to `data`.
|
|
|
|
At the end of the function, a method `plot_graph()` is called on `data`.
|
|
The call is sure to fail if `data` was assigned to `None`.
|
|
This is prevented by checking first whether `data` is not `None` before
|
|
performing the call.
|
|
|
|
== Resources
|
|
|
|
=== Documentation
|
|
|
|
* The Python Data Model on https://docs.python.org/3/reference/datamodel.html#none[None]
|
|
* https://docs.python.org/3/library/exceptions.html#AttributeError[Attribute Error]
|
|
* https://docs.python.org/3/reference/expressions.html#attribute-references[Attribute References]
|
|
|
|
=== Articles & blog posts
|
|
|
|
* CVE - https://cwe.mitre.org/data/definitions/476[CWE-476 - NULL Pointer Dereference]
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
include::../message.adoc[]
|
|
|
|
include::../highlighting.adoc[]
|
|
|
|
'''
|
|
== Comments And Links
|
|
(visible only on this page)
|
|
|
|
include::../comments-and-links.adoc[]
|
|
|
|
endif::env-github,rspecator-view[]
|