So the reaction to my Python sys.exit blog entry included people claiming this is fine and that duck typing is not that important in the Python language, and why would you do this for real anyways?
To me it felt like this is the kind of quirks that are perfect to obfuscate code, so I try to see if I could use the fact that exceptions are silently swallowed for fun and profit. Let’s assume I want my code to call some sensitive API (which might throw Exceptions), but without leaving the tell-tale catch statements. This is what the code below does.
#!/usr/bin/env python3
import sys
def do_something_sensitive():
print("do_something_sensitive called")
raise PermissionError("Illegal access!")
class Worker:
def __init__(self, name):
self.name = name
self.error = None
def __str__(self):
if self.error:
return f"{self.name}: {self.error()}"
return self.name
def work(self):
self.error = do_something_sensitive
try:
w = Worker("Worker A")
print(f"Starting {w}")
w.work()
print(f"Done")
sys.exit(w)
except Exception as e:
sys.exit(f"Bad stuff: {e}", file=sys.stderr)
Execution on my machine is the following:
Starting Done do_something_sensitive called
The only hint that something went wrong is an exit status of 1. The PermissionError exception is silently swallowed, the exception handling block is never visited despite the fact that do_something_sensitive was called and threw. So if your code is trying to probe some security stuff, the only tell-tale will be an none zero exit status.
If the code catches SystemExit, you get more reasonable behaviour, do_something_sensitive is only called when __str__ is invoked and the exception is throw in that context.
Is it a security bug? I don’t know, but it looks like a mechanism to obfuscate malicious code.
