def apply(self, mh, cfg, filename, full_text, lines): if len(lines) >= 2 and lines[-1] == "": mh.style_issue(Location(filename, len(lines)), "trailing blank lines at end of file", self.autofix) elif len(full_text) and full_text[-1] != "\n": mh.style_issue(Location(filename, len(lines)), "file should end with a new line", self.autofix)
def get_content(self): # First we try to read the file with the suggested encoding. try: with open(self.filename, "r", encoding=self.encoding) as fd: return fd.read() except UnicodeDecodeError: pass if self.encoding.lower() == "utf-8": # If that was UTF-8, we give up and ask for help. self.mh.error( Location(self.filename), "encoding error, please specify correct encoding" " on using --input-encoding", ) else: # Otherwise, we issue a warning, and try once more with # UTF-8. self.mh.warning( Location(self.filename), "encoding error for %s, assuming utf-8 instead" % self.encoding) self.encoding = "utf-8" try: with open(self.filename, "r", encoding=self.encoding) as fd: return fd.read() except UnicodeDecodeError: self.mh.error( Location(self.filename), "encoding error, please specify correct encoding" " on using --input-encoding", )
def register_parent(mh, options, dirname): assert isinstance(dirname, str) parent_dirname = os.path.dirname(dirname) if dirname in tree: return if DEBUG_TRACE_TREE: print("RP: %s" % dirname) # Check for a ".git" directory. This would indicate we've found a # project root. if USE_DOT_GIT and os.path.isdir(os.path.join(dirname, ".git")): found_root = True # Check if we're at the top of the filesystem elif parent_dirname == dirname: found_root = True # Otherwise we probably continue up else: found_root = False # Check if we have a config file present config_files = [] if not options.ignore_config: for cfg_filename in CONFIG_FILENAMES: if os.path.isfile(os.path.join(dirname, cfg_filename)): config_files.append(cfg_filename) tree[dirname] = Tree_Node(found_root, config_files) if len(config_files) > 1: mh.register_file(os.path.relpath(dirname)) mh.error( Location(os.path.relpath(dirname)), "multiple config files found; cannot find project root:" " please add a config file with the 'project_root'" " directive") elif config_files: try: cfg_file_ast = load_config(mh, os.path.join(dirname, config_files[0])) tree[dirname].set_ast(cfg_file_ast) except Error: cfg_file_ast = None if cfg_file_ast is None: mh.register_file(os.path.relpath(dirname)) mh.error( Location(os.path.relpath(dirname)), "cannot find project root because the config file" " contains errors: please add a config file with" " the 'project_root' directive") if not tree[dirname].project_root: register_parent(mh, options, parent_dirname)
def apply(self, mh, cfg, filename, line_no, line): if line.endswith(" "): if len(line.strip()) == 0: mh.style_issue(Location(filename, line_no), "whitespace on blank line", self.autofix) else: mh.style_issue( Location(filename, line_no, len(line.rstrip()), len(line), line), "trailing whitespace", self.autofix)
def apply(self, mh, cfg, filename, line_no, line): if len(line) > cfg.style_config["line_length"]: mh.style_issue( Location(filename, line_no, cfg.style_config["line_length"], len(line), line), "line exceeds %u characters" % cfg.style_config["line_length"], self.autofix)
def parse_config_file(self): n_file = Config_File() has_errors = False while not self.peek_eof(): try: n_item = self.parse_config_item() except Error: # On errors, we skip tokens until we get to a # newline has_errors = True n_item = None while not self.peek_eof() and not self.nt.first_in_line: self.skip() if n_item: n_file.add_item(n_item) self.match_eof() if has_errors: self.mh.error(Location(self.filename), "config file contains errors") return None return n_file
def apply(self, mh, cfg, filename, full_text, lines): if len(lines) > cfg.style_config["file_length"]: mh.style_issue(Location(filename, len(lines)), "file exceeds %u lines" % cfg.style_config["file_length"], self.autofix)
def apply(self, mh, cfg, filename, line_no, line): if len(line.strip()): self.is_blank = False elif self.is_blank: mh.style_issue(Location(filename, line_no), "more than one consecutive blank line", self.autofix) else: self.is_blank = True
def apply(self, mh, cfg, filename, line_no, line): if "\t" in line: mh.style_issue(Location(filename, line_no, line.index("\t"), line.index("\t"), line), "tab is not allowed", self.autofix)
def get_content(self): try: with open(self.filename, "r", encoding=self.encoding) as fd: return fd.read() except UnicodeDecodeError: pass if self.encoding != "utf-8": self.mh.warning( Location(self.filename), "encoding error for %s, assuming utf-8 instead" % self.encoding) self.encoding = "utf-8" try: with open(self.filename, "r", encoding=self.encoding) as fd: return fd.read() except UnicodeDecodeError: self.mh.error(Location(self.filename), "cannot read file, encoding error")
def loc(self): return Location(self.get_container().filename, blockname=self.local_name())
def loc(self): return Location(self.filename)
def analyze(mh, new_filename, lexer, n_file): assert isinstance(mh, Message_Handler) assert isinstance(new_filename, str) assert new_filename.endswith(".json_symtab") assert isinstance(lexer, MATLAB_Lexer) assert isinstance(n_file, m_ast.Function_File) def fmt_value(trace_value): assert trace_value["type"] == "int" return trace_value["data"] for n_fdef in n_file.l_functions: function_name = str(n_fdef.n_sig.n_name) cmd = ["cbmc", new_filename, "--json-ui", "--function", function_name, "--bounds-check", "--div-by-zero-check", "--signed-overflow-check", "--unsigned-overflow-check", "--float-overflow-check", "--nan-check"] cbmc_result = subprocess.run(cmd, check=False, capture_output=True, encoding="utf-8") assert cbmc_result.stderr == "" if cbmc_result.returncode == 0: mh.info(n_fdef.loc(), "verification successful") continue cbmc_msg = json.loads(cbmc_result.stdout) results = None for msg in cbmc_msg: if "result" in msg: if results is None: results = msg["result"] else: raise ICE("duplicate results") if results is None: raise ICE("result not found in cbmc output") for item in results: assert item["status"] == "FAILURE" fail_loc = item["trace"][-1] assert fail_loc["stepType"] == "failure" assert fail_loc["property"] == "overflow.1" orig_file = fail_loc["sourceLocation"]["file"] assert orig_file == lexer.filename orig_line = int(fail_loc["sourceLocation"]["line"]) orig_cols = fail_loc["sourceLocation"]["column"].split(":") orig_col_start = int(orig_cols[0]) orig_col_end = int(orig_cols[1]) loc = Location( filename = orig_file, line = orig_line, col_start = orig_col_start, col_end = orig_col_end, context = lexer.context_line[orig_line - 1]) mh.check(loc, "operation saturates for some inputs") for trace in item["trace"][:-1]: if trace["internal"] or trace["hidden"]: continue if trace["stepType"] == "assignment": mh.info(loc, "counter-example trace: %s = %s" % (trace["lhs"], fmt_value(trace["value"])))