Skip to content

Commit 8c18703

Browse files
committed
pySCG: Adding explanation of the 'is' operator to CWE-595
Signed-off-by: edanhub <[email protected]>
1 parent 911549c commit 8c18703

File tree

3 files changed

+50
-14
lines changed

3 files changed

+50
-14
lines changed

docs/Secure-Coding-Guide-for-Python/CWE-697/CWE-595/README.md

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ You want to implement the `__eq__` method on a class if you believe you ever wan
66

77
## Non-Compliant Code Example
88

9-
The non-compliant code shows how the default comparison operator compares object references rather than the object values. Furthermore, it displays how this causes issues when comparing lists of objects, although it applies to other types of collections as well. Finally, it shows how the `in` operator also depends on the behavior of the `__eq__` method and, therefore, also returns a non-desirable result.
9+
The non-compliant code shows how the default comparison operator compares object references rather than the object values. Furthermore, it displays how this causes issues when comparing lists of objects, although it applies to other types of collections as well. Then, it shows how the `in` operator also depends on the behavior of the `__eq__` method and, therefore, also returns a non-desirable result. Finally, it performs the comparison with the `is` operator, which checks as to whether the references point to the same object regardless of the stored value.
1010

1111
[*noncompliant01.py:*](noncompliant01.py)
1212

@@ -27,41 +27,59 @@ print(Integer(12) == Integer(12))
2727
print([Integer(12)] == [Integer(12)])
2828
# And this is equally this will always be False as well
2929
print(Integer(12) in [Integer(10), Integer(12)])
30+
# The 'is' will return True only if both references point to the same object
31+
a = Integer(12)
32+
b = a
33+
# Here, a and b point to the same Integer, so 'is' returns True
34+
print(a is b)
35+
36+
b = Integer(12)
37+
# Even though b still points to an Integer of the same value, it is a new object, so 'is' returns False
38+
print(a is b)
3039

3140
```
3241

3342
## Compliant Solution
3443

35-
In this compliant solution the `__eq__` method is implemented and all the comparisons now correctly compares the object values, rather than the object reference.
44+
In this compliant solution, the `__eq__` method is implemented and the comparisons that not use `is` now correctly compare the object values, rather than the object reference. The `is` operator does not call `__eq__`, hence the last print will still display `False`.
3645

3746
[*compliant01.py:*](compliant01.py)
3847

3948
```py
4049
""" Compliant Code Example """
41-
42-
50+
51+
4352
class Integer:
4453
def __init__(self, value):
4554
self.value = value
46-
55+
4756
def __eq__(self, other):
4857
if isinstance(other, type(self)):
4958
return self.value == other.value
5059
if isinstance(other, int):
5160
return self.value == other
5261
return False
53-
54-
62+
63+
5564
#####################
5665
# exploiting above code example
5766
#####################
5867
# All these scenarios will now show True
5968
print(Integer(12) == Integer(12))
6069
print([Integer(12)] == [Integer(12)])
6170
print(Integer(12) in [Integer(10), Integer(12)])
62-
71+
6372
# By adding the handling for int we also support
6473
print(Integer(12) == 12)
74+
# The 'is' will return True only if both references point to the same object
75+
a = Integer(12)
76+
b = a
77+
# Here, a and b point to the same Integer, so 'is' returns True
78+
print(a is b)
79+
80+
b = Integer(12)
81+
# Since the 'is' operator does not call __eq__, print below will still return False
82+
print(a is b)
6583

6684
```
6785

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,36 @@
11
# SPDX-FileCopyrightText: OpenSSF project contributors
22
# SPDX-License-Identifier: MIT
33
""" Compliant Code Example """
4-
5-
4+
5+
66
class Integer:
77
def __init__(self, value):
88
self.value = value
9-
9+
1010
def __eq__(self, other):
1111
if isinstance(other, type(self)):
1212
return self.value == other.value
1313
if isinstance(other, int):
1414
return self.value == other
1515
return False
16-
17-
16+
17+
1818
#####################
1919
# exploiting above code example
2020
#####################
2121
# All these scenarios will now show True
2222
print(Integer(12) == Integer(12))
2323
print([Integer(12)] == [Integer(12)])
2424
print(Integer(12) in [Integer(10), Integer(12)])
25-
25+
2626
# By adding the handling for int we also support
2727
print(Integer(12) == 12)
28+
# The 'is' will return True only if both references point to the same object
29+
a = Integer(12)
30+
b = a
31+
# Here, a and b point to the same Integer, so 'is' returns True
32+
print(a is b)
33+
34+
b = Integer(12)
35+
# Since the 'is' operator does not call __eq__, print below will still return False
36+
print(a is b)

docs/Secure-Coding-Guide-for-Python/CWE-697/CWE-595/noncompliant01.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,12 @@ def __init__(self, value):
1616
print([Integer(12)] == [Integer(12)])
1717
# And this is equally this will always be False as well
1818
print(Integer(12) in [Integer(10), Integer(12)])
19+
# The 'is' will return True only if both references point to the same object
20+
a = Integer(12)
21+
b = a
22+
# Here, a and b point to the same Integer, so 'is' returns True
23+
print(a is b)
24+
25+
b = Integer(12)
26+
# Even though b still points to an Integer of the same value, it is a new object, so 'is' returns False
27+
print(a is b)

0 commit comments

Comments
 (0)