Runtime Monitoring of C Programs for Security and Correctness Suan Hsi Yong

advertisement
Runtime Monitoring
of C Programs
for Security and Correctness
Suan Hsi Yong
University of Wisconsin – Madison
Ph.D. Committee: Susan Horwitz (advisor),
Thomas Reps, Charles Fischer,
Somesh Jha, James Smith
_1
Errors in Software
• Software errors are undesirable
– may produce incorrect results
– may crash system
– may corrupt data
– may be vulnerable to attack
• Software errors are difficult to detect
– may be infrequently exercised
– may not noticeably alter observable output
_2
Memory and Type Safety
• Memory safety: each dereference can
only access ‘intended target’
– spatial access errors
(e.g., out-of-bounds array access)
– temporal access errors
(e.g., stale pointer dereference)
• Type safety: operations can only be
applied to values of certain types
_3
Memory and Type Safety
• Useful for improving quality of software
• Tradeoff between efficiency and flexibility
– If too general, incurs a high runtime
overhead to enforce
– If too restrictive, limits expressiveness and
utility of language
• C language mandates but does not
enforce memory and type safety
– programmer’s responsibility, error prone
_4
Approaches for Finding Errors
• Static Approaches
– imprecise, not scalable
• Dynamic Approaches
– incomplete coverage, high runtime overhead
• This thesis: Dynamic approach, but use
static analysis to improve overhead
– for testing/debugging, and for use in
deployed software
_5
This Thesis Explores…
• Runtime checking of memory and type
safety in C programs
• Three manifestations
– Memory-Safety Enforcer (MSE): detects
invalid dereferences
– Sensitive Location Checker (SLC): detects
invalid writes to security-sensitive locations
– Runtime Type Checker (RTC): detects bugs
manifested as type errors
_6
Common Features
• Tagged memory
– each byte of memory is tagged at runtime
with information used to detect errors
• Source-level instrumentation
– approach is portable, compatible with
uninstrumented libraries
• Static analysis
– identifies and eliminates unnecessary
instrumentation
_7
Architecture
C
source
file
Instrumenter
instrumented
C source
file
runtime
system/
libraries
C
Compiler
Static
Analysis
classifications
instrumented
executable
_8
Outline
• Introduction
• Memory-Safety Enforcer (MSE)
• Sensitive-Location Checker (SLC)
• Runtime Type Checker (RTC)
• Related Work
• Conclusion
_9
Memory Safety
p = &a
p’s valid target is a
*(p+i)
valid only if it accesses a
• Spatial access error: out of bounds
– e.g., if i is negative or is too large
• Temporal access error: stale pointer
– e.g., if a had been freed prior to *(p+i)
10
_
Memory Safety Enforcer (MSE)
• Debugging Tool
– invalid access  programming error
– e.g., buffer overrun, stale pointer dereference
• Security Tool
– most attacks require invalid write to succeed
(e.g., stack smashing attacks)
– halt execution when violation detected
11
_
Control Transfer Attacks
• Idea: overwrite sensitive location with
address of malicious code
• Sensitive locations include
– return address (stack smashing)
– global offset table
– function pointers
– longjmp buffer
– exec call argument
– others…
12
_
Stack Smashing
char buf[12];
char *p = &buf[0];
do {
*p = getchar();
} while(*p++ != ‘\0’);
p
buf
return address
13
_
Detecting Invalid Access
• Fat Pointer
– Record information about what each
pointer should point to
– Safe-C, CCured, Cyclone
• Tagged Memory (our approach)
– Record information about which locations
may be valid targets of some pointer
dereference
– also used by Purify
14
_
Fat Pointers
• associate information with pointer:
p
address and size of referent
char buf[12];
char *p = &buf[0];
do {
*p = getchar();
} while(*p++ != ‘\0’);
buf
12

buf

return address
15
_
Tagged Memory
• associates information with
target rather than pointer
char buf[12];
char *p = &buf[0];
do {
*p = getchar();
} while(*p++ != ‘\0’);
p


