Given the example code below:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int name;
} type4;
typedef struct {
int name;
type4 *p4;
} type3;
typedef struct {
int name;
type3 *p3;
} type2;
typedef struct {
int name;
type2* p2;
} type1;
int main(void){
type1 *p1 = malloc(sizeof(type1));
p1->p2 = malloc(sizeof(type2));
p1->p2->p3 = malloc(sizeof(type3));
p1->p2->p3->p4 = malloc(sizeof(type4));
printf("p4: %dn", p1->p2->p3->p4->name);
free(p1->p2->p3->p4);
free(p1->p2->p3);
free(p1->p2);
free(p1);
return 0;
}
I want to write a CodeQL script to make sure:
- before
p1->p2
, the nullness ofp1
is checked, i.e.,if(p1) { p1->p2; }
- before
p1->p2->p3
, the nullness ofp1->p2
is checked, i.e.,if(p1->p2){ p1->p2->p3; }
- …
Before TaintTracking and everything, I need to first find a way to express p1
, p1->p2
, p1->p2->p3
, …, but I just couldn’t.
Here is my attempt:
/**
* @id pointers-test
* @kind problem
* @problem.severity warning
*/
import cpp
class StartOfPointerFieldAccess extends Variable {
StartOfPointerFieldAccess(){
exists(PointerFieldAccess pfa, LocalVariable v|
v.getType() instanceof PointerType
and pfa.getQualifier+().(VariableAccess).getTarget() = v
and this = v
)
}
}
from PointerFieldAccess pfa, StartOfPointerFieldAccess pv
where pfa.getQualifier+().(VariableAccess).getTarget() = pv
select pfa, "Interesting Pointer Field Access."
The issue is that my script only returns individual fields (p1
, p2
, p3
, …), instead of the entire chain (such as p1->p2->p3
), while concat
doesn’t support complex types (such as PointerFieldAccess), so I couldn’t combine my results either.
P.S. the C source and the QL script are tested and usable.
pitboy1o1 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
1