}
-/* 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;
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("<frame>");
VG_(sprintf)(ibuf,"<ip>0x%llx</ip>", (ULong)eip);
APPEND(maybe_newline);
if (know_objname) {
APPEND(maybe_newline);
APPEND("<obj>");
- APPEND_ESC(buf_obj);
+ APPEND_ESC(1*BUF_LEN/10, buf_obj);
APPEND("</obj>");
}
if (know_fnname) {
APPEND(maybe_newline);
APPEND("<fn>");
- APPEND_ESC(buf_fn);
+ APPEND_ESC(6*BUF_LEN/10, buf_fn);
APPEND("</fn>");
}
if (know_srcloc) {
if (know_dirinfo) {
APPEND(maybe_newline);
APPEND("<dir>");
- APPEND(buf_dirname);
+ APPEND_ESC(1*BUF_LEN/10, buf_dirname);
APPEND("</dir>");
}
APPEND(maybe_newline);
APPEND("<file>");
- APPEND_ESC(buf_srcloc);
+ APPEND_ESC(1*BUF_LEN/10, buf_srcloc);
APPEND("</file>");
APPEND(maybe_newline);
APPEND("<line>");