2015-01-15 10:21:18 +01:00
#!/usr/bin/perl
2021-07-11 00:00:22 +02:00
# SPDX-FileCopyrightText: 2021 Pragmatic Software <pragma78@gmail.com>
# SPDX-License-Identifier: MIT
2015-01-15 10:21:18 +01:00
use warnings ;
use strict ;
2019-06-26 18:34:19 +02:00
package _c_base ;
2015-01-15 10:21:18 +01:00
use parent '_default' ;
2015-05-19 05:48:15 +02:00
sub preprocess {
my $ self = shift ;
2019-06-13 06:35:04 +02:00
2022-02-06 20:33:21 +01:00
my $ input = $ self - > { input } // '' ;
2019-06-13 06:35:04 +02:00
open ( my $ fh , '>' , '.input' ) ;
print $ fh "$input\n" ;
close $ fh ;
2019-06-25 04:01:38 +02:00
my @ cmd = $ self - > split_line ( $ self - > { cmdline } , strip_quotes = > 1 , preserve_escapes = > 0 ) ;
2019-06-13 06:35:04 +02:00
if ( $ self - > { code } =~ m/print_last_statement\(.*\);$/m ) {
# remove print_last_statement wrapper in order to get warnings/errors from last statement line
my $ code = $ self - > { code } ;
$ code =~ s/print_last_statement\((.*)\);$/$1;/mg ;
open ( my $ fh , '>' , $ self - > { sourcefile } ) or die $! ;
print $ fh $ code . "\n" ;
close $ fh ;
print "Executing [$self->{cmdline}] without print_last_statement\n" ;
my ( $ retval , $ stdout , $ stderr ) = $ self - > execute ( 60 , undef , @ cmd ) ;
$ self - > { output } = $ stderr ;
$ self - > { output } . = ' ' if length $ self - > { output } ;
$ self - > { output } . = $ stdout ;
$ self - > { error } = $ retval ;
# now compile with print_last_statement intact, ignoring compile results
if ( not $ self - > { error } ) {
open ( my $ fh , '>' , $ self - > { sourcefile } ) or die $! ;
print $ fh $ self - > { code } . "\n" ;
close $ fh ;
print "Executing [$self->{cmdline}] with print_last_statement\n" ;
$ self - > execute ( 60 , undef , @ cmd ) ;
}
} else {
open ( my $ fh , '>' , $ self - > { sourcefile } ) or die $! ;
print $ fh $ self - > { code } . "\n" ;
close $ fh ;
print "Executing [$self->{cmdline}]\n" ;
my ( $ retval , $ stdout , $ stderr ) = $ self - > execute ( 60 , undef , @ cmd ) ;
$ self - > { output } = $ stderr ;
$ self - > { output } . = ' ' if length $ self - > { output } ;
$ self - > { output } . = $ stdout ;
$ self - > { error } = $ retval ;
}
2015-05-19 05:48:15 +02:00
if ( $ self - > { cmdline } =~ m/--(?:version|analyze)/ ) {
$ self - > { done } = 1 ;
}
}
2015-01-15 10:21:18 +01:00
sub postprocess {
my $ self = shift ;
2015-07-18 17:12:59 +02:00
$ self - > SUPER:: postprocess ;
2015-01-15 10:21:18 +01:00
# no errors compiling, but if output contains something, it must be diagnostic messages
if ( length $ self - > { output } ) {
$ self - > { output } =~ s/^\s+// ;
$ self - > { output } =~ s/\s+$// ;
$ self - > { output } = "[$self->{output}]\n" ;
}
print "Executing gdb\n" ;
2021-10-20 06:03:34 +02:00
my ( $ exitval , $ stdout , $ stderr ) ;
2022-02-06 09:24:04 +01:00
my $ ulimits = "ulimit -f 2000; ulimit -t 8; ulimit -u 200" ;
my @ args = $ self - > split_line ( $ self - > { arguments } , strip_quotes = > 1 , preserve_escapes = > 0 ) ;
my $ quoted_args = '' ;
foreach my $ arg ( @ args ) {
$ arg =~ s/'/'"'"'/g ;
$ quoted_args . = "'$arg' " ;
}
2021-10-20 06:03:34 +02:00
if ( $ self - > { cmdline } =~ /-fsanitize=(?:[^ ]+,)?address/ ) {
# leak sanitizer doesn't work under ptrace/gdb
# ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1
2022-02-06 09:24:04 +01:00
( $ exitval , $ stdout , $ stderr ) = $ self - > execute ( 60 , "$ulimits; ./prog $quoted_args\n" , '/bin/sh' ) ;
2021-10-20 06:03:34 +02:00
} else {
2022-02-06 09:24:04 +01:00
my $ input = "$ulimits; guest-gdb ./prog $quoted_args" ;
( $ exitval , $ stdout , $ stderr ) = $ self - > execute ( 60 , $ input , '/bin/sh' ) ;
2021-10-20 06:03:34 +02:00
}
2015-01-15 10:21:18 +01:00
2019-06-13 06:35:04 +02:00
my $ result = $ stderr ;
$ result . = ' ' if length $ result ;
$ result . = $ stdout ;
2015-01-15 10:21:18 +01:00
2015-09-18 07:18:14 +02:00
if ( not length $ result ) {
$ self - > { no_output } = 1 ;
} elsif ( $ self - > { code } =~ m/print_last_statement\(.*\);$/m
2019-06-13 06:35:04 +02:00
&& ( $ result =~ m/A syntax error in expression/ || $ result =~ m/No symbol.*in current context/ || $ result =~ m/has unknown return type; cast the call to its declared return/ || $ result =~ m/Can't take address of.*which isn't an lvalue/ ) ) {
2015-09-18 07:18:14 +02:00
# strip print_last_statement and rebuild/re-run
$ self - > { code } =~ s/print_last_statement\((.*)\);/$1;/mg ;
$ self - > preprocess ;
$ self - > postprocess ;
} else {
$ self - > { output } . = $ result ;
}
2015-01-15 10:21:18 +01:00
}
1 ;