Skip to content

Commit

Permalink
Merged master:5f41ca48d1c into amd-gfx:d5bbbc9d494
Browse files Browse the repository at this point in the history
Local branch amd-gfx d5bbbc9 Merged master:7bf168390fd into amd-gfx:a06e03ac400
Remote branch master 5f41ca4 [clang-tidy] More strict on matching the standard memset function in memset-usage check.
  • Loading branch information
Sw authored and Sw committed Jul 10, 2020
2 parents d5bbbc9 + 5f41ca4 commit 955d3cb
Show file tree
Hide file tree
Showing 25 changed files with 1,927 additions and 263 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,19 @@ namespace tidy {
namespace bugprone {

void SuspiciousMemsetUsageCheck::registerMatchers(MatchFinder *Finder) {
// Note: void *memset(void *buffer, int fill_char, size_t byte_count);
// Match the standard memset:
// void *memset(void *buffer, int fill_char, size_t byte_count);
auto MemsetDecl =
functionDecl(hasName("::memset"),
parameterCountIs(3),
hasParameter(0, hasType(pointerType(pointee(voidType())))),
hasParameter(1, hasType(isInteger())),
hasParameter(2, hasType(isInteger())));

// Look for memset(x, '0', z). Probably memset(x, 0, z) was intended.
Finder->addMatcher(
callExpr(
callee(functionDecl(hasName("::memset"))),
callee(MemsetDecl),
hasArgument(1, characterLiteral(equals(static_cast<unsigned>('0')))
.bind("char-zero-fill")),
unless(
Expand All @@ -36,14 +44,14 @@ void SuspiciousMemsetUsageCheck::registerMatchers(MatchFinder *Finder) {

// Look for memset with an integer literal in its fill_char argument.
// Will check if it gets truncated.
Finder->addMatcher(callExpr(callee(functionDecl(hasName("::memset"))),
Finder->addMatcher(callExpr(callee(MemsetDecl),
hasArgument(1, integerLiteral().bind("num-fill")),
unless(isInTemplateInstantiation())),
this);

// Look for memset(x, y, 0) as that is most likely an argument swap.
Finder->addMatcher(
callExpr(callee(functionDecl(hasName("::memset"))),
callExpr(callee(MemsetDecl),
unless(hasArgument(1, anyOf(characterLiteral(equals(
static_cast<unsigned>('0'))),
integerLiteral()))),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,8 @@ void foo(int xsize, int ysize) {
// despite v == 0.
memset(p, -1, v);
}

void *memset(int);
void NoCrash() {
memset(1);
}
3 changes: 3 additions & 0 deletions clang/test/SemaTemplate/stack-exhaustion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
// implementation limits, just disable the test.
// UNSUPPORTED: system-netbsd

// asan has own stack-overflow check.
// UNSUPPORTED: asan

// expected-warning@* 0-1{{stack nearly exhausted}}
// expected-note@* 0+{{}}

Expand Down
5 changes: 2 additions & 3 deletions clang/utils/analyzer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ ENV PATH="/analyzer/bin:${PATH}"

ADD entrypoint.py /entrypoint.py

# Uncomment in case of requirements
# ADD requirements.txt /requirements.txt
# RUN pip3 install -r /requirements.txt
ADD requirements.txt /requirements.txt
RUN pip3 install -r /requirements.txt

ENTRYPOINT ["python", "/entrypoint.py"]
44 changes: 26 additions & 18 deletions clang/utils/analyzer/SATest.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,27 +132,35 @@ def docker_shell(args):
pass

finally:
print("Please wait for docker to clean up")
call("docker stop satest", shell=True)
docker_cleanup()


def docker_run(args, command, docker_args=""):
return call("docker run --rm --name satest "
"-v {llvm}:/llvm-project "
"-v {build}:/build "
"-v {clang}:/analyzer "
"-v {scripts}:/scripts "
"-v {projects}:/projects "
"{docker_args} "
"satest-image:latest {command}"
.format(llvm=args.llvm_project_dir,
build=args.build_dir,
clang=args.clang_dir,
scripts=SCRIPTS_DIR,
projects=PROJECTS_DIR,
docker_args=docker_args,
command=command),
shell=True)
try:
return call("docker run --rm --name satest "
"-v {llvm}:/llvm-project "
"-v {build}:/build "
"-v {clang}:/analyzer "
"-v {scripts}:/scripts "
"-v {projects}:/projects "
"{docker_args} "
"satest-image:latest {command}"
.format(llvm=args.llvm_project_dir,
build=args.build_dir,
clang=args.clang_dir,
scripts=SCRIPTS_DIR,
projects=PROJECTS_DIR,
docker_args=docker_args,
command=command),
shell=True)

except KeyboardInterrupt:
docker_cleanup()


def docker_cleanup():
print("Please wait for docker to clean up")
call("docker stop satest", shell=True)


def main():
Expand Down
74 changes: 48 additions & 26 deletions clang/utils/analyzer/SATestBuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
variable. It should contain a comma separated list.
"""
import CmpRuns
import SATestUtils
import SATestUtils as utils
from ProjectMap import DownloadType, ProjectInfo

import glob
Expand All @@ -63,7 +63,7 @@
# and this is we can shush that false positive
from plistlib import InvalidFileException # type:ignore
from subprocess import CalledProcessError, check_call
from typing import Dict, IO, List, NamedTuple, Optional, TYPE_CHECKING
from typing import Dict, IO, List, NamedTuple, Optional, TYPE_CHECKING, Tuple


###############################################################################
Expand Down Expand Up @@ -115,7 +115,7 @@ def stdout(message: str):
if 'CC' in os.environ:
cc_candidate: Optional[str] = os.environ['CC']
else:
cc_candidate = SATestUtils.which("clang", os.environ['PATH'])
cc_candidate = utils.which("clang", os.environ['PATH'])
if not cc_candidate:
stderr("Error: cannot find 'clang' in PATH")
sys.exit(1)
Expand Down Expand Up @@ -194,9 +194,9 @@ def run_cleanup_script(directory: str, build_log_file: IO):
cwd = os.path.join(directory, PATCHED_SOURCE_DIR_NAME)
script_path = os.path.join(directory, CLEANUP_SCRIPT)

SATestUtils.run_script(script_path, build_log_file, cwd,
out=LOCAL.stdout, err=LOCAL.stderr,
verbose=VERBOSE)
utils.run_script(script_path, build_log_file, cwd,
out=LOCAL.stdout, err=LOCAL.stderr,
verbose=VERBOSE)


class TestInfo(NamedTuple):
Expand Down Expand Up @@ -351,8 +351,6 @@ def get_output_dir(self) -> str:
return OUTPUT_DIR_NAME

def build(self, directory: str, output_dir: str):
time_start = time.time()

build_log_path = get_build_log_path(output_dir)

stdout(f"Log file: {build_log_path}\n")
Expand All @@ -375,19 +373,23 @@ def build(self, directory: str, output_dir: str):
if self.project.mode == 1:
self._download_and_patch(directory, build_log_file)
run_cleanup_script(directory, build_log_file)
self.scan_build(directory, output_dir, build_log_file)
build_time, memory = self.scan_build(directory, output_dir,
build_log_file)
else:
self.analyze_preprocessed(directory, output_dir)
build_time, memory = self.analyze_preprocessed(directory,
output_dir)

if self.is_reference_build:
run_cleanup_script(directory, build_log_file)
normalize_reference_results(directory, output_dir,
self.project.mode)

stdout(f"Build complete (time: {time.time() - time_start:.2f}). "
stdout(f"Build complete (time: {utils.time_to_str(build_time)}, "
f"peak memory: {utils.memory_to_str(memory)}). "
f"See the log for more details: {build_log_path}\n")

def scan_build(self, directory: str, output_dir: str, build_log_file: IO):
def scan_build(self, directory: str, output_dir: str,
build_log_file: IO) -> Tuple[float, int]:
"""
Build the project with scan-build by reading in the commands and
prefixing them with the scan-build options.
Expand Down Expand Up @@ -416,6 +418,10 @@ def scan_build(self, directory: str, output_dir: str, build_log_file: IO):
options += "--override-compiler "

extra_env: Dict[str, str] = {}

execution_time = 0.0
peak_memory = 0

try:
command_file = open(build_script_path, "r")
command_prefix = "scan-build " + options + " "
Expand Down Expand Up @@ -451,19 +457,26 @@ def scan_build(self, directory: str, output_dir: str, build_log_file: IO):
if VERBOSE >= 1:
stdout(f" Executing: {command_to_run}\n")

check_call(command_to_run, cwd=cwd,
stderr=build_log_file,
stdout=build_log_file,
env=dict(os.environ, **extra_env),
shell=True)
time, mem = utils.check_and_measure_call(
command_to_run, cwd=cwd,
stderr=build_log_file,
stdout=build_log_file,
env=dict(os.environ, **extra_env),
shell=True)

execution_time += time
peak_memory = max(peak_memory, mem)

except CalledProcessError:
stderr("Error: scan-build failed. Its output was: \n")
build_log_file.seek(0)
shutil.copyfileobj(build_log_file, LOCAL.stderr)
sys.exit(1)

def analyze_preprocessed(self, directory: str, output_dir: str):
return execution_time, peak_memory

def analyze_preprocessed(self, directory: str,
output_dir: str) -> Tuple[float, int]:
"""
Run analysis on a set of preprocessed files.
"""
Expand All @@ -487,14 +500,17 @@ def analyze_preprocessed(self, directory: str, output_dir: str):
fail_path = os.path.join(plist_path, "failures")
os.makedirs(fail_path)

execution_time = 0.0
peak_memory = 0

for full_file_name in glob.glob(directory + "/*"):
file_name = os.path.basename(full_file_name)
failed = False

# Only run the analyzes on supported files.
if SATestUtils.has_no_extension(file_name):
if utils.has_no_extension(file_name):
continue
if not SATestUtils.is_valid_single_input_file(file_name):
if not utils.is_valid_single_input_file(file_name):
stderr(f"Error: Invalid single input file {full_file_name}.\n")
raise Exception()

Expand All @@ -509,8 +525,12 @@ def analyze_preprocessed(self, directory: str, output_dir: str):
if VERBOSE >= 1:
stdout(f" Executing: {command}\n")

check_call(command, cwd=directory, stderr=log_file,
stdout=log_file, shell=True)
time, mem = utils.check_and_measure_call(
command, cwd=directory, stderr=log_file,
stdout=log_file, shell=True)

execution_time += time
peak_memory = max(peak_memory, mem)

except CalledProcessError as e:
stderr(f"Error: Analyzes of {full_file_name} failed. "
Expand All @@ -522,6 +542,8 @@ def analyze_preprocessed(self, directory: str, output_dir: str):
if not failed:
os.remove(log_file.name)

return execution_time, peak_memory

def generate_config(self) -> str:
out = "serialize-stats=true,stable-report-filename=true"

Expand Down Expand Up @@ -579,7 +601,7 @@ def _download_from_git(self, directory: str, build_log_file: IO):
stdout=build_log_file, shell=True)

def _unpack_zip(self, directory: str, build_log_file: IO):
zip_files = list(glob.glob(os.path.join(directory, "/*.zip")))
zip_files = list(glob.glob(directory + "/*.zip"))

if len(zip_files) == 0:
raise ValueError(
Expand All @@ -598,9 +620,9 @@ def _unpack_zip(self, directory: str, build_log_file: IO):
@staticmethod
def _run_download_script(directory: str, build_log_file: IO):
script_path = os.path.join(directory, DOWNLOAD_SCRIPT)
SATestUtils.run_script(script_path, build_log_file, directory,
out=LOCAL.stdout, err=LOCAL.stderr,
verbose=VERBOSE)
utils.run_script(script_path, build_log_file, directory,
out=LOCAL.stdout, err=LOCAL.stderr,
verbose=VERBOSE)

@staticmethod
def _apply_patch(directory: str, build_log_file: IO):
Expand Down
Loading

0 comments on commit 955d3cb

Please sign in to comment.