https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88037

            Bug ID: 88037
           Summary: std::string pretty printer causes "virtual memory
                    exhausted" when used on uninitialized data
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: walther at indel dot ch
  Target Milestone: ---

The Python pretty printer for std::string places no limit on the printed string
length, which means that when looking at uninitialized memory that happens to
have a huge value where the length field is expected, GDB dies trying to
allocate memory to fetch the lazy string:

../../gdb/utils.c:1053: internal-error: virtual memory exhausted: can't
allocate 2080900006 bytes.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) [answered Y; input not from terminal]
../../gdb/utils.c:1053: internal-error: virtual memory exhausted: can't
allocate 2080900006 bytes.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Create a core file of GDB? (y or n) [answered Y; input not from terminal]

In my case, this happened when stopped on a breakpoint at the beginning of a
function where further down a local std::string variable is declared and
initialized, and my GUI frontend issued MI command -stack-list-locals. The
returned list already included this local variable, even though it was not
initialized yet. Of course, corrupted or uninitialized variables can occur for
any number of other reasons when analyzing a faulty program.

I suggest adding something along the lines of

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py
b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 827c87b70..ba3606e3b 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -830,6 +830,10 @@ class StdStringPrinter:
             reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer ()
             header = ptr.cast(reptype) - 1
             length = header.dereference ()['_M_length']
+        if length > 10000:
+            # We may be looking at uninitialized memory and trying to print a
+            # multigigabyte string would run GDB out of memory.
+            return ptr.string(length = 100) + ('... (length: %d)' % length)
         if hasattr(ptr, "lazy_string"):
             return ptr.lazy_string (length = length)
         return ptr.string (length = length)

Reply via email to