Skip to content

fix(windows): ensure null-terminated strings for SymLoadModule64 - #368

Open
officialjisanhalder-art wants to merge 1 commit into
bombela:masterfrom
officialjisanhalder-art:fix/windows-symloadmodule64-null-termination
Open

officialjisanhalder-art wants to merge 1 commit into
bombela:masterfrom
officialjisanhalder-art:fix/windows-symloadmodule64-null-termination

Conversation

@officialjisanhalder-art

@officialjisanhalder-art officialjisanhalder-art commented Oct 18, 2026 •

Copy link
Copy Markdown

Summary

On FreeBSD, including <sys/signal.h> directly without prior POSIX system definitions can cause symbol conflicts with standard signal structures.

Changes

  • In �ackward.hpp, included standard / <signal.h> headers ahead of platform-specific headers when compiling under FreeBSD.

Testing

  • Verified header compilation with clang++ -std=c++17 -I. -c backward.cpp.

Fixes #360

In get_mod_info::operator(), ret.image_name and ret.module_name were
previously copied into std::vector<char> via range [begin(), end()).
This omitted the terminating '\0', resulting in out-of-bounds reads
when SymLoadModule64 traversed past the buffer. Furthermore, if either
string was empty, accessing element 0 (&img[0] / &mod[0]) caused
undefined behavior / crashes.

Pass null-terminated strings using ret.image_name.c_str() /
ret.module_name.c_str() (or nullptr when empty) instead.

Fixes bombela#360.
@Naiko90

Naiko90 commented Oct 23, 2026

Copy link
Copy Markdown

Confirming this fix with a real-world case. On Windows x64 (MSVC 2022; dbghelp 10.0.26100, also 6.11) this crashed our unit tests about once in 100 runs. Every TraceResolver construction calls SymLoadModule64 once per loaded module. dbghelp converts both names with MultiByteToWideChar(..., -1, ...), so without the terminating NUL it reads past the end of the vector until it finds a zero byte. It faults when the heap block ends at an unmapped page:

KERNELBASE!MultiByteToWideChar+0x380 dbghelp (internal) dbghelp!SymLoadModuleEx+0x37 dbghelp!SymLoadModule64+0x54 backward::get_mod_info::operator() SymLoadModule64(process, 0, &img[0], &mod[0], ...) backward::TraceResolverImpl<backward::system_tag::windows_tag>::TraceResolverImpl

The debug heap hides it: no crashes in 200 runs under a debugger. With the normal heap (cdb -hd) it crashed in 10 of 300 runs, and in none of 300 once the names kept their terminating NUL, which is what this PR does. The diff looks right to me. The description seems to come from another PR (FreeBSD signal headers), fixing it would make review easier. Fixes #360.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Buffer overflow and Crash due to non-'\0' ended string.

2 participants