Files
llvm-project/lldb/test/Shell/Settings/TestCxxFrameFormatRecursive.test
Michael Buch 1d07609894 [lldb][Format] Reject recursive format entities (#174750)
Depends on:
* https://github.com/llvm/llvm-project/pull/174618

If a format entity calls back into `Format` and passes it a format
entity type that we're already in the process of parsing, we are likely
going to run into infinite recursion and blow the stack. I think this is
only an issue when a format entity calls Format on a format string
provided by the user (otherwise we're in control of the recursion). An
example of this can be seen in the test-case adjusted by this patch.

This seems to be causing actual crashes in the field, so this patch adds
basic tracking to `Formatter::Format` that checks whether we're
recursively parsing the same entity. This may very well be intended by
some entities (e.g., `Root` and `Scope`), so there is an escape hatch
for those. There's also a special case where `Variable` causes a
recursive format (which I pointed out in a source comment).

We could narrow the scope of what kind of recursion is allowed by adding
a `UserProvidedFormatChild` (or similar) flag to `Entry`, and only
disallow recursing on those kinds of entries. For now I just use an
exemption list in `IsInvalidRecursiveFormat`.

Adding a unit-test for this is unfortunately tricky because the only
format entity that currently suffers from this is
`${function.name-with-args}`, which requires a language plugin and valid
target. If we really wanted to we could probably mock all of those, but
the shell test provides test coverage for the previously crashing case.

rdar://166890120
2026-01-08 16:25:42 +00:00

23 lines
651 B
Plaintext

# Test disallowed variables inside the
# plugin.cplusplus.display.function-name-format setting.
# RUN: split-file %s %t
# RUN: %clang_host -g -gdwarf %t/main.cpp -o %t.out
# RUN: %lldb -o "settings set interpreter.stop-command-source-on-error false" \
# RUN: -x -b -s %t/commands.input %t.out -o exit 2>&1 \
# RUN: | FileCheck %s
#--- main.cpp
int main(int argc, char const *argv[]) { return 0; }
#--- commands.input
settings set plugin.cplusplus.display.function-name-format "${function.name-with-args}"
settings set -f frame-format "custom-frame '${function.name-with-args}'\n"
b main
run
bt
# CHECK: bt
# CHECK: custom-frame 'main