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