return address
 = valid target of unsafe dereference
buf












































16
_
Fat Pointer vs. Tagged Memory
• Fat Pointers
+ Guaranteed to catch all spatial errors
– Difficult to catch temporal errors efficiently
• e.g., CCured uses garbage collection
• Tagged Memory
+ Can detect both spatial and temporal errors
efficiently
– Guaranteed only to catch invalid accesses to
non-user memory
• But can improve with static analysis
17
_
Improving MSE
• Which dereferences to check?
– if static analysis can guarantee that *p is always
valid, then *p need not be instrumented.
– classify dereferences into checked/unchecked
• Which locations to tag valid at runtime?
– if x can only be accessed directly or via
unchecked dereference, then x need not be
tagged valid
– classify locations into tracked/untracked
18
_












































Checked Derefs/Tracked Locs
• naively: all dereferences are checked;
all user-defined locations are tracked
char buf[12];
char *p = &buf[0];
do {
*p = getchar();
} while(*p++ != ‘\0’);
p
buf


return address
19
_





























 
 













Checked Derefs/Tracked Locs
FN_PTR fp = &foo;
char buf[12];
char *p = &buf[0];
do {
*p = getchar();
} while(*p++ != ‘\0’);
(*fp)();
• Static Analysis: identify fewer
checked derefs and tracked locations
p
buf


fp
20
_
Checked Dereferences
• Writes Only vs. Read/Write
– write-only checks catches most attacks;
significantly improving overhead
• Flow-insensitive analysis:
a[i]  *(a+i)
– *p is checked if:
• p is assigned a non-pointer value, or
• p is the result of pointer arithmetic, or
• p may point to stack or freed heap location
21
_
Example: Checked Dereferences
FN_PTR fp = &foo;
char buf[12];
char *p = &buf[0];
do {
*p = getchar();
} while(*p++ != ‘\0’);
(*fp)();
dereferences:
*p checked
*fp unchecked
22
_
Tracked Locations
• locations that may be validly accessed via
checked dereference
• fewer tracked locations means better
performance and coverage
– less overhead to mark and clear valid tag
– increase likelihood of catching invalid access
• identify with points-to analysis [Das’00]
– for each checked dereference *p,
all locations in p’s points-to set are tracked
23
_
Example: Tracked Locations
FN_PTR fp = &foo;
char buf[12];
char *p = &buf[0];
do {
*p = getchar();
} while(*p++ != ‘\0’);
(*fp)();
points-to
locations:
dereferences:
graph:
p untracked
p
fp
*p unsafe
fp untracked
*fp safe
buf foo
buf tracked
24
_












































Example: Tracked Locations
FN_PTR fp = &foo;
char buf[12];
p
char *p = &buf[0];
buf
do {

*p = getchar();
} while(*p++ != ‘\0’);

