Skip to content

Commit

Permalink
release
Browse files Browse the repository at this point in the history
  • Loading branch information
insuyun committed Aug 25, 2016
0 parents commit c28ecf4
Show file tree
Hide file tree
Showing 27,364 changed files with 4,475,109 additions and 0 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
31 changes: 31 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/fs.img
/bin/llvm/
/private/

*~
*.as
*#
*.cmake
*.def
tags
Release+Asserts

# for testing
test-as/Makefile

# auto-generated
*.llvm*
*.config
*.cfg
*.log
*.status
*.spec
*.bak


llvm/include/llvm/Config/config.h
llvm/include/llvm/Config/llvm-config.h
llvm/include/llvm/Support/DataTypes.h

# tmp directory
tmp
60 changes: 60 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
APISan: Sanitizing API Usages through Semantic Cross-Checking
=============================================================

Environments
------------
- Tested in Ubuntu 14.04
- Setup
```sh
$ ./setup.sh
```
- How to build symbolic database
```sh
$ apisan build [cmds]
```
- Run './configure'
```sh
$ apisan build ./configure
$ apisan build make
```
- How to run a checker
```sh
$ apisan check --db=[db] --checker=[checker]
```
- Example
```sh
$ cd test/return-value
$ ../../apisan build make
$ ../../apisan check --checker=rvchk
```

Checkers (under analyzer/apisan/check)
--------------------------------------
- Return value checker: retval.py
- Argument checker: argument.py
- Causality checker: causality.py
- Condition checker: condition.py
- Integer overflow checker: intovfl.py
- Format string bug checker: fsb.py

Authors
-------
- Insu Yun <insu@gatech.edu>
- Changwoo Min <changwoo@gatech.edu>
- Xujie Si <six@gatech.edu>
- Yeongjin Jang <yeongjin.jang@gatech.edu>
- Taesoo Kim <taesoo@gatech.edu>
- Mayur Naik <naik@cc.gatech.edu>

Publications
------------
```
@inproceedings{yun:apisan,
title = {{APISan: Sanitizing API Usages through Semantic Cross-checking}},
author = {Insu Yun and Changwoo Min and Xujie Si and Yeongjin Jang and Taesoo Kim and Mayur Naik},
booktitle = {Proceedings of the 25th USENIX Security Symposium (Security)},
month = aug,
year = 2016,
address = {Austin, TX},
}
```
2 changes: 2 additions & 0 deletions analyzer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
parser.out
parsetab.py
Empty file added analyzer/apisan/__init__.py
Empty file.
17 changes: 17 additions & 0 deletions analyzer/apisan/check/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from apisan.parse.explorer import Explorer
from apisan.check.argument import ArgChecker
from apisan.check.causality import CausalityChecker
from apisan.check.condition import CondChecker
from apisan.check.echo import EchoChecker
from apisan.check.fsb import FSBChecker
from apisan.check.intovfl import IntOvflChecker
from apisan.check.retval import RetValChecker

CHECKERS = {
"rvchk": RetValChecker,
"cpair": CausalityChecker,
"cond": CondChecker,
"fsb": FSBChecker,
"args": ArgChecker,
"intovfl": IntOvflChecker
}
70 changes: 70 additions & 0 deletions analyzer/apisan/check/argument.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env python3
from .checker import Checker, Context, BugReport
from ..parse.explorer import is_call
from ..lib import config
from ..parse.symbol import CallSymbol, IDSymbol

def extract_nodes(arg):
s = set()
stack = [arg]
while stack:
arg = stack.pop()
for child in arg.children:
stack.append(child)
if isinstance(arg, IDSymbol):
s.add(arg)
return s

def check_related(arg1, arg2):
if not (isinstance(arg1, CallSymbol) or
isinstance(arg2, CallSymbol)):
return False

nodes1 = extract_nodes(arg1)
nodes2 = extract_nodes(arg2)
return bool(nodes1 & nodes2)

class ArgContext(Context):
def get_bugs(self):
added = set()
bugs = []
for key, value in self.ctx_uses.items():
total = self.total_uses[key]
related = len(value[True])
score = related / len(total)
codes = value[False]
if score >= config.THRESHOLD and score != 1:
for bug in codes:
br = BugReport(score, bug, key, False)
added.add(bug)
bugs.append(br)
return bugs

class ArgChecker(Checker):
def _initialize_process(self):
self.context = ArgContext()

def _process_path(self, path):
for i, node in enumerate(path):
if is_call(node):
call = node.event.call
code = node.event.code
for i, arg1 in enumerate(call.args):
for j in range(i + 1, len(call.args)):
arg2 = call.args[j]
related = check_related(arg1, arg2)
self.context.add((call.name, i, j), related, code)

def _finalize_process(self):
return self.context

def merge(self, ctxs):
if not ctxs:
return None
ctx = ctxs[0]
for i in range(1, len(ctxs)):
ctx.merge(ctxs[i])
return self.rank(ctx.get_bugs())

def rank(self, reports):
return sorted(reports, key=lambda k: k.score, reverse=True)
82 changes: 82 additions & 0 deletions analyzer/apisan/check/causality.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env python3
from .checker import Checker, Context
from ..lib.rank_utils import (
is_alloc, is_dealloc, is_lock, is_unlock
)
from ..parse.explorer import is_call
from ..parse.symbol import IDSymbol

