Coverage Report

Created: 2025-07-12 06:03

/src/ntpsec/libntp/assert.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright Internet Systems Consortium, Inc. ("ISC")
3
 * Copyright Internet Software Consortium.
4
 * Copyright the NTPsec project contributors
5
 * SPDX-License-Identifier: ISC
6
 */
7
8
/*! \file */
9
10
#include "config.h"
11
12
#include <stdio.h>
13
#include <stdlib.h>
14
15
#include "ntp.h"
16
#include "ntp_debug.h"
17
#include "ntp_syslog.h"
18
#include "ntp_assert.h"
19
#include "isc_result.h"
20
21
#ifdef USEBACKTRACE
22
23
/*
24
 * Getting a back trace of a running process is tricky and highly platform
25
 * dependent.  Our current approach is as follows:
26
 * 1. If the system library supports the "backtrace()" function, use it.
27
 *    OS X support this starting at with SDK 10.5.  glibc since version 2.1
28
 * 2. Otherwise, if unwind.h exists then use the __Unwind_Backtrace() function.
29
 *    This function is available on Linux, OS X, and FreeBSD.  It is defined
30
 *    in Linux Standard Base since version 4.1
31
 * 3. Otherwise, tough luck.
32
 */
33
34
/*
35
 * The maximum number of stack frames to dump on assertion failure.
36
 */
37
#ifndef BACKTRACE_MAXFRAME
38
0
#define BACKTRACE_MAXFRAME 128
39
#endif
40
41
42
# ifdef HAVE_BACKTRACE_SYMBOLS_FD
43
#include <execinfo.h>
44
45
void
46
0
backtrace_log(void) {
47
0
  int nptrs;
48
0
  void *buffer[BACKTRACE_MAXFRAME];
49
0
  char **strings;
50
51
0
  nptrs = backtrace(buffer, BACKTRACE_MAXFRAME);
52
0
  strings = backtrace_symbols(buffer, nptrs);
53
0
  msyslog(LOG_ERR, "ERR: Stack trace:\n");
54
0
  if (strings) {
55
     /* skip trace of this shim function */
56
0
     for (int j = 1; j < nptrs; j++)
57
0
         msyslog(LOG_ERR, "ERR:  %s\n", strings[j]);
58
59
0
     free(strings);
60
0
  }
61
0
}
62
# elif defined(HAVE__UNWIND_BACKTRACE)
63
#include <unwind.h>
64
65
typedef struct {
66
  void **result;
67
  int max_depth;
68
  int skip_count;
69
  int count;
70
} trace_arg_t;
71
72
static _Unwind_Reason_Code
73
btcallback(struct _Unwind_Context *uc, void *opq) {
74
  trace_arg_t *arg = (trace_arg_t *)opq;
75
76
  if (arg->skip_count > 0)
77
    arg->skip_count--;
78
  else
79
    arg->result[arg->count++] = (void *)_Unwind_GetIP(uc);
80
  if (arg->count == arg->max_depth)
81
    return (5); /* _URC_END_OF_STACK */
82
83
  return (0); /* _URC_NO_REASON */
84
}
85
86
87
void
88
backtrace_log(void) {
89
  trace_arg_t arg;
90
  void *buffer[BACKTRACE_MAXFRAME];
91
92
  arg.skip_count = 1;
93
  arg.result = buffer;
94
  arg.max_depth = BACKTRACE_MAXFRAME;
95
  arg.count = 0;
96
  _Unwind_Backtrace(btcallback, &arg);
97
98
  msyslog(LOG_ERR, "ERR: Stack trace:\n");
99
  /* skip trace of this shim function */
100
  for (int i = 1; i < arg.count; i++) {
101
      msyslog(LOG_ERR, "ERR: #%d %p in ??\n", i, buffer[i]);
102
  }
103
104
}
105
#endif /* HAVE__UNWIND_BACKTRACE */
106
107
#endif /* USEBACKTRACE */
108
109
/*% Type to Text */
110
static const char *
111
0
assertion_typetotext(assertiontype_t type) {
112
0
  const char *result;
113
114
  /*
115
   * These strings have purposefully not been internationalized
116
   * because they are considered to essentially be keywords of
117
   * the ISC development environment.
118
   */
119
0
  switch (type) {
120
0
  case assertiontype_require:
121
0
    result = "REQUIRE";
122
0
    break;
123
0
  case assertiontype_ensure:
124
0
    result = "ENSURE";
125
0
    break;
126
0
  case assertiontype_insist:
127
0
    result = "INSIST";
128
0
    break;
129
0
  case assertiontype_invariant:
130
0
    result = "INVARIANT";
131
0
    break;
132
0
  default:
133
0
    result = "(null)";
134
0
  }
135
0
  return (result);
136
0
}
137
138
/*
139
 * assertion_failed - Redirect assertion failed output to msyslog().
140
 */
141
void
142
assertion_failed(
143
  const char *file,
144
  int line,
145
  assertiontype_t type,
146
  const char *cond
147
  )
148
0
{
149
        /* Is recursion an issue? */
150
151
0
  termlogit = true; /* insist log to terminal */
152
153
0
  msyslog(LOG_ERR, "ERR: %s:%d: %s(%s) failed",
154
0
    file, line, assertion_typetotext(type), cond);
155
0
#ifndef BACKTRACE_DISABLED
156
0
        backtrace_log();
157
0
#endif
158
0
  msyslog(LOG_ERR, "ERR: exiting (due to assertion failure)");
159
160
0
  abort();
161
0
}