[cfe-dev] [StaticAnalyzer] How to allocate SymbolRef for values passed through function parameters

Artem Dergachev via cfe-dev cfe-dev at lists.llvm.org
Tue May 23 02:07:44 PDT 2017


Yep, i don't have much to add to Alexey's answer.

Assuming the body of request() is unavailable and your checker doesn't 
try to explicitly model it via evalCall() or a body farm, concrete-0 
values of local variables fd1 and fd2 should be replaced with conjured 
symbols, and remain as such until touched by another call or assignment, 
so you *should* be able to obtain these exact symbols in release().

The analyzer might have found an execution path on which descriptors 
were never requested, but in the code you posted this is definitely not 
the case. Or they might have been accidentally overwritten with 0's 
during the "some unrelated code", which would no longer be unrelated in 
this case.

It is supposed to just work "out of the box". If it doesn't, you may 
want to share a small reproducer code.

On 5/23/17 11:43 AM, Aleksei Sidorin wrote:
> Hello Haowei,
>
> After call to request(), both values of fd1 and fd2 should become 
> symbolic. This is because its body is not available in the current 
> translation unit so the analyzer invalidates the values of argument 
> pointers. I can see this behaviour while reproducing your test - both 
> fd1 and fd2 are assigned with SymbolConjured.
> This behaviour you observe looks strange. Do you try to perform 
> evalCall() on request() function? If so, you could forgot to 
> invalidate the arguments. Could you post your checker here?
>
>
> 23.05.2017 03:21, Haowei Wu via cfe-dev пишет:
>> Hi,
>>
>> I am new to clang and I am developing a checker to detect resource 
>> leaks that is similar to the SimpleStreamChecker except that the 
>> target function is passing its return value through parameters. The 
>> example code would be like:
>>
>> int request(int * arg1, int * arg2);
>> int release(int arg1);
>> void foo() {
>>    int fd1 = 0, fd2 = 0;
>>    request(&fd1, &fd2);
>>
>>    // ..... some unrelated code
>>
>>    release(fd1);
>>    release(fd2);
>> }
>>
>>
>> Here, the integer fd1 and fd2 are resource descriptors that should be 
>> assigned with unique integer values after the "request(&fd1, &fd2)" 
>> call. The resource will be leaked if someone forgot to call 
>> "release(fd)" on a resource descriptor.
>>
>> The problem is , if I use the "Call.getArgSVal(0)" on the calls to 
>>  the "release(fd1)" or "release(fd2)"  function, I only get a 
>> "ConcreteInt" which is the value "0" that I assigned in the 
>> initializer instead of a SVal with a SymbolRef. In this case, I 
>> cannot determine if the value in "fd1" is the same value that is 
>> assigned after the call to the "request(&fd1, &fd2)".
>>
>> The original SimpleStreamChecker does not have this issue because the 
>> file descriptor (to be precise, it is FILE *) used in "FILE *F = 
>> fopen("mylog.txt", "w");" is passed through the return value instead 
>> of parameter. In this case, clang will allocate a SymbolRef for "F". 
>> And it will be the same one if I call 
>> "Call.getReturnValue().getAsSymbol()" on a "fclose(F)".
>>
>> My question is, is there anyway to allocate SymbolRef to the 
>> variables pointed by arg1 and arg2 manually in the checkPreCall for 
>> the "int request(int * arg1, int * arg2)"? So in checkPostCall for 
>> "int release(int arg1);" I can use 
>> "Call.getReturnValue().getAsSymbol()" to check if the SymbolRef of 
>> "arg1" is the same one that allocated in "int request(int * arg1, int 
>> * arg2)"?
>>
>> Thanks for any help,
>> Haowei
>>
>>
>>
>>
>>
>>
>>
>>
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>
> -- 
> Best regards,
> Aleksei Sidorin,
> SRR, Samsung Electronics




More information about the cfe-dev mailing list