Skip to content

Results of the Facebook Infer static analysis tool #111

@TomasBeranek

Description

@TomasBeranek

Hello, within the Arrowhead Project we applied the Facebook Infer static analyzer to the core-cpp project. Infer produced over 500 issues (note that Infer produces a large number of false reports). Due to a large number of reported issues, we have checked only reported NULL dereferences. Some of them point to some suspicious parts of the code:

103
core-cpp/inc/sqlite3/shell.c:14500: error: Null Dereference
pointer 'zText' last assigned on line 14498 could be null and is dereferenced at line 14500, column 7.

    14498.   const char *zText = (const char*)sqlite3_value_text(argv[0]);
    14499.   UNUSED_PARAMETER(argc);
    14500.   if( zText[0]=='\'' ){
                 ^
    14501.     int nText = sqlite3_value_bytes(argv[0]);
    14502.     int i;

The sqlite3ValueText function can return NULL, but in the shellEscapeCrnl
function, there is no check for it. In this context, I was not able to prove that
the NULL DEREFERENCE may happen, but it is a generally good practice to check
the returned value if the function can return NULL.

329
core-cpp/inc/sqlite3/sqlite3.c:102113: error: Null Dereference
pointer 'pExpr' last assigned on line 102109 could be null and is dereferenced at line 102113, column 10.

    102111.   assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0
    102112.        || sqlite3StrICmp(pExpr->u.zToken,"false")==0 );
    102113.   return pExpr->u.zToken[4]==0;
                     ^
    102114. }
    102115.

The sqlite3ExprSkipCollate function can return NULL, because it contains while
loop, which can break when pExpr == NULL, this value is then immediately returned.
In the sqlite3ExprTruthValue function, the returned value is not checked for NULL.
Again, I was not able to prove that the NULL DEREFERENCE can happen (see 103).

380
core-cpp/inc/sqlite3/sqlite3.c:116098: error: Null Dereference
pointer 'pColl2' last assigned on line 116097 could be null and is dereferenced at line 116098, column 9.

    116096.   for(i=0; i<3; i++){
    116097.     pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, 0);
    116098.     if( pColl2->xCmp!=0 ){
                    ^
    116099.       memcpy(pColl, pColl2, sizeof(CollSeq));
    116100.       pColl->xDel = 0;         /* Do not copy the destructor */

The NULL DEREFERENCE can happen if the sqlite3HashFind function can return NULL.
Since in the findCollSeqEntry function, there is a check for it, I assume that it
is possible. Moreover, one level above in the call tree there is another check for
NULL --> if the returned value is not NULL then some offset is added. Again,
I was not able to prove that the NULL DEREFERENCE can happen (see 103).

417
core-cpp/inc/sqlite3/sqlite3.c:122594: error: Null Dereference
pointer 'pPk' last assigned on line 122593 could be null and is dereferenced at line 122594, column 16.

    122592.   }else{
    122593.     pPk = sqlite3PrimaryKeyIndex(pTab);
    122594.     nPkField = pPk->nKeyCol;
                           ^
    122595.   }
    122596.

The NULL DEREFERENCE can happen if the sqlite3PrimaryKeyIndex function can return
NULL. It is possible because:

	Index *p;
	for(p=pTab->pIndex; p && !IsPrimaryKeyIndex(p); p=p->pNext){}
	return p;

The loop can end when p == NULL and the NULL value is then returned. Again,
I was not able to prove that the NULL DEREFERENCE can happen (see 103).

492
core-cpp/inc/sqlite3/sqlite3.c:139683: error: Null Dereference
pointer 'pPk' last assigned on line 139682 could be null and is dereferenced at line 139683, column 17.

    139681.     }else{
    139682.       Index *pPk = sqlite3PrimaryKeyIndex(pTab);
    139683.       int nPk = pPk->nKeyCol;
                            ^
    139684.       int iPk = pParse->nMem+1;
    139685.       pParse->nMem += nPk;

Same as 417.

506
core-cpp/inc/sqlite3/sqlite3.c:142499: error: Null Dereference
pointer 'pNew' last assigned on line 142497 could be null and is dereferenced at line 142499, column 26.

    142497.   pNew = sqlite3ExprDup(db, pX, 0);
    142498.   if( db->mallocFailed==0 ){
    142499.     ExprList *pOrigRhs = pNew->x.pSelect->pEList;  /* Original unmodified RHS */
                                     ^
    142500.     ExprList *pOrigLhs = pNew->pLeft->x.pList;     /* Original unmodified LHS */
    142501.     ExprList *pRhs = 0;         /* New RHS after modifications */

The NULL DEREFERENCE can happen if the sqlite3ExprDup function can return NULL.
It is possible because:

	return p ? exprDup(db, p, flags, 0) : 0;

Again, I was not able to prove that the NULL DEREFERENCE can happen (see 103).

512
core-cpp/inc/sqlite3/sqlite3.c:144771: error: Null Dereference
pointer 'pRight' last assigned on line 144770 could be null and is dereferenced at line 144771, column 8.

    144769.
    144770.   pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr);
    144771.   op = pRight->op;
                   ^
    144772.   if( op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){
    144773.     Vdbe *pReprepare = pParse->pReprepare;

Same as 329.

If you are interested, I can also provide the rest of the reported issues or a more detailed description produced by Infer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions