jsommers / pytricia

A library for fast IP address lookup in Python.
GNU Lesser General Public License v3.0
216 stars 22 forks source link

Bugfix: pytricia_contains must return -1 on error, rather than 0 #32

Closed 0xl3x1 closed 4 years ago

0xl3x1 commented 4 years ago

This PR addresses incorrect error handling logic for the containment operation in pytricia.c.

Demonstration of the bug in the current pytricia master branch (29ff816):

import pytricia
import traceback

pyt = pytricia.PyTricia(128)

try:
    # this is the line that raises the exception:
    if "42" in pyt:
        pass
except Exception as e:
    print("This one should be triggered")
    print(e)

try:
    print(len("hello"))
except Exception as e:
    print("This one is triggered instead")
    print(e)
    traceback.print_exc()

Expected Output:

This one should be triggered
Invalid key type
5

Actual Output:

This one is triggered instead
<built-in function len> returned a result with an error set
ValueError: Invalid key type

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "test.py", line 15, in <module>
    print(len("hello"))
SystemError: <built-in function len> returned a result with an error set

The Python C API documentation for PySequence_Contains says:

Determine if o contains value. If an item in o is equal to value, return 1, otherwise return 0. On error, return -1. This is equivalent to the Python expression value in o.

However, pytricia_contains currently returns 0 instead of -1 in the case of an error, and at the same time the call to _key_object_to_prefix raises a Python exception, which results in undefined Python exception handling behaviour. This PR fixes the issue.