clang-fortify-driver.cpp revision 8c8e02df25e6d5b9e25c540d4a778a3b120511fb
1// Copyright 2018 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <err.h>
6#include <fcntl.h>
7#include <signal.h>
8#include <stdio.h>
9#include <string.h>
10#include <unistd.h>
11
12#include "clang-fortify-common.h"
13
14// It's potentially easy for us to get blocked if a FORTIFY'ed I/O call isn't
15// properly verified.
16static void SetTimeout(int secs) {
17  struct sigaction sigact;
18  bzero(&sigact, sizeof(sigact));
19
20  sigact.sa_flags = SA_RESETHAND;
21  sigact.sa_handler = [](int) {
22    const char complaint[] = "!!! Timeout reached; abort abort abort\n";
23    (void)write(STDOUT_FILENO, complaint, strlen(complaint));
24    _exit(1);
25  };
26
27  if (sigaction(SIGALRM, &sigact, nullptr))
28    err(1, "Failed to establish a SIGALRM handler");
29
30  alarm(secs);
31}
32
33static void PrintFailures(const std::vector<Failure> &failures) {
34  fprintf(stderr, "Failure(s): (%zu total)\n", failures.size());
35  for (const Failure &f : failures) {
36    const char *why = f.expected_death ? "didn't die" : "died";
37    fprintf(stderr, "\t`%s` at line %d %s\n", f.message, f.line, why);
38  }
39}
40
41int main() {
42  // On my dev machine, this test takes around 70ms to run to completion. On
43  // samus, it's more like 20 seconds.
44  SetTimeout(300);
45
46  // Some functions (e.g. gets()) try to read from stdin. Stop them from doing
47  // so, lest they block forever.
48  int dev_null = open("/dev/null", O_RDONLY);
49  if (dev_null < 0)
50    err(1, "Failed opening /dev/null");
51
52  if (dup2(dev_null, STDIN_FILENO) < 0)
53    err(1, "Failed making stdin == /dev/null");
54
55  bool failed = false;
56
57  fprintf(stderr, "::: Testing _FORTIFY_SOURCE=1 :::\n");
58  std::vector<Failure> failures = test_fortify_1();
59  if (!failures.empty()) {
60    PrintFailures(failures);
61    failed = true;
62  }
63
64  fprintf(stderr, "::: Testing _FORTIFY_SOURCE=2 :::\n");
65  failures = test_fortify_2();
66  if (!failures.empty()) {
67    PrintFailures(failures);
68    failed = true;
69  }
70
71  return failed ? 1 : 0;
72}
73