From 0bb974e3eec060c1820ada60f8e9e41b827d1d6e Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Thu, 28 Jun 2018 00:42:11 +0000 Subject: [PATCH] [analyzer] Use sufficiently large types for index bounds calculation. The ProgramState::assumeInBound() API is used by checkers to make an assumption that a certain array index is within the array's bounds (i.e. is greater than or equal to 0 and is less than the length of the array). When the type of the index was unspecified by the caller, it assumed that the type is 'int', which caused some indices and sizes to truncate during calculations. Use ArrayIndexTy by default instead, which is used by the analyzer to represent index types and is currently hardcoded to long long. Patch by Bevin Hansson! Differential Revision: https://reviews.llvm.org/D46944 llvm-svn: 335803 --- .../lib/StaticAnalyzer/Core/ProgramState.cpp | 3 +-- clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 3 ++- clang/test/Analysis/index-type.c | 23 +++++++++++++++++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp index 141863d2ac8a..2b401607293b 100644 --- a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -336,9 +336,8 @@ ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx, // Get the offset: the minimum value of the array index type. BasicValueFactory &BVF = svalBuilder.getBasicValueFactory(); - // FIXME: This should be using ValueManager::ArrayindexTy...somehow. if (indexTy.isNull()) - indexTy = Ctx.IntTy; + indexTy = svalBuilder.getArrayIndexType(); nonloc::ConcreteInt Min(BVF.getMinValue(indexTy)); // Adjust the index. diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index acb6eeab8d91..db6449e6d5f3 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1341,7 +1341,8 @@ RegionStoreManager::getSizeInElements(ProgramStateRef state, // If a variable is reinterpreted as a type that doesn't fit into a larger // type evenly, round it down. // This is a signed value, since it's used in arithmetic with signed indices. - return svalBuilder.makeIntVal(RegionSize / EleSize, false); + return svalBuilder.makeIntVal(RegionSize / EleSize, + svalBuilder.getArrayIndexType()); } //===----------------------------------------------------------------------===// diff --git a/clang/test/Analysis/index-type.c b/clang/test/Analysis/index-type.c index b86913b996f6..123dcd65bd7c 100644 --- a/clang/test/Analysis/index-type.c +++ b/clang/test/Analysis/index-type.c @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.security.ArrayBoundV2 -verify %s -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,alpha.security.ArrayBoundV2 -DM32 -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.security.ArrayBoundV2 -Wno-implicit-function-declaration -verify %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,alpha.security.ArrayBoundV2 -Wno-implicit-function-declaration -DM32 -verify %s // expected-no-diagnostics #define UINT_MAX (~0u) @@ -36,4 +36,23 @@ void testIndexTooBig64() { *ptr = 42; // no-warning } +#define SIZE 4294967296 + +static unsigned size; +static void * addr; +static unsigned buf[SIZE]; + +void testOutOfBounds() { + // Not out of bounds. + buf[SIZE-1] = 1; // no-warning +} + +void testOutOfBoundsCopy1() { + memcpy(buf, addr, size); // no-warning +} + +void testOutOfBoundsCopy2() { + memcpy(addr, buf, size); // no-warning +} + #endif