Skip to content

Commit 0233b3e

Browse files
devajithvsdpiparo
authored andcommitted
[cling] Fix infinite recursion when printing self-referencing containers
Some container types (e.g., nlohmann::json scalar values) have iterators that dereference to the container itself, causing infinite recursion in `printValue_impl`. (cherry picked from commit c8a3d6a)
1 parent 9ab4de1 commit 0233b3e

2 files changed

Lines changed: 42 additions & 2 deletions

File tree

interpreter/cling/include/cling/Interpreter/RuntimePrintValue.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,20 @@ namespace cling {
210210
const void* M = TypeTest::isMap(obj);
211211

212212
std::string str("{ ");
213-
str += printValue(&(*iter), M);
213+
214+
// If the dereferenced iterator points to the container itself, we have
215+
// infinite recursion. This occurs with scalar values in nlohmann::json
216+
auto printWithRecursionGuard = [obj](const auto* ptr,
217+
const void* M) -> std::string {
218+
if (static_cast<const void*>(ptr) == static_cast<const void*>(obj))
219+
return "<recursion detected>";
220+
return printValue(ptr, M);
221+
};
222+
223+
str += printWithRecursionGuard(&(*iter), M);
214224
while (++iter != iterEnd) {
215225
str += ", ";
216-
str += printValue(&(*iter), M);
226+
str += printWithRecursionGuard(&(*iter), M);
217227
}
218228
return str + " }";
219229
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//------------------------------------------------------------------------------
2+
// CLING - the C++ LLVM-based InterpreterG :)
3+
//
4+
// This file is dual-licensed: you can choose to license it under the University
5+
// of Illinois Open Source License or the GNU Lesser General Public License. See
6+
// LICENSE.TXT for details.
7+
8+
//------------------------------------------------------------------------------
9+
10+
// RUN: cat %s | %cling -Xclang -verify 2>&1 | FileCheck %s
11+
12+
.rawInput 1
13+
// When begin() != end() but *begin() points to the container itself
14+
// (in nlohmann::json), printValue_impl infinitely recurses without the
15+
// self-reference check.
16+
17+
class RecursionTest {
18+
public:
19+
RecursionTest() = default;
20+
auto begin() const { return this; } // iterate over self
21+
auto end() const { return this + 1; } // just to make sure begin() != end()
22+
};
23+
.rawInput 0
24+
25+
RecursionTest j;
26+
j
27+
// CHECK: (RecursionTest &) { <recursion detected> }
28+
29+
// expected-no-diagnostics
30+
.q

0 commit comments

Comments
 (0)