(*fp)();
fp
points-to
locations:
dereferences:
graph:
p untracked
p
fp
*p unsafe
fp untracked
*fp safe
buf foo
buf tracked
25
_
Summary of MSE Coverage
MSE
Unoptimized
MSE + Static
Analysis
Return
address
yes
yes
Function
pointer
no
likely
exec
argument
no
maybe
Attack target
26
_
Evaluation: Runtime Overhead
27
_
Flow-Sensitive Analyses
• Redundant Checks Analysis
*(p+i) = ...;
*(p+i) = ...;
//- don’t instrument
• Pointer Range Analysis
– track range of possible values for each pointer
*p = ...;
p  a:char[10], [3,7]
– if *p is definitely in-bounds, don’t instrument
28
_
Flow-Sensitive Analyses
29
_
Flow-Sensitive Analyses
30
_
Analysis Time Slowdown
31
_
MSE Static Analysis Summary
• Unoptimized MSE
– high runtime overhead
– only catches invalid access to non-user memory
• Flow-insensitive (Extended Points-To Analysis)
– low runtime overhead, scalable analysis
• Flow-sensitive Analyses
– 20% improvement, but analysis not scalable
• Write-only faster than read-write checking
32
_
Comparison with Other Tools
(runtime overhead)
33
_
Summary of MSE
• Tool for detecting invalid pointer
dereferences that
+ has low runtime overhead
+ does not report false positives
+ is portable, and does not require
programmer changes to source code
+ protects against a wide range of
vulnerabilities, including stack smashing
and erroneous free
34
_
Outline
• Introduction
• Memory-Safety Enforcer (MSE)
• Sensitive-Location Checker (SLC)
• Runtime Type Checker (RTC)
• Related Work
• Conclusion
35
_
Two Approaches to Security
• MSE: Try to detect all invalid accesses
– including invalid accesses that are not
vulnerable to attack
• SLC: Detect only invalid accesses to
sensitive locations
– return address, function pointers,
longjmp buffers, exec call arguments
– related work: StackGuard – protects only
return address on the activation record
36
_
SLC vs MSE: classification
MSE:
identify
unsafe
dereferences,
then compute
tracked
locations
dereferences
*p
locations
w
x
*q
y
*r
z
(points-to edges)
37
_
SLC vs MSE: classification
SLC:
identify
sensitive
locations,
then compute
unchecked
dereferences
dereferences
*p
locations
w
x
*q
y
*r
z
(points-to edges)
38
_
Example
char safe_buf[8]; not sensitive
safe
_buf
char vuln_buf[8]; sensitive
strcpy(vuln_buf, “ls”);
unchecked
gets(safe_buf); checked
system(vuln_buf);
return address
vuln
_buf



































