"Fossies" - the Fresh Open Source Software Archive

Member "cppcheck-1.89/lib/check64bit.cpp" (1 Sep 2019, 7300 Bytes) of package /windows/misc/cppcheck-1.89.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "check64bit.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.84_vs_1.85.

    1 /*
    2  * Cppcheck - A tool for static C/C++ code analysis
    3  * Copyright (C) 2007-2018 Cppcheck team.
    4  *
    5  * This program is free software: you can redistribute it and/or modify
    6  * it under the terms of the GNU General Public License as published by
    7  * the Free Software Foundation, either version 3 of the License, or
    8  * (at your option) any later version.
    9  *
   10  * This program is distributed in the hope that it will be useful,
   11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13  * GNU General Public License for more details.
   14  *
   15  * You should have received a copy of the GNU General Public License
   16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   17  */
   18 
   19 //---------------------------------------------------------------------------
   20 // 64-bit portability
   21 //---------------------------------------------------------------------------
   22 
   23 #include "check64bit.h"
   24 
   25 #include "errorlogger.h"
   26 #include "settings.h"
   27 #include "symboldatabase.h"
   28 #include "token.h"
   29 #include "tokenize.h"
   30 
   31 #include <cstddef>
   32 
   33 //---------------------------------------------------------------------------
   34 
   35 // CWE ids used
   36 static const struct CWE CWE398(398U);   // Indicator of Poor Code Quality
   37 static const struct CWE CWE758(758U);   // Reliance on Undefined, Unspecified, or Implementation-Defined Behavior
   38 
   39 // Register this check class (by creating a static instance of it)
   40 namespace {
   41     Check64BitPortability instance;
   42 }
   43 
   44 void Check64BitPortability::pointerassignment()
   45 {
   46     if (!mSettings->isEnabled(Settings::PORTABILITY))
   47         return;
   48 
   49     const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
   50 
   51     // Check return values
   52     for (const Scope * scope : symbolDatabase->functionScopes) {
   53         if (scope->function == nullptr || !scope->function->hasBody()) // We only look for functions with a body
   54             continue;
   55 
   56         bool retPointer = false;
   57         if (scope->function->token->strAt(-1) == "*") // Function returns a pointer
   58             retPointer = true;
   59         else if (Token::Match(scope->function->token->previous(), "int|long|DWORD")) // Function returns an integer
   60             ;
   61         else
   62             continue;
   63 
   64         for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
   65             // skip nested functions
   66             if (tok->str() == "{") {
   67                 if (tok->scope()->type == Scope::ScopeType::eFunction || tok->scope()->type == Scope::ScopeType::eLambda)
   68                     tok = tok->link();
   69             }
   70 
   71             if (tok->str() != "return")
   72                 continue;
   73 
   74             if (!tok->astOperand1() || tok->astOperand1()->isNumber())
   75                 continue;
   76 
   77             const ValueType * const returnType = tok->astOperand1()->valueType();
   78             if (!returnType)
   79                 continue;
   80 
   81             if (retPointer && !returnType->typeScope && returnType->pointer == 0U)
   82                 returnIntegerError(tok);
   83 
   84             if (!retPointer && returnType->pointer >= 1U)
   85                 returnPointerError(tok);
   86         }
   87     }
   88 
   89     // Check assignments
   90     for (const Scope * scope : symbolDatabase->functionScopes) {
   91         for (const Token *tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) {
   92             if (tok->str() != "=")
   93                 continue;
   94 
   95             const ValueType *lhstype = tok->astOperand1() ? tok->astOperand1()->valueType() : nullptr;
   96             const ValueType *rhstype = tok->astOperand2() ? tok->astOperand2()->valueType() : nullptr;
   97             if (!lhstype || !rhstype)
   98                 continue;
   99 
  100             // Assign integer to pointer..
  101             if (lhstype->pointer >= 1U &&
  102                 !tok->astOperand2()->isNumber() &&
  103                 rhstype->pointer == 0U &&
  104                 rhstype->originalTypeName.empty() &&
  105                 rhstype->type == ValueType::Type::INT)
  106                 assignmentIntegerToAddressError(tok);
  107 
  108             // Assign pointer to integer..
  109             if (rhstype->pointer >= 1U &&
  110                 lhstype->pointer == 0U &&
  111                 lhstype->originalTypeName.empty() &&
  112                 lhstype->isIntegral() &&
  113                 lhstype->type >= ValueType::Type::CHAR &&
  114                 lhstype->type <= ValueType::Type::INT)
  115                 assignmentAddressToIntegerError(tok);
  116         }
  117     }
  118 }
  119 
  120 void Check64BitPortability::assignmentAddressToIntegerError(const Token *tok)
  121 {
  122     reportError(tok, Severity::portability,
  123                 "AssignmentAddressToInteger",
  124                 "Assigning a pointer to an integer is not portable.\n"
  125                 "Assigning a pointer to an integer (int/long/etc) is not portable across different platforms and "
  126                 "compilers. For example in 32-bit Windows and linux they are same width, but in 64-bit Windows and linux "
  127                 "they are of different width. In worst case you end up assigning 64-bit address to 32-bit integer. The safe "
  128                 "way is to store addresses only in pointer types (or typedefs like uintptr_t).", CWE758, false);
  129 }
  130 
  131 void Check64BitPortability::assignmentIntegerToAddressError(const Token *tok)
  132 {
  133     reportError(tok, Severity::portability,
  134                 "AssignmentIntegerToAddress",
  135                 "Assigning an integer to a pointer is not portable.\n"
  136                 "Assigning an integer (int/long/etc) to a pointer is not portable across different platforms and "
  137                 "compilers. For example in 32-bit Windows and linux they are same width, but in 64-bit Windows and linux "
  138                 "they are of different width. In worst case you end up assigning 64-bit integer to 32-bit pointer. The safe "
  139                 "way is to store addresses only in pointer types (or typedefs like uintptr_t).", CWE758, false);
  140 }
  141 
  142 void Check64BitPortability::returnPointerError(const Token *tok)
  143 {
  144     reportError(tok, Severity::portability,
  145                 "CastAddressToIntegerAtReturn",
  146                 "Returning an address value in a function with integer return type is not portable.\n"
  147                 "Returning an address value in a function with integer (int/long/etc) return type is not portable across "
  148                 "different platforms and compilers. For example in 32-bit Windows and Linux they are same width, but in "
  149                 "64-bit Windows and Linux they are of different width. In worst case you end up casting 64-bit address down "
  150                 "to 32-bit integer. The safe way is to always return an integer.", CWE758, false);
  151 }
  152 
  153 void Check64BitPortability::returnIntegerError(const Token *tok)
  154 {
  155     reportError(tok, Severity::portability,
  156                 "CastIntegerToAddressAtReturn",
  157                 "Returning an integer in a function with pointer return type is not portable.\n"
  158                 "Returning an integer (int/long/etc) in a function with pointer return type is not portable across different "
  159                 "platforms and compilers. For example in 32-bit Windows and Linux they are same width, but in 64-bit Windows "
  160                 "and Linux they are of different width. In worst case you end up casting 64-bit integer down to 32-bit pointer. "
  161                 "The safe way is to always return a pointer.", CWE758, false);
  162 }