ealeon
ealeon

Reputation: 12452

Python: checking for executable

is_exec = lambda x: subprocess.call("type " + x, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0 and (os.path.isfile(x) and os.access(x, os.X_OK))

I came across this code and it works fine but is it redundant?

Isnt is_exec = lambda x: os.access(x, os.X_OK) sufficient?

Question: Is there a case where is_exec = lambda x: os.access(x, os.X_OK) isnt catching but the first one does?

Upvotes: 0

Views: 141

Answers (2)

FatalError
FatalError

Reputation: 54551

There is a subtle difference here -- in the first call, this will also detect shell built-ins, for example:

$ type cd
cd is a shell builtin
$ echo $?
0

But there is no actual cd executable as such, so you can't check it explicitly with os.access(). That said, I believe it should actually be

is_exec = lambda x: subprocess.call("type " + x, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0 or (os.path.isfile(x) and os.access(x, os.X_OK))

Note that the middle operator is now or. Also, the subprocess pipes seem a bit superfluous here, and there is the caveat that it can be used as a shell injection to consider too.

All in all, if you only care about verifying exeutable files, then ditching the first bit is fine.

Upvotes: 1

chepner
chepner

Reputation: 530970

Both require os.access(x, os.X_OK) to return True. However, in addition to performing some unnecessary tests before calling os.access, the first opens you up to a shell injection attack unless you carefully screen the value of x before using it. Using shell=True with subprocess.call simply passes a string to the shell for execution. If the value of x is carefully constructed, you end up executing more than just the type command. For example:

x = "somefile.txt; rm foo.txt"
subprocess.call("type " + x, shell=True,
                stdout=subprocess.PIPE, stderr=subprocess.PIPE)

will pass the string "type somefile.txt; rm foo.txt" to the shell, resulting in two commands, not just one, in being executed.

Upvotes: 1

Related Questions