如何通过Python Hook进程或修改程序,将云存储文件注入Slither的Stdin?
问题背景
我使用第三方Python工具包Slither,它仅支持通过本地文件路径调用(比如slither filename.sol)。现在要把它部署在Django API后端,捕获输出返回给用户,但应用运行在仅提供临时存储的Heroku平台上,所以选择Cloudinary存储文件,能获取到文件的Cloudinary URI(比如https://mybucket.cloundary.io/mybucket),但Slither不支持直接传入这类URI。
当前我是先把文件下载到本地./files/目录再调用:
subprocess.run( f"slither {'./files/'+filename}", stderr=subprocess.STDOUT, shell=True, timeout=120, universal_newlines=True )
希望实现直接传入Cloudinary URI调用Slither,比如:
subprocess.run( f"slither {'https://mybucket.cloundary.io/mybucket'}", stderr=subprocess.STDOUT, shell=True, timeout=120, universal_newlines=True )
可行解决方案
方案1:修改Slither源码添加URI支持
Slither是开源工具,直接修改它的入口逻辑就能添加HTTP/HTTPS URI支持:
- 找到Slither处理输入参数的核心文件(比如
slither/__main__.py) - 增加判断逻辑:如果输入是HTTP/HTTPS开头的URI,先用
requests下载文件到内存临时文件,再将临时文件路径传给原有处理逻辑 - 修改完成后重新打包Slither,替换Heroku环境中的依赖包
核心逻辑示例:
import tempfile import requests import os from slither.slither import Slither def main(target): if target.startswith(('http://', 'https://')): # 下载文件内容 resp = requests.get(target) resp.raise_for_status() # 创建临时文件 with tempfile.NamedTemporaryFile(suffix='.sol', delete=False) as tmp: tmp.write(resp.content) tmp_path = tmp.name # 用临时文件调用Slither slither = Slither(tmp_path) # 调用完成后删除临时文件 os.unlink(tmp_path) else: slither = Slither(target) # 后续输出处理逻辑...
方案2:Hook调用逻辑,自动下载URI到临时目录
不想修改Slither源码的话,可在调用前自行处理URI:
- 在Django视图中先判断传入的目标是否为Cloudinary URI
- 如果是,将文件下载到Heroku允许的临时可写目录
/tmp - 使用本地临时文件路径调用Slither,调用完成后删除临时文件
示例代码:
import os import requests import tempfile import subprocess def analyze_contract(target): local_path = target # 判断是否为URI if target.startswith(('http://', 'https://')): # 下载文件到/tmp临时目录 resp = requests.get(target) resp.raise_for_status() with tempfile.NamedTemporaryFile(suffix='.sol', delete=False, dir='/tmp') as tmp: tmp.write(resp.content) local_path = tmp.name # 调用Slither result = subprocess.run( f"slither {local_path}", stderr=subprocess.STDOUT, shell=True, timeout=120, universal_newlines=True, capture_output=True ) # 清理临时文件 if local_path.startswith('/tmp/'): os.unlink(local_path) return result.stdout
方案3:使用Slither的Python API直接处理内存内容
Slither提供Python API,无需通过subprocess调用,可直接处理内存中的文件内容:
- 下载Cloudinary文件内容到内存
- 直接将内容传给Slither API,无需写入本地文件
示例代码:
import requests from slither.slither import Slither def analyze_contract_from_uri(uri): # 下载文件内容 resp = requests.get(uri) resp.raise_for_status() contract_content = resp.text # 直接用内存内容初始化Slither slither = Slither(contracts_content=contract_content) # 收集分析结果 analysis_results = [] for detector in slither.detectors: detector.run() analysis_results.extend(detector.results) # 格式化结果返回 return "\n".join([str(res) for res in analysis_results])
内容的提问来源于stack exchange,提问作者djangonewbie
相关产品推荐
相关产品推荐

