[DB] Don't fail hard when realpath fails

Summary: When infer runs on preprocessed source, original files may not be around anymore. Don't crash infer when that happens.

Reviewed By: jvillard, jberdine

Differential Revision: D4258285

fbshipit-source-id: a19569c
master
Andrzej Kotulski 9 years ago committed by Facebook Github Bot
parent ff3b6a10db
commit bd0f0cc7fc

@ -171,10 +171,8 @@ def _text_of_report_list(project_root, reports, bugs_txt_path, limit=None,
def _is_user_visible(project_root, report): def _is_user_visible(project_root, report):
filename = report[JSON_INDEX_FILENAME]
kind = report[JSON_INDEX_KIND] kind = report[JSON_INDEX_KIND]
return (os.path.isfile(os.path.join(project_root, filename)) and return kind in [ISSUE_KIND_ERROR, ISSUE_KIND_WARNING, ISSUE_KIND_ADVICE]
kind in [ISSUE_KIND_ERROR, ISSUE_KIND_WARNING, ISSUE_KIND_ADVICE])
def print_and_save_errors(infer_out, project_root, json_report, bugs_out, def print_and_save_errors(infer_out, project_root, json_report, bugs_out,

@ -11,6 +11,7 @@ from __future__ import print_function
from __future__ import unicode_literals from __future__ import unicode_literals
import codecs import codecs
import os
from . import colorize, config from . import colorize, config
@ -67,6 +68,8 @@ def build_source_context(source_name, mode, report_line):
# get source excerpt # get source excerpt
line_number = 1 line_number = 1
excerpt = '' excerpt = ''
if not os.path.isfile(source_name):
return ''
with codecs.open(source_name, 'r', with codecs.open(source_name, 'r',
encoding=config.CODESET, errors="replace") as source_file: encoding=config.CODESET, errors="replace") as source_file:
# avoid going past the end of the file # avoid going past the end of the file

@ -386,13 +386,6 @@ let should_report (issue_kind: Exceptions.err_kind) issue_type error_desc =>
} }
}; };
let is_file source_file =>
switch (Unix.stat (DB.source_file_to_abs_path source_file)) {
| {st_kind: S_REG | S_LNK} => true
| _ => false
| exception Unix.Unix_error _ => false
};
let module IssuesCsv = { let module IssuesCsv = {
let csv_issues_id = ref 0; let csv_issues_id = ref 0;
let pp_header fmt () => let pp_header fmt () =>
@ -427,8 +420,7 @@ let module IssuesCsv = {
}; };
if ( if (
in_footprint && in_footprint &&
error_filter source_file error_desc error_name && error_filter source_file error_desc error_name && should_report ekind error_name error_desc
should_report ekind error_name error_desc && is_file source_file
) { ) {
let err_desc_string = error_desc_to_csv_string error_desc; let err_desc_string = error_desc_to_csv_string error_desc;
let err_advice_string = error_advice_to_csv_string error_desc; let err_advice_string = error_advice_to_csv_string error_desc;
@ -504,8 +496,7 @@ let module IssuesJson = {
if ( if (
in_footprint && in_footprint &&
error_filter source_file error_desc error_name && error_filter source_file error_desc error_name &&
should_report_source_file && should_report_source_file && should_report ekind error_name error_desc
should_report ekind error_name error_desc && is_file source_file
) { ) {
let kind = Exceptions.err_kind_string ekind; let kind = Exceptions.err_kind_string ekind;
let bug_type = Localise.to_string error_name; let bug_type = Localise.to_string error_name;
@ -826,8 +817,7 @@ let module Stats = {
let error_strs = { let error_strs = {
let pp1 fmt () => F.fprintf fmt "%d: %s" stats.nerrors type_str; let pp1 fmt () => F.fprintf fmt "%d: %s" stats.nerrors type_str;
let pp2 fmt () => let pp2 fmt () =>
F.fprintf F.fprintf fmt " %a:%d" DB.source_file_pp loc.Location.file loc.Location.line;
fmt " %a:%d" DB.source_file_pp loc.Location.file loc.Location.line;
let pp3 fmt () => F.fprintf fmt " (%a)" Localise.pp_error_desc error_desc; let pp3 fmt () => F.fprintf fmt " (%a)" Localise.pp_error_desc error_desc;
[pp_to_string pp1 (), pp_to_string pp2 (), pp_to_string pp3 ()] [pp_to_string pp1 (), pp_to_string pp2 (), pp_to_string pp3 ()]
}; };

@ -48,14 +48,14 @@ let rel_path_from_abs_path root fname =
else None (* The project root is not a prefix of the file name *) else None (* The project root is not a prefix of the file name *)
let source_file_from_abs_path fname = let source_file_from_abs_path fname =
(* IMPORTANT: results of realpath are cached to not ruin performance *)
let fname_real = realpath fname in
let project_root_real = realpath Config.project_root in
let models_dir_real = Config.models_src_dir in
if Filename.is_relative fname then if Filename.is_relative fname then
(failwithf (failwithf
"ERROR: Path %s is relative, when absolute path was expected .@." "ERROR: Path %s is relative, when absolute path was expected .@."
fname); fname);
(* try to get realpath of source file. Use original if it fails *)
let fname_real = try realpath fname with Unix.Unix_error _ -> fname in
let project_root_real = realpath Config.project_root in
let models_dir_real = Config.models_src_dir in
match rel_path_from_abs_path project_root_real fname_real with match rel_path_from_abs_path project_root_real fname_real with
| Some path -> RelativeProjectRoot path | Some path -> RelativeProjectRoot path
| None -> ( | None -> (

@ -600,8 +600,19 @@ let rec create_path path =
let realpath_cache = Hashtbl.create 1023 let realpath_cache = Hashtbl.create 1023
let realpath path = let realpath path =
try Hashtbl.find realpath_cache path match Hashtbl.find realpath_cache path with
with Not_found -> | exception Not_found -> (
let realpath = Core.Std.Filename.realpath path in match Core.Std.Filename.realpath path with
Hashtbl.add realpath_cache path realpath; | realpath ->
realpath Hashtbl.add realpath_cache path (Ok realpath);
realpath
| exception Unix.Unix_error (code, f, arg) ->
F.eprintf
"WARNING: Failed to resolve file %s with \"%s\" \n@." arg (Unix.error_message code);
(* cache failures as well *)
Hashtbl.add realpath_cache path (Error (code, f, arg));
raise (Unix.Unix_error (code, f, arg))
)
| Ok path -> path
| Error (code, f, arg) -> raise (Unix.Unix_error (code, f, arg))

@ -0,0 +1,16 @@
# 1 "/tmp/removed_src.c"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 330 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "/tmp/removed_src.c" 2
# 1 "/tmp/removed_header.h" 1
void fun();
# 3 "/tmp/removed_src.c" 2
int deref(int* a) { return *a; }
int test() { return deref(0); }

@ -0,0 +1,18 @@
# Copyright (c) 2016 - present Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
TESTS_DIR = ../..
ANALYZER = infer
CLANG_OPTIONS = -c
INFER_OPTIONS = --report-custom-error --developer-mode --headers --project-root ../codetoanalyze
INFERPRINT_OPTIONS = --issues-tests
SOURCES = \
../codetoanalyze/preprocessed.c
include $(TESTS_DIR)/clang.make

@ -0,0 +1 @@
/tmp/removed_src.c, test, 0, NULL_DEREFERENCE, [start of procedure test(),start of procedure deref()]
Loading…
Cancel
Save