198504959SGeorge Balatsouras // RUN: %clang_dfsan -gmlt %s -o %t && %run %t >%t.out 2>&1
298504959SGeorge Balatsouras // RUN: FileCheck %s < %t.out
398504959SGeorge Balatsouras
498504959SGeorge Balatsouras #include <assert.h>
598504959SGeorge Balatsouras #include <sanitizer/dfsan_interface.h>
698504959SGeorge Balatsouras #include <stdio.h>
798504959SGeorge Balatsouras #include <string.h>
898504959SGeorge Balatsouras
998504959SGeorge Balatsouras #define NOINLINE __attribute__((noinline))
1098504959SGeorge Balatsouras
bar(int depth,char * buf,size_t len)1198504959SGeorge Balatsouras NOINLINE size_t bar(int depth, char *buf, size_t len) {
1298504959SGeorge Balatsouras if (!depth) {
1398504959SGeorge Balatsouras return dfsan_sprint_stack_trace(buf, len);
1498504959SGeorge Balatsouras }
1598504959SGeorge Balatsouras
1698504959SGeorge Balatsouras return bar(depth - 1, buf, len);
1798504959SGeorge Balatsouras }
1898504959SGeorge Balatsouras
baz(int depth,char * buf,size_t len)1998504959SGeorge Balatsouras NOINLINE size_t baz(int depth, char *buf, size_t len) {
2098504959SGeorge Balatsouras return bar(depth, buf, len);
2198504959SGeorge Balatsouras }
2298504959SGeorge Balatsouras
main(int argc,char * argv[])2398504959SGeorge Balatsouras int main(int argc, char *argv[]) {
2498504959SGeorge Balatsouras char buf[3000];
2598504959SGeorge Balatsouras size_t length = dfsan_sprint_stack_trace(buf, sizeof(buf));
2698504959SGeorge Balatsouras assert(length < sizeof(buf));
2798504959SGeorge Balatsouras printf("==OUTPUT==\n%s==EOS==\n", buf);
2898504959SGeorge Balatsouras
2998504959SGeorge Balatsouras // CHECK: ==OUTPUT==
3098504959SGeorge Balatsouras // CHECK: #0 {{.*}} in main [[FILEPATH:.*]]/stack_trace.c:[[# @LINE - 5 ]]
3198504959SGeorge Balatsouras // CHECK: ==EOS==
3298504959SGeorge Balatsouras
3398504959SGeorge Balatsouras length = baz(8, buf, sizeof(buf));
3498504959SGeorge Balatsouras printf("==OUTPUT==\n%s==EOS==\n", buf);
3598504959SGeorge Balatsouras
3698504959SGeorge Balatsouras // CHECK: ==OUTPUT==
37*df9400c5SFangrui Song // CHECK: #0 {{.*}} in bar.dfsan [[FILEPATH]]/stack_trace.c:13
38*df9400c5SFangrui Song // CHECK-COUNT-8: #{{[1-9]+}} {{.*}} in bar.dfsan [[FILEPATH]]/stack_trace.c:16
39*df9400c5SFangrui Song // CHECK: #9 {{.*}} in baz.dfsan [[FILEPATH]]/stack_trace.c:20
4098504959SGeorge Balatsouras // CHECK: #10 {{.*}} in main [[FILEPATH]]/stack_trace.c:[[# @LINE - 7 ]]
4198504959SGeorge Balatsouras // CHECK: ==EOS==
4298504959SGeorge Balatsouras
4398504959SGeorge Balatsouras char tinybuf[8];
4498504959SGeorge Balatsouras size_t same_length = baz(8, tinybuf, sizeof(tinybuf));
4598504959SGeorge Balatsouras
4698504959SGeorge Balatsouras printf("==TRUNCATED OUTPUT==\n%s==EOS==\n", tinybuf);
4798504959SGeorge Balatsouras // CHECK: ==TRUNCATED OUTPUT==
4898504959SGeorge Balatsouras // CHECK: #0 ==EOS==
4998504959SGeorge Balatsouras
5098504959SGeorge Balatsouras printf("Returned length: %zu\n", length);
5198504959SGeorge Balatsouras printf("Actual length: %zu\n", strlen(buf));
5298504959SGeorge Balatsouras printf("Returned length with truncation: %zu\n", same_length);
5398504959SGeorge Balatsouras
5498504959SGeorge Balatsouras // CHECK: Returned length: [[#LEN:]]
5598504959SGeorge Balatsouras // CHECK: Actual length: [[#LEN]]
5698504959SGeorge Balatsouras // CHECK: Returned length with truncation: [[#LEN]]
5798504959SGeorge Balatsouras
5898504959SGeorge Balatsouras buf[0] = '\0';
5998504959SGeorge Balatsouras length = baz(8, buf, 0);
6098504959SGeorge Balatsouras printf("Output=\"%s\"\n", buf);
6198504959SGeorge Balatsouras printf("Returned length: %zu\n", length);
6298504959SGeorge Balatsouras // CHECK: Output=""
6398504959SGeorge Balatsouras // CHECK: Returned length: [[#LEN]]
6498504959SGeorge Balatsouras }
65