codeql
codeql copied to clipboard
To get the expression from SwitchCase
#define ABC XVY(1)
{
int cmd = 1;
int ABC=1;
switch(cmd) {
case ABC:
printf("hello!\n);
}
}
How to get a "ABC" from a SwitchCase class? (Not a value using (SwitchCase).getExpr().getFullyConverted().getValue() )
Thanks in advance,
Hello! Thanks for reaching out with this question. Would something like this get what you're after?
from SwitchCase s, MacroInvocation m
where exists(Expr e | e = s.getExpr() and e = m.getExpr())
select s, m
@edoardopirovano , I'm using a control flow node:
result = cfn.(SwitchCase).getExpr()
cfn -> "case ...:". cfn.(SwitchCase).getExpr() -> unsigned int
Can i get the "ABC" based on the control flow node?
cfn.(SwitchCase).????? -> "ABC"
Thanks,
I see. Would something like this do what you need:
exists(Expr e | e = cfn.(SwitchCase).getExpr() and e = result.getExpr())
The result
will now be of type MacroInvocation
rather than Expr
, so other parts of your code may need changing. If you can share more of your code, I'd be happy to help out with that.
@edoardopirovano,
Even though i can get the value of case via:
cfn.(SwitchCase).getExpr().getFullyConverted().getValue()
If i can replace "Here i'd like to ..." with "cfn.???" (which returns "ABC") , it's the best. The query i'm using:
string getCase(ControlFlowNode cfn) {
cfn.getAQlClass().toString().matches("SwitchCase") and result = cfn.toString() +"Here i'd like to be the ABC" + "_" + cfn.getAQlClass()
or
result = getCase(cfn.getAPredecessor())
}
from FunctionCall fc, string where_case
where
where_case = getCase(fc.getAPredecessor())
select fc.getLocation(), fc, where_case as THE_CASE, fc.getControlFlowScope()
I see. I think fitting in the above snippet into your code gives:
string getCase(ControlFlowNode cfn) {
cfn.getAQlClass().toString().matches("SwitchCase") and exists(MacroInvocation m, Expr e | e = cfn.(SwitchCase).getExpr() and e = m.getExpr() and result = m.toString())
or
result = getCase(cfn.getAPredecessor())
}
from FunctionCall fc, string where_case
where
where_case = getCase(fc.getAPredecessor())
select fc.getLocation(), fc, where_case as THE_CASE, fc.getControlFlowScope()
Hoping that is what you need?
@edoardopirovano , The query you shared is working well.
One more question, is there any way to get the "[XXXX]" of "case [XXXX]:" regardless of type?
One more question, is there any way to get the "[XXXX]" of "case [XXXX]:" regardless of type?
Unfortunately, I think the macros do need to be handled separately with a different branch like the one we came up with above. This is because some of the pre-processing has happened already by the time the code is imported into the CodeQL database, so to CodeQL the macros look like they have already been expanded and to restore what the user actually wrote we need a distinct case that does what we did above.
@edoardopirovano,
Occasionally, the strings of conditions for switch-case provide useful clues for security analysis. It would be useful if the conditions can be obtained. For example:
// case ABCDE:
cfn.(SwitchCase).getConditions().toString()
// ABCDE expected
// case 1:
cfn.(SwitchCase).getConditions().toString()
// 1 expected
// case add(a+b):
cfn.(SwitchCase).getConditions().toString()
// add(a+b) expected
Thanks, we'll certainly consider this, but unfortunately keeping all the raw strings as they appeared in the source code will probably be fairly prohibitive in terms of how much information would have to end up in the CodeQL database. I'll note we also have MacroInvocation.getUnexpandedArgument
which could help in your use case.
Out of interest, what are you hoping to achieve that requires the raw strings of the conditions? I would've thought for most analysis, the final expression after macro expansion is what you would want since that is what the compiler actually uses.