# 爬取镜像
docker pull smartbugs/osiris:d1ecc37
#创建Osiris相关的容器
docker run -it --privileged=true -v /home/wtf/Osiris_test:/Osiris_test --name Osiris smartbugs/osiris:d1ecc37
//这里不用加/bin/bash,它可以自动创建shell交互式命令行。
#使用Osiris测试合约
python ~/osiris/osiris.py -s ~/datasets/SimpleDAO/SimpleDAO_0.4.19.sol
## -s 后面是合约文件的路径
##批量测试脚本
建立批量测试脚本batch_test.py在Osiris_test目录下。
batch_test.py脚本示例
# -*- coding: utf-8 -*-
import subprocess
import re
import sys
from sklearn.metrics import accuracy_score, recall_score, precision_score, f1_score
# 在Python 2.7中设置默认编码为utf-8
reload(sys)
sys.setdefaultencoding('utf-8')
# 这一步确保Python 2.7能够正确处理UTF-8编码的字符串,避免在处理非ASCII字符时抛出UnicodeEncodeError。
# 文件路径
contract_names_file = '/Osiris_test/final_reentrancy_name_fixed.txt'
contract_labels_file = '/Osiris_test/final_reentrancy_label_fixed.txt'
# 读取合约文件名
with open(contract_names_file, 'r') as file:
contract_names = file.read().splitlines()
# 读取合约标签
with open(contract_labels_file, 'r') as file:
contract_labels = [int(label) for label in file.read().splitlines()]
# 确保合约名和标签的数量匹配
assert len(contract_names) == len(contract_labels), "合约文件名和标签数量不匹配"
predictions = []
true_labels = contract_labels
for contract in contract_names:
# 运行Osiris命令并捕获输出和错误
try:
filename = "/Osiris_test/sourcecode/" + contract.strip()
print("正在解析 {} 合约".format(contract))
result = subprocess.Popen(
['python', '/root/osiris/osiris.py', '-s', filename],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# 获取stdout和stderr的输出
osiris_output, error = result.communicate()
# 解码输出为utf-8,忽略无法解码的字符
osiris_output = osiris_output.decode('utf-8', 'ignore')
error = error.decode('utf-8', 'ignore')
# 将捕获到的输出从字节流解码为UTF-8字符串,使用'ignore'参数忽略无法解码的字符,防止抛出异常。
# 安全地打印错误输出,避免UnicodeEncodeError
# 使用encode('utf-8', 'replace')将无法编码的字符替换掉
print("Error output: {}".format(error.encode('utf-8', 'replace')))
#在Python 2.7中,直接打印包含非ASCII字符的字符串可能导致UnicodeEncodeError。
#通过先将字符串编码为UTF-8,并使用'replace'参数替换无法编码的字符,确保打印操作不会失败。
# 使用正则表达式匹配'Reentrancy bug: <空格或制表符> True'
reentrancy_match = re.search(r'Reentrancy\s+bug:\s+True', error)
if reentrancy_match:
print("{}:存在重入漏洞!".format(contract))
predictions.append(1)
else:
print("{}:没有检测到重入漏洞!".format(contract))
predictions.append(0)
except UnicodeDecodeError as e:
print("解码失败: ", e)
predictions.append(0)
# 计算评价指标
accuracy = accuracy_score(true_labels, predictions)
recall = recall_score(true_labels, predictions)
precision = precision_score(true_labels, predictions)
f1 = f1_score(true_labels, predictions)
print("准确率 (ACC): {:.4f}%".format(100 * accuracy))
print("召回率 (RE): {:.4f}%".format(100 * recall))
print("精确率 (PRE): {:.4f}%".format(100 * precision))
print("F1 指数: {:.4f}%".format(100 * f1))
batch_test测试脚本:测试大量合约,并将合约的真实标签传入,测试结束后,会直接算出准确率、召回率、精确率、F1指数。
#使用此脚本,要注意适用性,不然会报错的,不过,大家可以借鉴一下,旨在帮助大家更快的写出测试脚本。
# 安装 scikit-learn
pip install scikit-learn -i https://pypi.tuna.tsinghua.edu.cn/simple