| // RUN: %clang_analyze_cc1 -analyzer-checker=core,security.insecureAPI.vfork,unix.Vfork -verify %s |
| // RUN: %clang_analyze_cc1 -analyzer-checker=core,security.insecureAPI.vfork,unix.Vfork -verify -x c++ %s |
| |
| #include "Inputs/system-header-simulator.h" |
| |
| void foo(); |
| |
| // Ensure that child process is properly checked. |
| int f1(int x) { |
| pid_t pid = vfork(); // expected-warning{{Call to function 'vfork' is insecure}} |
| if (pid != 0) |
| return 0; |
| |
| switch (x) { |
| case 0: |
| // Ensure that modifying pid is ok. |
| pid = 1; // no-warning |
| // Ensure that calling whitelisted routines is ok. |
| execl("", "", 0); // no-warning |
| _exit(1); // no-warning |
| break; |
| case 1: |
| // Ensure that writing variables is prohibited. |
| x = 0; // expected-warning{{This assignment is prohibited after a successful vfork}} |
| break; |
| case 2: |
| // Ensure that calling functions is prohibited. |
| foo(); // expected-warning{{This function call is prohibited after a successful vfork}} |
| break; |
| default: |
| // Ensure that returning from function is prohibited. |
| return 0; // expected-warning{{Return is prohibited after a successful vfork; call _exit() instead}} |
| } |
| |
| while(1); |
| } |
| |
| // Same as previous but without explicit pid variable. |
| int f2(int x) { |
| pid_t pid = vfork(); // expected-warning{{Call to function 'vfork' is insecure}} |
| |
| switch (x) { |
| case 0: |
| // Ensure that writing pid is ok. |
| pid = 1; // no-warning |
| // Ensure that calling whitelisted routines is ok. |
| execl("", "", 0); // no-warning |
| _exit(1); // no-warning |
| break; |
| case 1: |
| // Ensure that writing variables is prohibited. |
| x = 0; // expected-warning{{This assignment is prohibited after a successful vfork}} |
| break; |
| case 2: |
| // Ensure that calling functions is prohibited. |
| foo(); // expected-warning{{This function call is prohibited after a successful vfork}} |
| break; |
| default: |
| // Ensure that returning from function is prohibited. |
| return 0; // expected-warning{{Return is prohibited after a successful vfork; call _exit() instead}} |
| } |
| |
| while(1); |
| } |
| |
| // Ensure that parent process isn't restricted. |
| int f3(int x) { |
| if (vfork() == 0) // expected-warning{{Call to function 'vfork' is insecure}} |
| _exit(1); |
| x = 0; // no-warning |
| foo(); // no-warning |
| return 0; |
| } // no-warning |
| |
| // Unbound pids are special so test them separately. |
| void f4(int x) { |
| switch (x) { |
| case 0: |
| vfork(); // expected-warning{{Call to function 'vfork' is insecure}} |
| x = 0; // expected-warning{{This assignment is prohibited after a successful vfork}} |
| break; |
| |
| case 1: |
| { |
| char args[2]; |
| switch (vfork()) { // expected-warning{{Call to function 'vfork' is insecure}} |
| case 0: |
| args[0] = 0; // expected-warning{{This assignment is prohibited after a successful vfork}} |
| exit(1); |
| } |
| break; |
| } |
| |
| case 2: |
| { |
| pid_t pid; |
| if ((pid = vfork()) == 0) // expected-warning{{Call to function 'vfork' is insecure}} |
| while(1); // no-warning |
| break; |
| } |
| } |
| while(1); |
| } //no-warning |
| |
| |
| void f5() { |
| // See "libxtables: move some code to avoid cautions in vfork man page" |
| // (http://lists.netfilter.org/pipermail/netfilter-buglog/2014-October/003280.html). |
| if (vfork() == 0) { // expected-warning{{Call to function 'vfork' is insecure}} |
| execl("prog", "arg1", 0); // no-warning |
| exit(1); // expected-warning{{This function call is prohibited after a successful vfork}} |
| } |
| } |
| |