39
_
SLC vs MSE: instrumentation
• SLC must set/clear tag of sensitive
locations, while MSE must set/clear tag
of tracked locations
– In general, much fewer sensitive locations
that tracked locations, so SLC is faster
• SLC must set/clear tag of return
address on activation record
– may slow down SLC compared to MSE
40
_
Runtime Overhead: SLC vs MSE
Average: SLC=37.7%, MSE=54.1%
41
_
SLC: The Bad News
• In some of the benchmarks (ijpeg, li, perl,
gap), over 90% of the dereferences were
not checked
– i.e., they may point to a sensitive location
– due to imprecision of points-to analysis
• could be improved with better points-to analysis
• Good news: can tell from static analysis
whether SLC will be effective for a given
program
42
_
SLC vs MSE
• Memory Safety Enforcer (MSE)
– detects invalid accesses that may not be
vulnerable to attack
– may prevent new as-yet-undiscovered
methods of attack
• Sensitive Location Checker (SLC)
– targets specific locations known (a priori) to
be vulnerable to attack
– better runtime overhead because of limited
scope
43
_
Outline
• Introduction
• Memory-Safety Enforcer (MSE)
• Sensitive-Location Checker (SLC)
• Runtime Type Checker (RTC)
• Related Work
• Conclusion
44
_
Runtime Type Checking
• Idea is to detect runtime type violations
– value of one type is used in context of
incompatible type
– Scalar types only (structs and arrays
broken down into components)
• Debugging tool, for use during
development/testing
– Higher overhead acceptable (~20x)
– Related tools: Purify, Insure++, Valgrind
45
_
Error Example 1: Union
union U {
int u1;
int *u2;
} u;
int *p;
u.u1 = 20;
// write int into u.u1
p = u.u2;
// copy int from u.u2 -- suspicious!
*p = 0;
// bad pointer deref -- error!
46
_
Example 2: Bad Pointer Access
int *intArray = (int *)
malloc(15 * sizeof(int));
int **ptrArray = (int **)
malloc(15 * sizeof(int *));
intArray
ptrArray
User memory
47
_
Example 2: Bad Pointer Access
int *i, sumEven = 0;
PURIFY
ORIGINAL
for(i = intArray; ...; i += 2)
sumEven += *i;
intArray
intArray
i
ptrArray
i
User memory
ptrArray
padding
User memory48_
Example 3: Custom Allocator
char * myMalloc(size_t size)
{
static char *myMemory, *current;
...
if(first_time){
myMemory = (char *) malloc(BLKSIZE);
}
...
return &myMemory[current += size];
}
49
_
Example 3: Custom Allocator
ORIGINAL
int *intArray = (int *)
myMalloc(10 * sizeof(int));
int **ptrArray = (int **)
myMalloc(10 * sizeof(int *));
intArray
i
User memory
myMemory
i
PURIFY
ptrArray
myMemory
User memory
50
_
Example 4: Simulated Inheritance
struct Base {
int a1;
int a2;
} base;
struct Sub {
int b1;
int b2;
char b3;
} sub;
void f(struct Base *s)
{
s->a1 = ...
s->a2 = ...
}
:
f(&base);
f(&sub);
:
51
_
Example 4: Simulated Inheritance
struct Base {
int a1;
int a2;
} base;
struct Sub {
int b1;
float f1;
int b2;
char b3;
} sub;
:
void f(struct Base *s)
{
f(&base);
s->a1 = ...
s->a2 = ...
f(&sub);
}
:
52
_
Runtime Type-Checking
• Track type of values in memory
– store in mirror of memory: 4 bits for each byte
– unalloc, uninit, integral, real, pointer, zero
• Warning when type of value assigned
does not match expected type
• Error when bad runtime type is used
53
_
Runtime Type Checking Tool
(memory) (mirror)
int k;
float f;
int *p;
k
...
unalloc
f = 2.3;
f
...
unalloc
p
...
unalloc
p = (int *)&f;
k = *p;
print_int( k );
54
_
Runtime Type Checking Tool
(memory) (mirror)
int k;
float f;
int *p;
k
...
unalloc
uninit
f = 2.3;
f
...
unalloc
p
...
unalloc
p = (int *)&f;
k = *p;
print_int( k );
instrument a declaration
55
_
Runtime Type Checking Tool
(memory) (mirror)
int k;
float f;
int *p;
k
...
unalloc
uninit
f = 2.3;
f
...
unalloc
uninit
p
...
unalloc
uninit
p = (int *)&f;
k = *p;
print_int( k );
instrument a declaration
56
_
Runtime Type Checking Tool
(memory) (mirror)
int k;
float f;
int *p;
k
...
unalloc
uninit
f = 2.3;
f
...
2.3
unalloc
uninit
float
p
...
unalloc
uninit
p = (int *)&f;
k = *p;
print_int( k );
instrument an assignment
57
_
Runtime Type Checking Tool
(memory) (mirror)
int k;
float f;
int *p;
k
...
unalloc
uninit
f = 2.3;
f
...
2.3
unalloc
uninit
float
p
... )
( &f
unalloc
pointer
uninit
p = (int *)&f;
k = *p;
print_int( k );
instrument an assignment
58
_
Runtime Type Checking Tool
(memory) (mirror)
int k;
float f;
int *p;
k
f = 2.3;
f
...
2.3
unalloc
uninit
float
OK
p
... )
( &f
p = (int *)&f;
k = *p;
...
unalloc
uninit
unalloc
pointer
uninit
print_int( k );
instrument a use (of a pointer)
59
_
Runtime Type Checking Tool
(memory) (mirror)
int k;
float f;
int *p;
k
f = 2.3;
f
...
2.3
unalloc
uninit
float
p
... )
( &f
unalloc
pointer
uninit
p = (int *)&f;
k = *p;
...
OK
unalloc
uninit
print_int( k );
instrument a pointer dereference
60
_
Runtime Type Checking Tool
(memory) (mirror)
int k;
warning!
float f;
int *p;
k
...
2.3
unalloc
uninit
float
f = 2.3;
f
...
2.3
unalloc
uninit
float
p
... )
( &f
unalloc
pointer
uninit
p = (int *)&f;
k = *p;
print_int( k );
instrument an assignment
61
_
Runtime Type Checking Tool
(memory) (mirror)
int k;
error!
float f;
int *p;
k
...
2.3
unalloc
uninit
float
f = 2.3;
f
...
2.3
unalloc
uninit
float
p
... )
( &f
unalloc
pointer
uninit
p = (int *)&f;
k = *p;
print_int( k );
instrument a use (of an int)
62
_
Runtime Type Checking
• Found errors in SPEC 95, SPEC 2000,
and Solaris utilities
• But, overhead is high
– 4x-170x slowdown, average 43.5x
• Use Static Analysis
– Flow insensitive: Type Flow Analysis
– Flow sensitive: redundant checks,
may-be-uninitialized
63
_
Type Flow Analysis
• Classify lvalue expressions into:
– safe: runtime type always equals static type
• no instrumentation needed
– type-unsafe: always in-bounds, but runtime
type may not equal static type
• must be instrumented to check runtime type
– mem-unsafe: may violate memory safety
• must be fully instrumented (including check that
dereference does not access unalloc memory)
64
_
Type Flow Analysis
• Classify locations into:
– untracked: runtime type always equals
static type
• no instrumentation needed
– tracked: runtime type always equals static type,
but may be accessed by unsafe dereference
• initialize mirror to static type, but type doesn’t change
– unsafe: may cause type-safety error at runtime
• initialize mirror to uninit; type may change at runtime
65
_
Type-Flow Analysis
• Points-to Analysis
• Build Assignment
Graph
• Compute Possible
Types
• Classify Expressions
and Locations
>
66
_
Type-Flow Analysis
• Points-to Analysis
• Build Assignment
Graph
• Compute Possible
Types
Compute points-to set
for each pointer
p
pt
{f}
• Classify Expressions
and Locations
67
_
Type-Flow Analysis
• Points-to Analysis
x
x
• Build Assignment
Graph
5.0
VALUEfloat
• Compute Possible
Types
0
VALUEinit
• Classify Expressions
and Locations
&i
int valid-ptr
VALUE
nodes
68
_
Type-Flow Analysis
• Points-to Analysis
*p
• Build Assignment
Graph
y+z
VALUEint
• Compute Possible
Types
p+i
VALUEptr
• Classify Expressions
and Locations
&i
*p
VALUEvalid-ptr
nodes
69
_
Type-Flow Analysis
x = y;
=
x
y
• Points-to Analysis
• Build Assignment
Graph
• Compute Possible
Types
• Classify Expressions
and Locations
*p = 5.0;
=
*p
VALUEfloat
x = y + z;
x
=
VALUEint
edges
70
_
Type-Flow Analysis
T = “uninitialized”
• Points-to Analysis
• Build Assignment
Graph
• Compute Possible
Types
• Classify Expressions
and Locations
valid-ptr
pointer
init
int
char
float …
| = “multiply-typed”
71
_
Type-Flow Analysis
• Points-to Analysis
• Build Assignment
Graph
• Compute Possible
Types
float
VALUEfloat
T(x)  T(y)
x
=
T(y)
y
• Classify Expressions
and Locations
72
_
Type-Flow Analysis
• Points-to Analysis
• Build Assignment
Graph
• Compute Possible
Types
• Classify Expressions
and Locations
T(*p)  T(k)
p
*p
*p
k
=
pt
y
p
{k}
pt
{k}
T(k)  T(y)
73
_
Type-Flow Analysis
• Points-to Analysis
• Build Assignment
Graph
• Compute Possible
Types
• Classify Expressions
and Locations
1. poss-type(x) 
static-type(x)
 x type-unsafe
int k;
float f = 2.3;
int *p = &f;
k = *p;
}
poss-type(k) = float
static-type(k) = int
k type-unsafe
74
_
Type-Flow Analysis
• Points-to Analysis
• Build Assignment
Graph
• Compute Possible
Types
• Classify Expressions
and Locations
1. poss-type(x) 
static-type(x)
 x type-unsafe
