75 lines
1.7 KiB
Python
75 lines
1.7 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import random
|
|
import subprocess
|
|
|
|
from runner import run_sql_parallel
|
|
from sqlite_static_helper import *
|
|
from stats import save_bug
|
|
|
|
|
|
def is_crash(rc: int, _stderr: str) -> bool:
|
|
|
|
# https://tldp.org/LDP/abs/html/exitcodes.html
|
|
if rc > 128 and rc != 130:
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def is_unexpected_error(b_rc, _b_err, r_rc, _r_err, _sql):
|
|
if b_rc != 0 and r_rc == 0:
|
|
return True
|
|
return False
|
|
|
|
|
|
def is_valid_sql(r_rc: int, _r_err: str):
|
|
if r_rc != 0:
|
|
return False
|
|
return True
|
|
|
|
|
|
def check(buggy_bin: str,
|
|
ref_bin: str,
|
|
sql: str,
|
|
with_flag: bool = False,
|
|
save_bugs: bool = True) -> int:
|
|
"""
|
|
Returns:
|
|
- `-1`: The query was not successfully executed on the reference binary, probably due to syntax issues
|
|
- `0`: The query caused a logic bug, crash, or some other unexpected error.
|
|
- `1`: The query was successfully executed on both binaries.
|
|
"""
|
|
|
|
flag = '' if not with_flag else random.choice(FLAGS)
|
|
|
|
try:
|
|
b_out, b_err, b_rc, r_out, r_err, r_rc = run_sql_parallel(
|
|
buggy_bin, ref_bin, sql, flag)
|
|
except subprocess.TimeoutExpired:
|
|
return 0
|
|
except Exception:
|
|
return -1
|
|
|
|
if not is_valid_sql(r_rc, r_err):
|
|
return -1
|
|
|
|
# # Crash Detection
|
|
if is_crash(b_rc, b_err) and not is_crash(r_rc, r_err):
|
|
if save_bugs:
|
|
save_bug(sql, 'crash', b_out, b_err, flag=flag)
|
|
return 0
|
|
|
|
# # Unexpected Error Detection
|
|
elif is_unexpected_error(b_rc, b_err, r_rc, r_err, sql):
|
|
if save_bugs:
|
|
save_bug(sql, 'unexpected_error', b_out, b_err, flag=flag)
|
|
return 0
|
|
|
|
# # Logic Bug Detection
|
|
elif b_rc == 0 and r_rc == 0 and b_out != r_out:
|
|
if save_bugs:
|
|
save_bug(sql, 'logic', b_out, b_err, r_out, flag=flag)
|
|
return 0
|
|
return 1
|