Signatures
cclyzer++ can model the behavior of external code via signatures that describe the salient features of the code that is not available for analysis. Signatures are provided as a JSON file to the fact generator. The top level of the JSON should be a list, and each entry should have the form:
{
"name": "function_name",
"signatures": [
{
"signature_name": [ signature arguments ... ]
},
...
]
}
where function_name
is a regular expression that matches the mangled
(LLVM-level) function name.
If a signature should be applied multiple times with different arguments, it should appear multiple times in the list. For example:
{
"name": "function_name",
"signatures": [
{
"pts_arg_memcpy_arg": [ 0, 1 ],
"pts_arg_memcpy_arg": [ 0, 2 ]
}
]
}
Kinds of Signatures
- pts_none: []
Used to indicate that the function has no points-to relevant behavior and that the function should not be reported as missing points-to signatures.
- pts_return_alloc: []
Allocates a new memory object with type compatible with the callsite’s return type.
- Example:
pts_return_alloc: []
int *a = example(); int *b = example();Variables
a
andb
will point to distinct allocations of typeint
.
- pts_return_alloc_once: []
The pointer returned by this function at any callsite will point to the same allocation. Can be used to model libraries which return a pointer to a static internal location.
- Example:
pts_return_alloc_once: []
int *a = example(); int *b = example();Variables
a
andb
will point to the same allocation of typeint
.
- pts_return_aliases_arg: [ <arg index> ]
The pointer returned by this function may point to any type-compatible allocation pointed to by the argument at the specified index.
- Example:
pts_return_aliases_arg: [ 1 ]
int a = 0; int b = 1; int *c = example(&a, &b);Variable
c
will point to the stack allocation for variableb
.
- pts_return_aliases_arg_reachable: [ <arg index> ]
The pointer returned by this function may point to any type-compatible allocation that is reachable in the points-to graph from the argument at the specified index.
Can be used to model functions that extract interior pointers from arguments.
- Example:
pts_return_aliases_arg: [ 1 ]
struct container { int *internal; }; int a = 0; int b = 1; struct container as = { .internal = &a }; struct container bs = { .internal = &b }; int *c = example(&as, &bs);Variable
c
will point to the stack allocation for variableb
.
- pts_return_points_to_global: [ <global name> ]
The pointer returned by this function points to the allocation corresponding to the named global (which must be defined in the program under analysis).
- Example:
pts_return_points_to_global: [ test ]
int test = 5; void main(void) { int *a = example(); }Variable
a
will point to the global allocation fortest
.
- pts_return_aliases_global: [ <global name> ]
The pointer returned by this function may point to any type-compatible allocation pointed to by the named global (which must be defined in the program under analysis).
- Example:
pts_return_aliases_global: [ testptr ]
int test = 5; int *testptr = &test; void main(void) { int *a = example(); }Variable
a
will point to the global allocation fortest
.
- pts_return_aliases_global_reachable: [ <global name> ]
The pointer returned by this function may point to any type-compatible allocation that is reachable in the points-to graph from the named global (which must be defined in the program under analysis).
- Example:
pts_return_aliases_global_reachable: [ testptr ]
struct container { int *internal; }; int test = 5; struct container teststruct = { .internal = &test }; int *testptr = &teststruct; void main(void) { int *a = example(); }Variable
a
will point to the global allocation fortest
.
- pts_arg_alloc: [ <arg index> ]
Allocates a new memory object with type compatible with the specified argument’s pointer type and updates the points-to set of the pointer.
- Example:
pts_arg_alloc: [ 1 ]
int *a = nullptr; int *b = nullptr; int *c = nullptr; int *d = nullptr; example(&a, &b); example(&c, &d);Variables
b
andd
will point to distinct allocations of typeint
. Variablesa
andc
will not point to any allocations.
- pts_arg_alloc_once: [ <arg index> ]
Any pointers pointed-to by callsite arguments at the specified index will point to the same allocation. Can be used to model libraries which assign pointers to static locations into output variables.
- Example:
pts_arg_alloc_once: [ 1 ]
int *a = nullptr; int *b = nullptr; int *c = nullptr; int *d = nullptr; example(&a, &b); example(&c, &d);Variables
b
andd
will point to the same allocation of typeint
.
- pts_arg_memcpy_arg: [ <destination arg index>, <source arg index> ]
Points-to sets will be updated as if the memory pointed to by the source argument might have been copied to the memory pointed to by the destination argument.
- Example:
pts_arg_memcpy_arg: [ 0, 1 ]
int a = 0; int b = 1; int *ap = &a; int *bp = &b; example(&ap, &bp);Variable
ap
will point to the allocations for both variablesa
andb
. The points-to set of variablebp
will be unchanged and still refer only tob
.
- pts_arg_memcpy_arg_reachable: [ <destination arg index>, <source arg index> ]
Points-to sets will be updated as if any type-compatible memory allocation reachable from the source argument might have been copied to the memory pointed to by the destination argument.
- Example:
pts_arg_memcpy_arg_reachable: [ 0, 1 ]
struct container { int *internal; }; int a = 0; int b = 1; struct container sb = {.internal = &b}; int *ap = &a; struct container *sbp = &sb; example(&ap, &sbp);Variable
ap
will point to the allocations for both variablesa
andb
. The points-to set of variablesbp
andsb.internal
will be unchanged.
- pts_arg_memcpy_global: [ <destination arg index>, <global name> ]
Points-to sets will be updated as if the named global might have been copied to the memory pointed to by the destination argument.
- Example:
pts_arg_memcpy_arg: [ 0, test_struct ]
struct container { int *internal; }; test_int = 0; struct container test_struct = {.internal = &global_int}; void main(void) { struct container a; example(&a); }Variable
a.internal
will point to the global allocationtest_int
.
- pts_arg_memcpy_global_reachable: [ <destination arg index>, <global name> ]
Points-to sets will be updated as if the named global or any data reachable from it might have been copied to the memory pointed to by the destination argument.
- Example:
pts_arg_memcpy_global_reachable: [ 0, test_struct ]
struct container { int *internal; }; test_int = 0; struct container test_struct = {.internal = &global_int}; void main(void) { int a = 0; int *ap = &a; example(&ap); }Variable
ap
will point to the global allocationtest_int
.
- pts_arg_points_to_global: [ <destination arg index>, <global name> ]
The points-to set of the pointer pointed to by the specified argument will be updated to include the allocation corresponding to the named global.
- Example:
pts_arg_points_to_global: [ 0, test_int ]
test_int = 0; void main(void) { int a = 0; int *ap = &a; example(&ap); }Variable
ap
will point to the global alocationtest_int
.
Examples
The libc function close
has no visible effect on memory. It can be
modeled as
{"name": "^close$", "signatures": [{"pts_none": []}]}
fgetc(3)
says:
char *fgets(char *s, int size, FILE *stream)
gets() and fgets() return s on success, [...]
This behavior can be modeled by the following signature:
{"name": "^fgets$", "signatures": [{"pts_return_aliases_arg": [0]}]}