int k;
float f = 2.3;
int *p = &f;
k = *p;
}
poss-type(*p) = float
static-type(*p) = int
*p type-unsafe
75
_
Type-Flow Analysis
• Points-to Analysis
• Build Assignment
Graph
• Compute Possible
Types
• Classify Expressions
and Locations
2. poss-type(p) ≠ valid-ptr
 *p mem-unsafe
int *p = &k;
p = p + 1;
*p = 5;
 *p mem-unsafe
76
_
Type-Flow Analysis
• Points-to Analysis
• Build Assignment
Graph
• Compute Possible
Types
• Classify Expressions
and Locations
3.*p unsafe,
pt
p
{x}
 x tracked
int k;
float f = 2.3;
int *p = &f;
k = *p;
*p unsafe
p may-point-to f
}
f tracked
77
_
Type-Flow Analysis: Example
int k;
float f;
int *p;
f = 2.3;
p = (int *)&f;
k = *p;
print_int( k );
f
tracked
p
safe
k
*p
type-unsafe
type-unsafe
Instrumentation: w/o using type-flow analysis
78
_
Type-Flow Analysis: Example
int k;
float f;
int *p;
f = 2.3;
p = (int *)&f;
k = *p;
print_int( k );
f
tracked
p
safe
k
*p
type-unsafe
type-unsafe
Instrumentation: using type-flow analysis
79
_
RTC Runtime Overhead
80
_
Flow-sensitive Refinements
• May-be-uninitialized analysis
>
– needed to detect uses of uninitialized data
– analysis and runtime overhead both slow
• not worthwhile: better to use unoptimized
• Redundant checks analysis
– for each use of x, if error is reported, tag of x
is corrected to prevent cascading errors
y = x + 1;
z = x + 2;
//check of x is redundant
81
_
RTC Runtime Overhead
82
_
Analysis Time
83
_
Outline
• Introduction
• Memory-Safety Enforcer (MSE)
• Sensitive-Location Checker (SLC)
• Runtime Type Checker (RTC)
• Related Work
• Conclusion
84
_
Related Work
• Run-time Error Detection
– Purify, Insure++, Valgrind
– Safe C, CCured, Cyclone
– Safe languages (Java), dynamically-typed
languages (Lisp)
• Reducing Instrumentation
– Java (remove array-bounds checks)
– Lisp and Scheme (remove tag-handling
operations, e.g., Henglein)
– CCured (remove pointer checks: Necula et al)
85
_
Conclusion
• Finding errors and vulnerabilities is difficult
• Three related runtime monitoring approaches
– Sensitive location checker: efficient, security-oriented
– Memory-safety enforcer: efficient, security or debugging
– Runtime type-checker: slow, for debugging
• Effective in detecting errors
• Static analysis to improve runtime overhead
– Flow-insensitive: scalable, significant improvements
– Flow-sensitive: modest improvements, not scalable
86
_
Future Work
• Better static analysis: fewer unsafe
and tracked locations
– escape analysis / scope analysis
– better points-to analysis
• Different mechanism for tagging
– e.g. hash lookup
• Apply ideas to other languages and
environments
– e.g. absorb overhead on multiprocessor
87
_
Runtime Monitoring
of C Programs
for Security and Correctness
END
Suan Hsi Yong
University of Wisconsin – Madison
Ph.D. Committee: Susan Horwitz (advisor),
Thomas Reps, Charles Fischer,
Somesh Jha, James Smith
88
_
Index
• Start / Mem & Type Safety / Architecture
• MSE / Ctl-xfer Attack / Fat Pointers /
Classification / Flow-sensitive / Results
• SLC / Example / Results
• RTC / Union / MyMalloc / Inheritance /
Example / Type-Flow / Results
• Related / Conclusion / Future
• MSE example / CCured wild / Type-Flow
example / MBU
89
_
Example: Allocation
FN_PTR fp = &foo;
char buf[12];
char *p = &buf[0];
do {
*p = getchar();
} while(*p++ != ‘\0’);
(*fp)();
locations:
pointers:
p untracked
p unsafe
fp untracked
fp safe
buf tracked












































