diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c
index 22d2ae05b..2e8ee8d94 100644
--- a/coregrind/m_debuginfo/debuginfo.c
+++ b/coregrind/m_debuginfo/debuginfo.c
@@ -744,38 +744,73 @@ Bool VG_(lookup_symbol_SLOW)(UChar* sopatt, UChar* name, Addr* pEnt, Addr* pToc)
}
-/* Print into buf info on code address, function name and filename */
+/* VG_(describe_IP): print into buf info on code address, function
+ name and filename. */
+
+/* Copy str into buf starting at n, but not going past buf[n_buf-1]
+ and always ensuring that buf is zero-terminated. */
static Int putStr ( Int n, Int n_buf, Char* buf, Char* str )
{
+ vg_assert(n_buf > 0);
+ vg_assert(n >= 0 && n < n_buf);
for (; n < n_buf-1 && *str != 0; n++,str++)
buf[n] = *str;
+ vg_assert(n >= 0 && n < n_buf);
buf[n] = '\0';
return n;
}
-static Int putStrEsc ( Int n, Int n_buf, Char* buf, Char* str )
+
+/* Same as putStr, but escaping chars for XML output, and
+ also not adding more than count chars to n_buf. */
+
+static Int putStrEsc ( Int n, Int n_buf, Int count, Char* buf, Char* str )
{
Char alt[2];
+ vg_assert(n_buf > 0);
+ vg_assert(count >= 0 && count < n_buf);
+ vg_assert(n >= 0 && n < n_buf);
for (; *str != 0; str++) {
+ vg_assert(count >= 0);
+ if (count <= 0)
+ goto done;
switch (*str) {
- case '&': n = putStr( n, n_buf, buf, "&"); break;
- case '<': n = putStr( n, n_buf, buf, "<"); break;
- case '>': n = putStr( n, n_buf, buf, ">"); break;
- default: alt[0] = *str;
- alt[1] = 0;
- n = putStr( n, n_buf, buf, alt );
- break;
+ case '&':
+ if (count < 5) goto done;
+ n = putStr( n, n_buf, buf, "&");
+ count -= 5;
+ break;
+ case '<':
+ if (count < 4) goto done;
+ n = putStr( n, n_buf, buf, "<");
+ count -= 4;
+ break;
+ case '>':
+ if (count < 4) goto done;
+ n = putStr( n, n_buf, buf, ">");
+ count -= 4;
+ break;
+ default:
+ if (count < 1) goto done;
+ alt[0] = *str;
+ alt[1] = 0;
+ n = putStr( n, n_buf, buf, alt );
+ count -= 1;
+ break;
}
}
+ done:
+ vg_assert(count >= 0); /* should not go -ve in loop */
+ vg_assert(n >= 0 && n < n_buf);
return n;
}
Char* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf)
{
# define APPEND(_str) \
- n = putStr(n, n_buf, buf, _str);
-# define APPEND_ESC(_str) \
- n = putStrEsc(n, n_buf, buf, _str);
+ n = putStr(n, n_buf, buf, _str)
+# define APPEND_ESC(_count,_str) \
+ n = putStrEsc(n, n_buf, (_count), buf, (_str))
# define BUF_LEN 4096
UInt lineno;
@@ -802,7 +837,12 @@ Char* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf)
HChar* maybe_newline = human_readable ? "\n " : "";
HChar* maybe_newline2 = human_readable ? "\n " : "";
- /* Print in XML format, dumping in as much info as we know. */
+ /* Print in XML format, dumping in as much info as we know.
+ Ensure all tags are balanced even if the individual strings
+ are too long. Allocate 1/10 of BUF_LEN to the object name,
+ 6/10s to the function name, 1/10 to the directory name and
+ 1/10 to the file name, leaving 1/10 for all the fixed-length
+ stuff. */
APPEND("");
VG_(sprintf)(ibuf,"