Skip to content

Commit 23c3aa3

Browse files
authored
config.h: removed check of non-builtin define for USE_UNIX_BACKTRACE_SUPPORT / hardened print_stacktrace() (#7773)
1 parent 99cf9e3 commit 23c3aa3

File tree

2 files changed

+66
-27
lines changed

2 files changed

+66
-27
lines changed

cli/stacktrace.cpp

Lines changed: 65 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,17 @@
3131
void print_stacktrace(FILE* output, int start_idx, bool demangling, int maxdepth, bool omit_above_own)
3232
{
3333
// 32 vs. 64bit
34-
#define ADDRESSDISPLAYLENGTH ((sizeof(long)==8)?12:8)
34+
static constexpr auto ADDRESSDISPLAYLENGTH = (sizeof(long) == 8) ? 12 : 8;
35+
3536
void *callstackArray[32]= {nullptr}; // the less resources the better...
3637
const int currentdepth = backtrace(callstackArray, static_cast<int>(getArrayLength(callstackArray)));
38+
if (currentdepth == 0) {
39+
fputs("Callstack could not be obtained (backtrace)\n", output);
40+
return;
41+
}
42+
if (currentdepth == getArrayLength(callstackArray)) {
43+
fputs("Callstack might be truncated\n", output);
44+
}
3745
// set offset to 1 to omit the printing function itself
3846
int offset=start_idx+1; // some entries on top are within our own exception handling code or libc
3947
if (maxdepth<0)
@@ -43,60 +51,92 @@ void print_stacktrace(FILE* output, int start_idx, bool demangling, int maxdepth
4351

4452
char **symbolStringList = backtrace_symbols(callstackArray, currentdepth);
4553
if (!symbolStringList) {
46-
fputs("Callstack could not be obtained\n", output);
54+
fputs("Callstack could not be obtained (backtrace_symbols)\n", output);
4755
return;
4856
}
4957

5058
fputs("Callstack:\n", output);
5159
bool own_code = false;
5260
char demangle_buffer[2048]= {0};
61+
bool no_address = false;
5362
for (int i = offset; i < maxdepth; ++i) {
5463
const char * const symbolString = symbolStringList[i];
64+
// TODO: implement parsing for __APPLE__
65+
// 0 test-signalhandler 0x0000000100dbf42c _Z16print_stacktraceP7__sFILEibib + 124
66+
67+
/*
68+
* examples:
69+
* ./test-signalhandler(_Z16print_stacktraceP8_IO_FILEibib+0xa1) [0x55cb65e41464]
70+
* ./test-signalhandler(+0xf9d9) [0x55cb65e3c9d9]
71+
*/
72+
5573
// skip all leading libc symbols so the first symbol is our code
5674
if (omit_above_own && !own_code) {
5775
if (strstr(symbolString, "/libc.so.6") != nullptr)
5876
continue;
5977
own_code = true;
60-
offset = i; // make sure the numbering is continous if we omit frames
78+
offset = i; // make sure the numbering is continuous if we omit frames
6179
}
62-
char * realnameString = nullptr;
63-
const char * const firstBracketName = strchr(symbolString, '(');
64-
const char * const firstBracketAddress = strchr(symbolString, '[');
65-
const char * const secondBracketAddress = strchr(firstBracketAddress, ']');
66-
const char * const beginAddress = firstBracketAddress+3;
67-
const int addressLen = int(secondBracketAddress-beginAddress);
68-
const int padLen = (ADDRESSDISPLAYLENGTH-addressLen);
69-
if (demangling && firstBracketName) {
70-
const char * const plus = strchr(firstBracketName, '+');
71-
if (plus && (plus>(firstBracketName+1))) {
72-
char input_buffer[1024]= {0};
73-
strncpy(input_buffer, firstBracketName+1, plus-firstBracketName-1);
74-
size_t length = getArrayLength(demangle_buffer);
75-
int status=0;
76-
// We're violating the specification - passing stack address instead of malloc'ed heap.
77-
// Benefit is that no further heap is required, while there is sufficient stack...
78-
realnameString = abi::__cxa_demangle(input_buffer, demangle_buffer, &length, &status); // non-NULL on success
80+
const char * realnameString = nullptr;
81+
if (demangling) {
82+
const char * const firstBracketName = strchr(symbolString, '(');
83+
if (firstBracketName) {
84+
const char * const plus = strchr(firstBracketName, '+');
85+
if (plus && (plus>(firstBracketName+1))) {
86+
char input_buffer[1024]= {0};
87+
strncpy(input_buffer, firstBracketName+1, plus-firstBracketName-1);
88+
size_t length = getArrayLength(demangle_buffer);
89+
int status=0;
90+
// We're violating the specification - passing stack address instead of malloc'ed heap.
91+
// Benefit is that no further heap is required, while there is sufficient stack...
92+
realnameString = abi::__cxa_demangle(input_buffer, demangle_buffer, &length, &status); // non-NULL on success
93+
}
7994
}
8095
}
96+
97+
const char * const firstBracketAddress = strchr(symbolString, '[');
98+
if (!firstBracketAddress) {
99+
no_address = true;
100+
break;
101+
}
102+
const char * const secondBracketAddress = strchr(firstBracketAddress, ']');
103+
if (!secondBracketAddress) {
104+
no_address = true;
105+
break;
106+
}
107+
81108
const int ordinal=i-offset;
82109
fprintf(output, "#%-2d 0x",
83110
ordinal);
111+
const int padLen = [&]() {
112+
const char * const beginAddress = firstBracketAddress+3;
113+
const int addressLen = int(secondBracketAddress-beginAddress);
114+
return (ADDRESSDISPLAYLENGTH-addressLen);
115+
}();
84116
if (padLen>0)
85117
fprintf(output, "%0*d",
86-
padLen, 0);
118+
padLen,
119+
0);
87120
if (realnameString) {
88121
fprintf(output, "%.*s in %s\n",
89-
static_cast<int>(secondBracketAddress - firstBracketAddress - 3), firstBracketAddress+3,
122+
static_cast<int>(secondBracketAddress - firstBracketAddress - 3),
123+
firstBracketAddress+3,
90124
realnameString);
91125
} else {
92126
fprintf(output, "%.*s in %.*s\n",
93-
static_cast<int>(secondBracketAddress - firstBracketAddress - 3), firstBracketAddress+3,
94-
static_cast<int>(firstBracketAddress - symbolString), symbolString);
127+
static_cast<int>(secondBracketAddress - firstBracketAddress - 3),
128+
firstBracketAddress+3,
129+
static_cast<int>(firstBracketAddress - symbolString),
130+
symbolString);
95131
}
96132
}
97133
// NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion) - code matches the documented usage
98134
free(symbolStringList);
99-
#undef ADDRESSDISPLAYLENGTH
135+
136+
if (no_address) {
137+
fputs("Callstack could not be obtained (no address)\n", output);
138+
return;
139+
}
100140
}
101141

102142
#endif // USE_UNIX_BACKTRACE_SUPPORT

lib/config.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,7 @@ static const std::string emptyString;
211211
#define USE_WINDOWS_SEH
212212
#endif
213213

214-
// TODO: __GLIBC__ is dependent on the features.h include and not a built-in compiler define, so it might be problematic to depend on it
215-
#if !defined(NO_UNIX_BACKTRACE_SUPPORT) && defined(__GNUC__) && defined(__GLIBC__) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__NetBSD__) && !defined(__SVR4) && !defined(__QNX__)
214+
#if !defined(NO_UNIX_BACKTRACE_SUPPORT) && defined(__GNUC__) && !defined(__APPLE__) && !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__NetBSD__) && !defined(__SVR4) && !defined(__QNX__)
216215
#define USE_UNIX_BACKTRACE_SUPPORT
217216
#endif
218217

0 commit comments

Comments
 (0)