Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | #!/usr/bin/perl |
michael@0 | 2 | |
michael@0 | 3 | # Sixgill: Static assertion checker for C/C++ programs. |
michael@0 | 4 | # Copyright (C) 2009-2010 Stanford University |
michael@0 | 5 | # Author: Brian Hackett |
michael@0 | 6 | # |
michael@0 | 7 | # This program is free software: you can redistribute it and/or modify |
michael@0 | 8 | # it under the terms of the GNU General Public License as published by |
michael@0 | 9 | # the Free Software Foundation, either version 3 of the License, or |
michael@0 | 10 | # (at your option) any later version. |
michael@0 | 11 | # |
michael@0 | 12 | # This program is distributed in the hope that it will be useful, |
michael@0 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
michael@0 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
michael@0 | 15 | # GNU General Public License for more details. |
michael@0 | 16 | # |
michael@0 | 17 | # You should have received a copy of the GNU General Public License |
michael@0 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
michael@0 | 19 | |
michael@0 | 20 | # do a complete run of the system from raw source to reports. this requires |
michael@0 | 21 | # various run_monitor processes to be running in the background (maybe on other |
michael@0 | 22 | # machines) and watching a shared poll_file for jobs. if the output directory |
michael@0 | 23 | # for this script already exists then an incremental analysis will be performed |
michael@0 | 24 | # and the reports will only reflect the changes since the earlier run. |
michael@0 | 25 | |
michael@0 | 26 | use strict; |
michael@0 | 27 | use warnings; |
michael@0 | 28 | use IO::Handle; |
michael@0 | 29 | use File::Basename qw(dirname); |
michael@0 | 30 | use Getopt::Long; |
michael@0 | 31 | use Cwd; |
michael@0 | 32 | |
michael@0 | 33 | ################################# |
michael@0 | 34 | # environment specific settings # |
michael@0 | 35 | ################################# |
michael@0 | 36 | |
michael@0 | 37 | my $WORKDIR; |
michael@0 | 38 | my $SIXGILL_BIN; |
michael@0 | 39 | |
michael@0 | 40 | # poll file shared with the run_monitor script. |
michael@0 | 41 | my $poll_file; |
michael@0 | 42 | |
michael@0 | 43 | # root directory of the project. |
michael@0 | 44 | my $build_dir; |
michael@0 | 45 | |
michael@0 | 46 | # directory containing gcc wrapper scripts. |
michael@0 | 47 | my $wrap_dir; |
michael@0 | 48 | |
michael@0 | 49 | # optional file with annotations from the web interface. |
michael@0 | 50 | my $ann_file = ""; |
michael@0 | 51 | |
michael@0 | 52 | # optional output directory to do a diff against. |
michael@0 | 53 | my $old_dir = ""; |
michael@0 | 54 | |
michael@0 | 55 | # run in the foreground |
michael@0 | 56 | my $foreground; |
michael@0 | 57 | |
michael@0 | 58 | my $builder = "make -j4"; |
michael@0 | 59 | |
michael@0 | 60 | my $suppress_logs; |
michael@0 | 61 | GetOptions("build-root|b=s" => \$build_dir, |
michael@0 | 62 | "poll-file=s" => \$poll_file, |
michael@0 | 63 | "no-logs!" => \$suppress_logs, |
michael@0 | 64 | "work-dir=s" => \$WORKDIR, |
michael@0 | 65 | "sixgill-binaries|binaries|b=s" => \$SIXGILL_BIN, |
michael@0 | 66 | "wrap-dir=s" => \$wrap_dir, |
michael@0 | 67 | "annotations-file|annotations|a=s" => \$ann_file, |
michael@0 | 68 | "old-dir|old=s" => \$old_dir, |
michael@0 | 69 | "foreground!" => \$foreground, |
michael@0 | 70 | "buildcommand=s" => \$builder, |
michael@0 | 71 | ) |
michael@0 | 72 | or die; |
michael@0 | 73 | |
michael@0 | 74 | if (not -d $build_dir) { |
michael@0 | 75 | mkdir($build_dir); |
michael@0 | 76 | } |
michael@0 | 77 | if ($old_dir ne "" && not -d $old_dir) { |
michael@0 | 78 | die "Old directory '$old_dir' does not exist\n"; |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | $WORKDIR ||= "sixgill-work"; |
michael@0 | 82 | mkdir($WORKDIR, 0755) if ! -d $WORKDIR; |
michael@0 | 83 | $poll_file ||= "$WORKDIR/poll.file"; |
michael@0 | 84 | $build_dir ||= "$WORKDIR/js-inbound-xgill"; |
michael@0 | 85 | |
michael@0 | 86 | if (!defined $SIXGILL_BIN) { |
michael@0 | 87 | chomp(my $path = `which xmanager`); |
michael@0 | 88 | if ($path) { |
michael@0 | 89 | use File::Basename qw(dirname); |
michael@0 | 90 | $SIXGILL_BIN = dirname($path); |
michael@0 | 91 | } else { |
michael@0 | 92 | die "Cannot find sixgill binaries. Use the -b option."; |
michael@0 | 93 | } |
michael@0 | 94 | } |
michael@0 | 95 | |
michael@0 | 96 | $wrap_dir ||= "$WORKDIR/xgill-inbound/wrap_gcc"; |
michael@0 | 97 | $wrap_dir = "$SIXGILL_BIN/../scripts/wrap_gcc" if not (-e "$wrap_dir/basecc"); |
michael@0 | 98 | die "Bad wrapper directory: $wrap_dir" if not (-e "$wrap_dir/basecc"); |
michael@0 | 99 | |
michael@0 | 100 | # code to clean the project from $build_dir. |
michael@0 | 101 | sub clean_project { |
michael@0 | 102 | system("make clean"); |
michael@0 | 103 | } |
michael@0 | 104 | |
michael@0 | 105 | # code to build the project from $build_dir. |
michael@0 | 106 | sub build_project { |
michael@0 | 107 | return system($builder) >> 8; |
michael@0 | 108 | } |
michael@0 | 109 | |
michael@0 | 110 | our %kill_on_exit; |
michael@0 | 111 | END { |
michael@0 | 112 | for my $pid (keys %kill_on_exit) { |
michael@0 | 113 | kill($pid); |
michael@0 | 114 | } |
michael@0 | 115 | } |
michael@0 | 116 | |
michael@0 | 117 | # commands to start the various xgill binaries. timeouts can be specified |
michael@0 | 118 | # for the backend analyses here, and a memory limit can be specified for |
michael@0 | 119 | # xmanager if desired (and USE_COUNT_ALLOCATOR is defined in util/alloc.h). |
michael@0 | 120 | my $xmanager = "$SIXGILL_BIN/xmanager"; |
michael@0 | 121 | my $xsource = "$SIXGILL_BIN/xsource"; |
michael@0 | 122 | my $xmemlocal = "$SIXGILL_BIN/xmemlocal -timeout=20"; |
michael@0 | 123 | my $xinfer = "$SIXGILL_BIN/xinfer -timeout=60"; |
michael@0 | 124 | my $xcheck = "$SIXGILL_BIN/xcheck -timeout=30"; |
michael@0 | 125 | |
michael@0 | 126 | # prefix directory to strip off source files. |
michael@0 | 127 | my $prefix_dir = $build_dir; |
michael@0 | 128 | |
michael@0 | 129 | ########################## |
michael@0 | 130 | # general purpose script # |
michael@0 | 131 | ########################## |
michael@0 | 132 | |
michael@0 | 133 | # Prevent ccache from being used. I don't think this does any good. The problem |
michael@0 | 134 | # I'm struggling with is that if autoconf.mk still has 'ccache gcc' in it, the |
michael@0 | 135 | # builds fail in a mysterious way. |
michael@0 | 136 | $ENV{CCACHE_COMPILERCHECK} = 'date +%s.%N'; |
michael@0 | 137 | delete $ENV{CCACHE_PREFIX}; |
michael@0 | 138 | |
michael@0 | 139 | my $usage = "USAGE: run_complete result-dir\n"; |
michael@0 | 140 | my $result_dir = shift or die $usage; |
michael@0 | 141 | |
michael@0 | 142 | if (not $foreground) { |
michael@0 | 143 | my $pid = fork(); |
michael@0 | 144 | if ($pid != 0) { |
michael@0 | 145 | print "Forked, exiting...\n"; |
michael@0 | 146 | exit(0); |
michael@0 | 147 | } |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | # if the result directory does not already exist, mark for a clean build. |
michael@0 | 151 | my $do_clean = 0; |
michael@0 | 152 | if (not (-d $result_dir)) { |
michael@0 | 153 | $do_clean = 1; |
michael@0 | 154 | mkdir $result_dir; |
michael@0 | 155 | } |
michael@0 | 156 | |
michael@0 | 157 | if (!$suppress_logs) { |
michael@0 | 158 | my $log_file = "$result_dir/complete.log"; |
michael@0 | 159 | open(OUT, ">>", $log_file) or die "append to $log_file: $!"; |
michael@0 | 160 | OUT->autoflush(1); # don't buffer writes to the main log. |
michael@0 | 161 | |
michael@0 | 162 | # redirect stdout and stderr to the log. |
michael@0 | 163 | STDOUT->fdopen(\*OUT, "w"); |
michael@0 | 164 | STDERR->fdopen(\*OUT, "w"); |
michael@0 | 165 | } |
michael@0 | 166 | |
michael@0 | 167 | # pids to wait on before exiting. these are collating worker output. |
michael@0 | 168 | my @waitpids; |
michael@0 | 169 | |
michael@0 | 170 | chdir $result_dir; |
michael@0 | 171 | |
michael@0 | 172 | # to do a partial run, comment out the commands here you don't want to do. |
michael@0 | 173 | |
michael@0 | 174 | my $status = run_build(); |
michael@0 | 175 | |
michael@0 | 176 | # end of run commands. |
michael@0 | 177 | |
michael@0 | 178 | for my $pid (@waitpids) { |
michael@0 | 179 | waitpid($pid, 0); |
michael@0 | 180 | $status ||= $? >> 8; |
michael@0 | 181 | } |
michael@0 | 182 | |
michael@0 | 183 | print "Exiting run_complete with status $status\n"; |
michael@0 | 184 | exit $status; |
michael@0 | 185 | |
michael@0 | 186 | # get the IP address which a freshly created manager is listening on. |
michael@0 | 187 | sub get_manager_address |
michael@0 | 188 | { |
michael@0 | 189 | my $log_file = shift or die; |
michael@0 | 190 | |
michael@0 | 191 | # give the manager one second to start, any longer and something's broken. |
michael@0 | 192 | sleep(1); |
michael@0 | 193 | |
michael@0 | 194 | my $log_data = `cat $log_file`; |
michael@0 | 195 | my ($port) = $log_data =~ /Listening on ([\.\:0-9]*)/ |
michael@0 | 196 | or die "no manager found"; |
michael@0 | 197 | print OUT "Connecting to manager on port $port\n" unless $suppress_logs; |
michael@0 | 198 | print "Connecting to manager on port $port.\n"; |
michael@0 | 199 | return $1; |
michael@0 | 200 | } |
michael@0 | 201 | |
michael@0 | 202 | sub run_build |
michael@0 | 203 | { |
michael@0 | 204 | print "build started: "; |
michael@0 | 205 | print scalar(localtime()); |
michael@0 | 206 | print "\n"; |
michael@0 | 207 | |
michael@0 | 208 | # fork off a process to run the build. |
michael@0 | 209 | defined(my $pid = fork) or die; |
michael@0 | 210 | |
michael@0 | 211 | # log file for the manager. |
michael@0 | 212 | my $manager_log_file = "$result_dir/build_manager.log"; |
michael@0 | 213 | |
michael@0 | 214 | if (!$pid) { |
michael@0 | 215 | # this is the child process, fork another process to run a manager. |
michael@0 | 216 | defined(my $pid = fork) or die; |
michael@0 | 217 | exec("$xmanager -terminate-on-assert > $manager_log_file 2>&1") if (!$pid); |
michael@0 | 218 | $kill_on_exit{$pid} = 1; |
michael@0 | 219 | |
michael@0 | 220 | if (!$suppress_logs) { |
michael@0 | 221 | # open new streams to redirect stdout and stderr. |
michael@0 | 222 | open(LOGOUT, "> $result_dir/build.log"); |
michael@0 | 223 | open(LOGERR, "> $result_dir/build_err.log"); |
michael@0 | 224 | STDOUT->fdopen(\*LOGOUT, "w"); |
michael@0 | 225 | STDERR->fdopen(\*LOGERR, "w"); |
michael@0 | 226 | } |
michael@0 | 227 | |
michael@0 | 228 | my $address = get_manager_address($manager_log_file); |
michael@0 | 229 | |
michael@0 | 230 | # write the configuration file for the wrapper script. |
michael@0 | 231 | my $config_file = "$WORKDIR/xgill.config"; |
michael@0 | 232 | open(CONFIG, ">", $config_file) or die "create $config_file: $!"; |
michael@0 | 233 | print CONFIG "$prefix_dir\n"; |
michael@0 | 234 | print CONFIG Cwd::abs_path("$result_dir/build_xgill.log")."\n"; |
michael@0 | 235 | print CONFIG "$address\n"; |
michael@0 | 236 | my @extra = ("-fplugin-arg-xgill-mangle=1"); |
michael@0 | 237 | push(@extra, "-fplugin-arg-xgill-annfile=$ann_file") |
michael@0 | 238 | if ($ann_file ne "" && -e $ann_file); |
michael@0 | 239 | print CONFIG join(" ", @extra) . "\n"; |
michael@0 | 240 | close(CONFIG); |
michael@0 | 241 | |
michael@0 | 242 | # Tell the wrapper where to find the config |
michael@0 | 243 | $ENV{"XGILL_CONFIG"} = Cwd::abs_path($config_file); |
michael@0 | 244 | |
michael@0 | 245 | # update the PATH so that the build will see the wrappers. |
michael@0 | 246 | $ENV{"PATH"} = "$wrap_dir:" . $ENV{"PATH"}; |
michael@0 | 247 | |
michael@0 | 248 | # do the build, cleaning if necessary. |
michael@0 | 249 | chdir $build_dir; |
michael@0 | 250 | clean_project() if ($do_clean); |
michael@0 | 251 | my $exit_status = build_project(); |
michael@0 | 252 | |
michael@0 | 253 | # signal the manager that it's over. |
michael@0 | 254 | system("$xsource -remote=$address -end-manager"); |
michael@0 | 255 | |
michael@0 | 256 | # wait for the manager to clean up and terminate. |
michael@0 | 257 | print "Waiting for manager to finish (build status $exit_status)...\n"; |
michael@0 | 258 | waitpid($pid, 0); |
michael@0 | 259 | my $manager_status = $?; |
michael@0 | 260 | delete $kill_on_exit{$pid}; |
michael@0 | 261 | |
michael@0 | 262 | # build is finished, the complete run can resume. |
michael@0 | 263 | # return value only useful if --foreground |
michael@0 | 264 | print "Exiting with status " . ($manager_status || $exit_status) . "\n"; |
michael@0 | 265 | exit($manager_status || $exit_status); |
michael@0 | 266 | } |
michael@0 | 267 | |
michael@0 | 268 | # this is the complete process, wait for the build to finish. |
michael@0 | 269 | waitpid($pid, 0); |
michael@0 | 270 | my $status = $? >> 8; |
michael@0 | 271 | print "build finished (status $status): "; |
michael@0 | 272 | print scalar(localtime()); |
michael@0 | 273 | print "\n"; |
michael@0 | 274 | |
michael@0 | 275 | return $status; |
michael@0 | 276 | } |
michael@0 | 277 | |
michael@0 | 278 | sub run_pass |
michael@0 | 279 | { |
michael@0 | 280 | my ($name, $command) = @_; |
michael@0 | 281 | my $log_file = "$result_dir/manager.$name.log"; |
michael@0 | 282 | |
michael@0 | 283 | # extra commands to pass to the manager. |
michael@0 | 284 | my $manager_extra = ""; |
michael@0 | 285 | $manager_extra .= "-modset-wait=10" if ($name eq "xmemlocal"); |
michael@0 | 286 | |
michael@0 | 287 | # fork off a manager process for the analysis. |
michael@0 | 288 | defined(my $pid = fork) or die; |
michael@0 | 289 | exec("$xmanager $manager_extra > $log_file 2>&1") if (!$pid); |
michael@0 | 290 | |
michael@0 | 291 | my $address = get_manager_address($log_file); |
michael@0 | 292 | |
michael@0 | 293 | # write the poll file for this pass. |
michael@0 | 294 | if (! -d dirname($poll_file)) { |
michael@0 | 295 | system("mkdir", "-p", dirname($poll_file)); |
michael@0 | 296 | } |
michael@0 | 297 | open(POLL, "> $poll_file"); |
michael@0 | 298 | print POLL "$command\n"; |
michael@0 | 299 | print POLL "$result_dir/$name\n"; |
michael@0 | 300 | print POLL "$address\n"; |
michael@0 | 301 | close(POLL); |
michael@0 | 302 | |
michael@0 | 303 | print "$name started: "; |
michael@0 | 304 | print scalar(localtime()); |
michael@0 | 305 | print "\n"; |
michael@0 | 306 | |
michael@0 | 307 | waitpid($pid, 0); |
michael@0 | 308 | unlink($poll_file); |
michael@0 | 309 | |
michael@0 | 310 | print "$name finished: "; |
michael@0 | 311 | print scalar(localtime()); |
michael@0 | 312 | print "\n"; |
michael@0 | 313 | |
michael@0 | 314 | # collate the worker's output into a single file. make this asynchronous |
michael@0 | 315 | # so we can wait a bit and make sure we get all worker output. |
michael@0 | 316 | defined($pid = fork) or die; |
michael@0 | 317 | |
michael@0 | 318 | if (!$pid) { |
michael@0 | 319 | sleep(20); |
michael@0 | 320 | exec("cat $name.*.log > $name.log"); |
michael@0 | 321 | } |
michael@0 | 322 | |
michael@0 | 323 | push(@waitpids, $pid); |
michael@0 | 324 | } |
michael@0 | 325 | |
michael@0 | 326 | # the names of all directories containing reports to archive. |
michael@0 | 327 | my $indexes; |
michael@0 | 328 | |
michael@0 | 329 | sub run_index |
michael@0 | 330 | { |
michael@0 | 331 | my ($name, $kind) = @_; |
michael@0 | 332 | |
michael@0 | 333 | return if (not (-e "report_$kind.xdb")); |
michael@0 | 334 | |
michael@0 | 335 | print "$name started: "; |
michael@0 | 336 | print scalar(localtime()); |
michael@0 | 337 | print "\n"; |
michael@0 | 338 | |
michael@0 | 339 | # make an index for the report diff if applicable. |
michael@0 | 340 | if ($old_dir ne "") { |
michael@0 | 341 | system("make_index $kind $old_dir > $name.diff.log"); |
michael@0 | 342 | system("mv $kind diff_$kind"); |
michael@0 | 343 | $indexes .= " diff_$kind"; |
michael@0 | 344 | } |
michael@0 | 345 | |
michael@0 | 346 | # make an index for the full set of reports. |
michael@0 | 347 | system("make_index $kind > $name.log"); |
michael@0 | 348 | $indexes .= " $kind"; |
michael@0 | 349 | |
michael@0 | 350 | print "$name finished: "; |
michael@0 | 351 | print scalar(localtime()); |
michael@0 | 352 | print "\n"; |
michael@0 | 353 | } |
michael@0 | 354 | |
michael@0 | 355 | sub archive_indexes |
michael@0 | 356 | { |
michael@0 | 357 | print "archive started: "; |
michael@0 | 358 | print scalar(localtime()); |
michael@0 | 359 | print "\n"; |
michael@0 | 360 | |
michael@0 | 361 | system("tar -czf reports.tgz $indexes"); |
michael@0 | 362 | system("rm -rf $indexes"); |
michael@0 | 363 | |
michael@0 | 364 | print "archive finished: "; |
michael@0 | 365 | print scalar(localtime()); |
michael@0 | 366 | print "\n"; |
michael@0 | 367 | } |