90
_
Example: Allocation
FN_PTR fp = &foo;
char buf[12];
char *p = &buf[0];
do {
*p = getchar();
} while(*p++ != ‘\0’);
(*fp)();
locations:
pointers:
p untracked
p unsafe
fp untracked
fp safe
buf tracked
fp












































91
_
Example: Allocation
FN_PTR fp = &foo;
char buf[12];
char *p = &buf[0];
do {
*p = getchar();
} while(*p++ != ‘\0’);
(*fp)();
locations:
pointers:
p untracked
p unsafe
fp untracked
fp safe
buf tracked
buf
fp












































92
_
Example: Allocation
FN_PTR fp = &foo;
char buf[12];
char *p = &buf[0];
do {
*p = getchar();
} while(*p++ != ‘\0’);
(*fp)();
locations:
pointers:
p untracked
p unsafe
fp untracked
fp safe
buf tracked
p
buf
fp












































93
_
Example: Checking Writes
FN_PTR fp = &foo;
char buf[12];
char *p = &buf[0];
do {
*p = getchar();
} while(*p++ != ‘\0’);
(*fp)();
locations:
pointers:
p untracked
p unsafe
fp untracked
fp safe
buf tracked

p
buf
fp












































94
_
Example: Checking Writes
FN_PTR fp = &foo;
char buf[12];
char *p = &buf[0];
do {
*p = getchar();
} while(*p++ != ‘\0’);
(*fp)();
locations:
pointers:
p untracked
p unsafe
fp untracked
fp safe
buf tracked
p
buf
fp












































