import pandas as pd
import os
import re
from openai import OpenAI, OpenAIError
from tqdm import tqdm
from concurrent.futures import ThreadPoolExecutor, as_completed
import json
import time
def generate_deepseek_analysis(cve_name, api_key="your key",
base_url="https://api.deepseek.com", max_workers=25,
input_file_suffix="_top50.csv", cache_dir="../cache"):
print(f"开始处理CVE: {cve_name}")
input_file = f'{cache_dir}/{cve_name}{input_file_suffix}'
if not os.path.exists(input_file):
raise FileNotFoundError(f"输入文件不存在: {input_file}")
new_df = pd.read_csv(input_file)
new_df['msg_text'] = new_df['msg_text'].fillna('')
new_df['diff_code'] = new_df['diff_code'].fillna('')
new_df['cwe'] = new_df['cwe'].apply(eval)
new_df['cwe'] = new_df['cwe'].apply(lambda x: [t[1] for t in x] if x else [])
new_df['cwe'] = new_df['cwe'].apply(lambda x: [] if all(item == 'Other' for item in x) else x)
for index, row in new_df.iterrows():
diff_code = row['diff_code']
if len(diff_code) > 50000:
diff_code = diff_code[:50000]
if len(row['cwe']) == 0:
user_prompt = f"Role: You are a security analyst with expertise in analyzing code changes for functionality and intent, as well as identifying whether those changes address known vulnerabilities or security issues.\n\nYou will be provided with the following information: CVE ID, CVE description (including details about the vulnerability, such as the type of vulnerability, the file or function where it occurs, and its cause), Commit message (the description of the commit), and Commit diff code (the specific code changes in the commit).\n\nFirst, analyze the code changes in the commit diff code, summarize the main changes, and identify any potential vulnerabilities that may be addressed. Common vulnerability types include, but are not limited to: buffer overflow, directory traversal, priviege escalation. If the commit modifies security-relevant code (e.g., memory management, input validation, authentication logic), analyze whether it strengthens security or fixes an existing vulnerability.\n\nSecond, based on your analysis, compare the commit message, code changes and the potential vulnerabilities it addresses with the CVE description to determine whether this commit is a patch for the CVE.\n\nAdditionally, at the end of your response, please summarize the following:\n1. A brief summary of the commit\n2. A list of potential vulnerability types addressed by the commit\n3. Whether this commit is a patch for the vulnerability (YES, NO, or UNKNOWN)\n\nPlease output the results in JSON format as shown below:\n{{\n \"summarization\": \"summary of the commit\",\n \"potential addressed vulnerability types\": [\"buffer overflow\", \"directory traversal\", ...],\n \"is_patch\": \"YES/NO/UNKNOWN\"\n}}\n\nCVE ID:\n{row['cve']}\n\nCVE description:\n{row['desc']}\n\ncommit message:\n{row['msg_text']}\n\ncommit diff code:\n{diff_code}"
elif len(row['cwe']) == 1:
user_prompt = f"Role: You are a security analyst with expertise in analyzing code changes for functionality and intent, as well as identifying whether those changes address known vulnerabilities or security issues.\n\nYou will be provided with the following information: CVE ID, CVE description (including details about the vulnerability, such as the type of vulnerability, the file or function where it occurs, and its cause), Commit message (the description of the commit), and Commit diff code (the specific code changes in the commit).\n\nFirst, analyze the code changes in the commit diff code, summarize the main changes, and identify any potential vulnerabilities that may be addressed. Common vulnerability types include, but are not limited to: buffer overflow, directory traversal, priviege escalation. If the commit modifies security-relevant code (e.g., memory management, input validation, authentication logic), analyze whether it strengthens security or fixes an existing vulnerability.\n\nSecond, based on your analysis, compare the commit message, code changes and the potential vulnerabilities it addresses with the CVE description to determine whether this commit is a patch for the CVE.\n\nAdditionally, at the end of your response, please summarize the following:\n1. A brief summary of the commit\n2. A list of potential vulnerability types addressed by the commit\n3. Whether this commit is a patch for the vulnerability (YES, NO, or UNKNOWN)\n\nPlease output the results in JSON format as shown below:\n{{\n \"summarization\": \"summary of the commit\",\n \"potential addressed vulnerability types\": [\"buffer overflow\", \"directory traversal\", ...],\n \"is_patch\": \"YES/NO/UNKNOWN\"\n}}\n\nCVE ID:\n{row['cve']}\n\nCVE description:\n{row['desc']} Its vulnerability type:{row['cwe'][0]}\n\ncommit message:\n{row['msg_text']}\n\ncommit diff code:\n{diff_code}"
elif len(row['cwe']) > 1:
result = ', '.join(row['cwe'])
user_prompt = f"Role: You are a security analyst with expertise in analyzing code changes for functionality and intent, as well as identifying whether those changes address known vulnerabilities or security issues.\n\nYou will be provided with the following information: CVE ID, CVE description (including details about the vulnerability, such as the type of vulnerability, the file or function where it occurs, and its cause), Commit message (the description of the commit), and Commit diff code (the specific code changes in the commit).\n\nFirst, analyze the code changes in the commit diff code, summarize the main changes, and identify any potential vulnerabilities that may be addressed. Common vulnerability types include, but are not limited to: buffer overflow, directory traversal, priviege escalation. If the commit modifies security-relevant code (e.g., memory management, input validation, authentication logic), analyze whether it strengthens security or fixes an existing vulnerability.\n\nSecond, based on your analysis, compare the commit message, code changes and the potential vulnerabilities it addresses with the CVE description to determine whether this commit is a patch for the CVE. \n\nAdditionally, at the end of your response, please summarize the following:\n1. A brief summary of the commit\n2. A list of potential vulnerability types addressed by the commit\n3. Whether this commit is a patch for the vulnerability (YES, NO, or UNKNOWN)\n\nPlease output the results in JSON format as shown below:\n{{\n \"summarization\": \"summary of the commit\",\n \"potential addressed vulnerability types\": [\"buffer overflow\", \"directory traversal\", ...],\n \"is_patch\": \"YES/NO/UNKNOWN\"\n}}\n\nCVE ID:\n{row['cve']}\n\nCVE description:\n{row['desc']} Its vulnerability type:{result}\n\ncommit message:\n{row['msg_text']}\n\ncommit diff code:\n{diff_code}"
new_df.at[index, 'prompt'] = user_prompt
new_df = new_df[['cve', 'commit', 'prompt']]
client = OpenAI(
api_key=api_key,
base_url=base_url,
timeout=200
)
MAX_RETRIES = 3
RETRY_DELAY = 5
def process_row(index, row):
prompt = row.prompt
if len(prompt) > 64000:
prompt = prompt[:64000]
retries = 0
completion = ''
while retries < MAX_RETRIES:
try:
completion = client.chat.completions.create(
model="deepseek-chat",
store=True,
messages=[
{"role": "user", "content": prompt}
]
)
break
except OpenAIError as e:
print(f"调用 API 时第 {index} 行出错: {e},重试第 {retries + 1} 次...")
retries += 1
time.sleep(RETRY_DELAY)
except Exception as e:
print(f"第 {index} 行出现非 API 相关异常: {e},不再重试")
break
else:
print(f"第 {index} 行请求重试 {MAX_RETRIES} 次后仍然失败")
return index, False, ''
if completion == '':
return index, False, ''
text = completion.choices[0].message.content
return index, True, text
def parse_json_response(text):
"""解析JSON响应"""
try:
patterns = [
r'({.*?})',
r'```json\s*({.*?})\s*```',
r'```\s*({.*?})\s*```',
r'(\{[^{}]*"summarization"[^{}]*\})',
]
for pattern in patterns:
match = re.search(pattern, text, re.DOTALL)
if match:
json_str = match.group(1)
data = json.loads(json_str)
return data
if text.strip().startswith('{') and text.strip().endswith('}'):
data = json.loads(text.strip())
return data
except (json.JSONDecodeError, AttributeError):
return None
return None
def process_row_with_json_retry(index, row, max_api_retries=3):
"""处理单行数据,如果JSON解析失败则重新调用API"""
for attempt in range(max_api_retries):
api_index, success, text = process_row(index, row)
if not success:
print(f"第 {index} 行API调用失败,尝试 {attempt + 1}/{max_api_retries}")
if attempt < max_api_retries - 1:
time.sleep(2)
continue
else:
return index, False, '', None
parsed_data = parse_json_response(text)
if parsed_data:
return index, True, text, parsed_data
else:
print(f"第 {index} 行JSON解析失败,重新调用API (尝试 {attempt + 1}/{max_api_retries})")
if attempt < max_api_retries - 1:
time.sleep(2)
continue
print(f"第 {index} 行经过 {max_api_retries} 次API调用仍无法获得有效JSON响应")
return index, False, text if 'text' in locals() else '', None
final_output = f'{cache_dir}/{cve_name}-deepseek.csv'
if not os.path.exists(final_output):
df_result = new_df[['cve', 'commit']].copy()
df_result['answer'] = ''
df_result['summarization'] = ''
df_result['potential_addressed_vulnerability_types'] = ''
df_result['is_patch'] = ''
df_result.to_csv(final_output, index=False)
df_result = pd.read_csv(final_output)
df_result['summarization'] = df_result['summarization'].astype('string')
df_result['potential_addressed_vulnerability_types'] = df_result['potential_addressed_vulnerability_types'].astype('string')
df_result['is_patch'] = df_result['is_patch'].astype('string')
df_result['answer'] = df_result['answer'].astype('string')
df_prompt = new_df
df_combined = df_result.merge(df_prompt, on=['cve', 'commit'], how='left')
indices_to_process = []
for index, row in df_combined.iterrows():
if pd.isna(row['answer']) or row['answer'] == '':
indices_to_process.append(index)
print(f'总共有 {len(df_combined)} 行数据')
print(f'需要处理 {len(indices_to_process)} 行数据')
if len(indices_to_process) > 0:
print('开始调用DeepSeek API...', time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = [executor.submit(process_row_with_json_retry, index, df_combined.loc[index]) for index in indices_to_process]
for future in tqdm(as_completed(futures), total=len(futures), desc="Processing all data"):
index, success, text, parsed_data = future.result()
if success and parsed_data:
df_combined.at[index, 'answer'] = text
df_combined.at[index, 'summarization'] = parsed_data.get('summarization', '')
df_combined.at[index, 'potential_addressed_vulnerability_types'] = str(parsed_data.get('potential addressed vulnerability types', []))
df_combined.at[index, 'is_patch'] = parsed_data.get('is_patch', '')
elif success:
df_combined.at[index, 'answer'] = text
print(f"第 {index} 行JSON解析失败,但原始响应已保存")
else:
print(f"第 {index} 行处理完全失败")
result_cols = ['cve', 'commit', 'answer', 'summarization', 'potential_addressed_vulnerability_types', 'is_patch']
df_combined[result_cols].to_csv(final_output, index=False)
print(f'所有数据处理完成,结果已保存到: {final_output}')
result_cols = ['cve', 'commit', 'answer', 'summarization', 'potential_addressed_vulnerability_types', 'is_patch']
return df_combined[result_cols]
if __name__ == "__main__":
cve_name = "CVE-2018-6596"
result_df = generate_deepseek_analysis(cve_name)
print("分析完成!")