From: Josef Weidendorfer Date: Mon, 26 Feb 2007 00:16:09 +0000 (+0000) Subject: Callgrind: Fix potential buffer overruns with user provided strings X-Git-Tag: svn/VALGRIND_3_3_0~348 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e06ac31db488d32dc06ffa11c1a8784ab01d08f8;p=thirdparty%2Fvalgrind.git Callgrind: Fix potential buffer overruns with user provided strings This introduces some macros to shorten the code for output of strings to a file descriptor. I could use this a lot, but this commit limits itself to the potential buffer overruns (to ease backporting - provided we want to do this) Heavy use of the macros probably blows up the code. Perhaps it would be better to provide e.g. a VG_(write_str3) function in the tool API. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6618 --- diff --git a/callgrind/command.c b/callgrind/command.c index bc4ae55218..67fcab9f28 100644 --- a/callgrind/command.c +++ b/callgrind/command.c @@ -128,41 +128,26 @@ static void setup_control(void) if (fd>=0) { Char buf[512]; Int i; - - VG_(sprintf)(buf, - "# This file is generated by Callgrind-" VERSION ".\n" - "# It is used to enable controlling the supervision of\n" - "# '%s'\n" - "# by external tools.\n\n", - VG_(args_the_exename) - ); - VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); + + WRITE_STR3(fd, + "# This file is generated by Callgrind-" VERSION ".\n" + "# It is used to enable controlling the supervision of\n" + "# '", VG_(args_the_exename), "'\n" + "# by external tools.\n\n"); VG_(sprintf)(buf, "version: " COMMAND_VERSION "\n"); VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); - VG_(sprintf)(buf, "base: %s\n", dir); - VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); - - VG_(sprintf)(buf, "dumps: %s\n", dump_filename); - VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); - - VG_(sprintf)(buf, "control: %s\n", command_file); - VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); - - VG_(sprintf)(buf, "result: %s\n", result_file); - VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); - - VG_(strcpy)(buf, "cmd:"); - VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); - VG_(sprintf)(buf, " %s", VG_(args_the_exename)); - VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); + WRITE_STR3(fd, "base: ", dir, "\n"); + WRITE_STR3(fd, "dumps: ", dump_filename, "\n"); + WRITE_STR3(fd, "control: ", command_file, "\n"); + WRITE_STR3(fd, "result: ", result_file, "\n"); + + WRITE_STR2(fd, "cmd: ", VG_(args_the_exename)); for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) { HChar* arg = * (HChar**)VG_(indexXA)( VG_(args_for_client), i ); if (!arg) continue; - tl_assert( VG_(strlen)(arg) < 512-4 ); /* see [512] above */ - VG_(sprintf)(buf, " %s", arg); - VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); + WRITE_STR2(fd, " ", arg); } VG_(write)(fd, "\n", 1); VG_(close)(fd); @@ -224,19 +209,14 @@ static Int dump_info(Int fd) VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); /* "base:" line */ - VG_(sprintf)(buf, "base: %s\n", dump_base); - VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); + WRITE_STR3(fd, "base: ", dump_base, "\n"); /* "cmd:" line */ - VG_(strcpy)(buf, "cmd:"); - VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); - VG_(sprintf)(buf, " %s", VG_(args_the_exename)); - VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); + WRITE_STR2(fd, "cmd: ", VG_(args_the_exename)); for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) { HChar* arg = * (HChar**)VG_(indexXA)( VG_(args_for_client), i ); if (!arg) continue; - VG_(sprintf)(buf, " %s", arg); - VG_(write)(fd, (void*)buf, VG_(strlen)(buf)); + WRITE_STR2(fd, " ", arg); } VG_(write)(fd, "\n", 1); diff --git a/callgrind/global.h b/callgrind/global.h index bb85bc6760..82b1d11629 100644 --- a/callgrind/global.h +++ b/callgrind/global.h @@ -121,6 +121,43 @@ struct _CommandLineOptions { #define LINE_BUF_LEN 64 +/* Convenience macros */ + +/* Use this only when size of sprintf args are known to fit into + * given buffer; for strings of unknown length, use WRITE_STR below + */ +#define WRITE_SPRINTF(fd, zz_buf, fmt, args...) \ + do { Int len = VG_(sprintf)(zz_buf, fmt, ## args); \ + VG_(write)(fd, (void*)zz_buf, len); \ + } while (0) + +#define WRITE_STR(fd, str) \ + do { if (str) { Int len = VG_(strlen)(str); \ + VG_(write)(fd, (void*)str, len); } \ + else VG_(write)(fd, "(null)", 6); \ + } while (0) + +#define WRITE_STR2(fd, str1, str2) \ + do { if (str1) { Int len = VG_(strlen)(str1); \ + VG_(write)(fd, (void*)str1, len); } \ + else VG_(write)(fd, "(null)", 6); \ + if (str2) { Int len = VG_(strlen)(str2); \ + VG_(write)(fd, (void*)str2, len); } \ + else VG_(write)(fd, "(null)", 6); \ + } while (0) + +#define WRITE_STR3(fd, str1, str2, str3) \ + do { if (str1) { Int len = VG_(strlen)(str1); \ + VG_(write)(fd, (void*)str1, len); } \ + else VG_(write)(fd, "(null)", 6); \ + if (str2) { Int len = VG_(strlen)(str2); \ + VG_(write)(fd, (void*)str2, len); } \ + else VG_(write)(fd, "(null)", 6); \ + if (str3) { Int len = VG_(strlen)(str3); \ + VG_(write)(fd, (void*)str3, len); } \ + else VG_(write)(fd, "(null)", 6); \ + } while (0) + /*------------------------------------------------------------*/ /*--- Statistics ---*/