95
_
Example: Checking Writes
FN_PTR fp = &foo;
char buf[12];
char *p = &buf[0];
do {
*p = getchar();
} while(*p++ != ‘\0’);
(*fp)();
locations:
pointers:
p untracked
p unsafe
fp untracked
fp safe
buf tracked
p

buf
fp












































96
_
Example: Checking Writes
FN_PTR fp = &foo;
char buf[12];
char *p = &buf[0];
do {
*p = getchar();
} while(*p++ != ‘\0’);
(*fp)();
locations:
pointers:
p untracked
p unsafe
fp untracked
fp safe
buf tracked
p
buf

fp












































97
_
Back
98
_
CCured WILD Pointers
int i;
int *p;
int *q1, *q2;
q1 = i;
q1 = (int)&p;
q2 = &i;
}
q1 WILD
=> q2 WILD
99
_
Back
100
_
Type-Flow Analysis: Example
int k;
float f;
int *p;
f = 2.3;
p = (int *)&f;
k = *p;
print_int( k );
1. Points-to analysis
p
pt
{f}
101
_
Type-Flow Analysis: Example
int k;
float f;
int *p;
f = 2.3;
p = (int *)&f;
k = *p;
print_int( k );
2. Assignment graph
=
f
=
p
=
k
p
pt
VALUEfloat
VALUEvalid-ptr
*p
{f}
102
_
Type-Flow Analysis: Example
int k;
float f;
int *p;
f = 2.3;
p = (int *)&f;
k = *p;
print_int( k );
3. Runtime types
float
f
valid-ptr
p
float
k
=
=
=
float
VALUEfloat
valid-ptr
VALUEvalid-ptr
float
*p
T(*p)  T(f)
p
pt
{f}
103
_
Type-Flow Analysis: Example
int k;
float f;
int *p;
float
tracked
f
valid-ptr
safe
p
f = 2.3;
p = (int *)&f;
k = *p;
print_int( k );
4. Type-safety levels
float
type-unsafe
k
float
type-unsafe
*p
p
pt
{f}
104
_
Back
105
_
May-be-uninitialized Analysis
106
_
May-be-uninitialized Analysis
107
_
May-be-uninitialized Analysis
108
_
Back
109
_
Download