class CausalityContext(Context):
def __init__(self):
super().__init__()
self.entries = {}

def add_or_intersect(self, key, values, code):
entry = (key, code)
if entry in self.entries:
self.entries[entry] &= values
else:
self.entries[entry] = values

def add_all(self):
for entry, values in self.entries.items():
key, code = entry
for value in values:
self.add(key, value, code)
self.add(key, None, code)

class CausalityChecker(Checker):
def _initialize_process(self):
self.context = CausalityContext()

def _process_path(self, path):
# get latest manager
cmgr = path[-1].cmgr
for i, node in enumerate(path):
if is_call(node):
call = node.event.call
code = node.event.code
constraint = cmgr.get(call)
# want to use as dictionary key
if constraint is not None:
constraint = tuple(constraint)

calls = set()
for j in range(i + 1, len(path)):
ff_node = path[j]
if (is_call(ff_node)
and ff_node.event.call.name != call.name):
calls.add(ff_node.event.call.name)
self.context.add_or_intersect((call.name, constraint), calls, code)

def _finalize_process(self):
self.context.add_all()
return self.context

def merge(self, ctxs):
if not ctxs:
return None
ctx = ctxs[0]
for i in range(1, len(ctxs)):
ctx.merge(ctxs[i])
return self.rank(ctx.get_bugs())

def rank(self, reports):
for report in reports:
func = report.key[0]
if not isinstance(func, IDSymbol):
continue
ctx = report.ctx
if not isinstance(ctx, IDSymbol):
continue

func_name = func.id
ctx_name = ctx.id

if is_alloc(func_name) and is_dealloc(ctx_name):
report.score += 0.5
elif is_lock(func_name) and is_unlock(ctx_name):
report.score += 0.5
elif is_dealloc(ctx_name):
report.score += 0.3
return sorted(reports, key=lambda k: k.score, reverse=True)
85 changes: 85 additions & 0 deletions analyzer/apisan/check/checker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/usr/bin/env python3
from ..parse.explorer import is_eop
from ..lib import config
from ..lib.store import Store

class BugReport():
def __init__(self, score, code, key, ctx):
self.key = key
self.ctx = ctx
self.score = score
self.code = code

def __repr__(self):
return "BugReport(score=%.02f, code=%s, key=%s, ctx=%s" % (
self.score, self.code, self.key, self.ctx
)

class Context():
def __init__(self):
self.total_uses = Store(level=1)
self.ctx_uses = Store(level=2)

def add(self, key, value, code):
if value is not None:
self.ctx_uses[key][value].add(code)
self.total_uses[key].add(code)

def merge(self, other):
self.total_uses.merge(other.total_uses)
self.ctx_uses.merge(other.ctx_uses)

def get_bugs(self):
added = set()
bugs = []
for key, value in self.ctx_uses.items():
total = self.total_uses[key]
for ctx, codes in value.items():
score = len(codes) / len(total)
if score >= config.THRESHOLD and score != 1:
diff = total - codes
for bug in diff:
br = BugReport(score, bug, key, ctx)
added.add(bug)
bugs.append(br)
return bugs

class Checker(object):
def _initialize_process(self):
# optional
pass

def _finalize_process(self):
raise NotImplementedError

def _process_path(self, path):
raise NotImplementedError

def process(self, tree):
self._initialize_process()
self._do_dfs(tree)
return self._finalize_process()

def _do_dfs(self, tree):
count = 0
indices = [0]
nodes = [tree.root]

while nodes:
index = indices.pop()
node = nodes.pop()
if is_eop(node):
nodes.append(node)
# delayed visiting for truncated paths
self._process_path(nodes)
nodes.pop()
count += 1
else:
if len(node.children) > index:
indices.append(index + 1)
nodes.append(node)

child = node.children[index]
child.visited = False
indices.append(0)
nodes.append(child)
45 changes: 45 additions & 0 deletions analyzer/apisan/check/condition.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env python3
from .checker import Checker, Context
from ..lib import utils, rank_utils
from ..lib.rank_utils import (
is_alloc, is_dealloc, is_lock, is_unlock
)
from ..parse.explorer import is_call
from ..parse.symbol import IDSymbol

class CondChecker(Checker):
def _initialize_process(self):
self.context = Context()

def _process_path(self, path):
# get latest manager
cmgr = path[-1].cmgr
for i, node in enumerate(path):
if is_call(node):
call = node.event.call
code = node.event.code
cstr = cmgr.get(call, True)
# want to use as dictionary key
constraints = set()
for j in range(0, len(path)):
if i == j: # skip myself
continue
ff_node = path[j]
if is_call(ff_node):
ff_call = ff_node.event.call
other_cstr = cmgr.get(ff_call, True)
self.context.add((call.name, cstr), (ff_call.name, other_cstr), code)

def _finalize_process(self):
return self.context

def merge(self, ctxs):
if not ctxs:
return None
ctx = ctxs[0]
for i in range(1, len(ctxs)):
ctx.merge(ctxs[i])
return self.rank(ctx.get_bugs())

def rank(self, reports):
return sorted(reports, key=lambda k:k.score, reverse=True)
Loading

0 comments on commit c28ecf4

Please sign in to comment.