隐藏用户 运行 脚本的标准输入数据?
Hide stdin data from user running script?
我正在 spoj.com 上构建一个问题。用户必须提交一个脚本,该脚本将预先附加我的代码,为他提供他必须使用的功能。此类模板:
def youmustusethis(maptask, reducetask):
data = sys.stdin.readlines()
return reduce(reducetask, map(maptask, data))
##### USER WRITES CODE BELOW #####
....
有趣的是:用户经常破解输出而不是解决问题。我预计人们会忽略该功能并直接读取标准输入并完全忽略我提供的 "framework" 来处理它。
有没有办法从脚本的下半部分隐藏标准输入数据,从而强制使用我的框架来处理它?
这似乎是一个奇怪的要求。你可能应该只写一个便条说 "don't access sys.stdin" 或类似的东西。
在我的脑海中,您可以关闭 sys.stdin 或重新分配它。
例如:
_stdin = sys.stdin
sys.stdin = None
[编辑:我觉得我应该提一下,这通常是个坏主意。]
您可以这样做:
import sys
try:
import StringIO as io # python2
except ImportError:
import io # python3
# your functions go here
sys.stdin = io.StringIO()
如果您的用户尝试使用 stdin
,这将使正常的文件操作不会失败,但也不会通过。但是,您的用户可能难以诊断。
比较:
def fails_loudly():
"""throws AttributeError"""
sys.stdin = None
return sys.stdin.read()
def fails_silently():
"""returns empty string"""
sys.stdin = io.StringIO()
return sys.stdin.read()
我找到了可能的解决方案。显然我可以向用户展示一个模板并预先附加一个不同的模板(略有不同)所以,我告诉用户 "use this":
def youmustusethis(maptask, reducetask):
data = sys.stdin.readlines()
return reduce(reducetask, map(maptask, data))
##### USER WRITES CODE BELOW #####
虽然我预先附加了类似的内容:
def youmustusethis(maptask, reducetask):
DATA_48fsnk29s73kdhx7292k = sys.stdin.readlines()
return reduce(reducetask, map(maptask, DATA_48fsnk29s73kdhx7292k))
##### USER WRITES CODE BELOW #####
请注意,根据 SPOJ 判断,代码是 运行,仅显示用户 AC/WA,没有标准输出或标准错误。除非用户能猜出变量名,否则很难找到。
我的建议是——不要。为了使这项工作正常进行,您需要考虑很多事情。考虑以下片段:
sys.stdin = open("/dev/stdin")
对于 ctypes
,这可能会变得更加困难。我建议寻找某人已经创建的 sandboxing/restricted Python 环境,而不是试图混淆相当大的攻击媒介。我的猜测是 IRC 机器人的库应该已经正确地做到了这一点。
我正在 spoj.com 上构建一个问题。用户必须提交一个脚本,该脚本将预先附加我的代码,为他提供他必须使用的功能。此类模板:
def youmustusethis(maptask, reducetask):
data = sys.stdin.readlines()
return reduce(reducetask, map(maptask, data))
##### USER WRITES CODE BELOW #####
....
有趣的是:用户经常破解输出而不是解决问题。我预计人们会忽略该功能并直接读取标准输入并完全忽略我提供的 "framework" 来处理它。
有没有办法从脚本的下半部分隐藏标准输入数据,从而强制使用我的框架来处理它?
这似乎是一个奇怪的要求。你可能应该只写一个便条说 "don't access sys.stdin" 或类似的东西。
在我的脑海中,您可以关闭 sys.stdin 或重新分配它。 例如:
_stdin = sys.stdin
sys.stdin = None
[编辑:我觉得我应该提一下,这通常是个坏主意。]
您可以这样做:
import sys
try:
import StringIO as io # python2
except ImportError:
import io # python3
# your functions go here
sys.stdin = io.StringIO()
如果您的用户尝试使用 stdin
,这将使正常的文件操作不会失败,但也不会通过。但是,您的用户可能难以诊断。
比较:
def fails_loudly():
"""throws AttributeError"""
sys.stdin = None
return sys.stdin.read()
def fails_silently():
"""returns empty string"""
sys.stdin = io.StringIO()
return sys.stdin.read()
我找到了可能的解决方案。显然我可以向用户展示一个模板并预先附加一个不同的模板(略有不同)所以,我告诉用户 "use this":
def youmustusethis(maptask, reducetask):
data = sys.stdin.readlines()
return reduce(reducetask, map(maptask, data))
##### USER WRITES CODE BELOW #####
虽然我预先附加了类似的内容:
def youmustusethis(maptask, reducetask):
DATA_48fsnk29s73kdhx7292k = sys.stdin.readlines()
return reduce(reducetask, map(maptask, DATA_48fsnk29s73kdhx7292k))
##### USER WRITES CODE BELOW #####
请注意,根据 SPOJ 判断,代码是 运行,仅显示用户 AC/WA,没有标准输出或标准错误。除非用户能猜出变量名,否则很难找到。
我的建议是——不要。为了使这项工作正常进行,您需要考虑很多事情。考虑以下片段:
sys.stdin = open("/dev/stdin")
对于 ctypes
,这可能会变得更加困难。我建议寻找某人已经创建的 sandboxing/restricted Python 环境,而不是试图混淆相当大的攻击媒介。我的猜测是 IRC 机器人的库应该已经正确地做到了这一点。