Home | History | Annotate | Download | only in src
      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.
     16 static 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 
     33 static 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 
     41 int 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