[compiler-rt] a7d4826 - [profile] Fix buffer overrun when parsing %c in filename string

Vedant Kumar via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 24 14:49:53 PST 2021


Author: Vedant Kumar
Date: 2021-02-24T14:49:45-08:00
New Revision: a7d4826101aba8594bf5308c6a3e40c44608bca5

URL: https://github.com/llvm/llvm-project/commit/a7d4826101aba8594bf5308c6a3e40c44608bca5
DIFF: https://github.com/llvm/llvm-project/commit/a7d4826101aba8594bf5308c6a3e40c44608bca5.diff

LOG: [profile] Fix buffer overrun when parsing %c in filename string

Fix a buffer overrun that can occur when parsing '%c' at the end of a
filename pattern string.

rdar://74571261

Reviewed By: kastiglione

Differential Revision: https://reviews.llvm.org/D97239

Added: 
    compiler-rt/test/profile/ContinuousSyncMode/get-filename.c

Modified: 
    compiler-rt/lib/profile/InstrProfilingFile.c

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/profile/InstrProfilingFile.c b/compiler-rt/lib/profile/InstrProfilingFile.c
index 42ffdae82622..656df480ba2c 100644
--- a/compiler-rt/lib/profile/InstrProfilingFile.c
+++ b/compiler-rt/lib/profile/InstrProfilingFile.c
@@ -8,6 +8,7 @@
 
 #if !defined(__Fuchsia__)
 
+#include <assert.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -699,6 +700,13 @@ static unsigned getMergePoolSize(const char *FilenamePat, int *I) {
   return 0;
 }
 
+/* Assert that Idx does index past a string null terminator. Return the
+ * result of the check. */
+static int checkBounds(int Idx, int Strlen) {
+  assert(Idx <= Strlen && "Indexing past string null terminator");
+  return Idx <= Strlen;
+}
+
 /* Parses the pattern string \p FilenamePat and stores the result to
  * lprofcurFilename structure. */
 static int parseFilenamePattern(const char *FilenamePat,
@@ -707,6 +715,7 @@ static int parseFilenamePattern(const char *FilenamePat,
   char *PidChars = &lprofCurFilename.PidChars[0];
   char *Hostname = &lprofCurFilename.Hostname[0];
   int MergingEnabled = 0;
+  int FilenamePatLen = strlen(FilenamePat);
 
   /* Clean up cached prefix and filename.  */
   if (lprofCurFilename.ProfilePathPrefix)
@@ -725,9 +734,12 @@ static int parseFilenamePattern(const char *FilenamePat,
     lprofCurFilename.OwnsFilenamePat = 1;
   }
   /* Check the filename for "%p", which indicates a pid-substitution. */
-  for (I = 0; FilenamePat[I]; ++I)
+  for (I = 0; checkBounds(I, FilenamePatLen) && FilenamePat[I]; ++I) {
     if (FilenamePat[I] == '%') {
-      if (FilenamePat[++I] == 'p') {
+      ++I; /* Advance to the next character. */
+      if (!checkBounds(I, FilenamePatLen))
+        break;
+      if (FilenamePat[I] == 'p') {
         if (!NumPids++) {
           if (snprintf(PidChars, MAX_PID_SIZE, "%ld", (long)getpid()) <= 0) {
             PROF_WARN("Unable to get pid for filename pattern %s. Using the "
@@ -761,7 +773,6 @@ static int parseFilenamePattern(const char *FilenamePat,
 
         __llvm_profile_set_page_size(getpagesize());
         __llvm_profile_enable_continuous_mode();
-        I++; /* advance to 'c' */
       } else {
         unsigned MergePoolSize = getMergePoolSize(FilenamePat, &I);
         if (!MergePoolSize)
@@ -775,6 +786,7 @@ static int parseFilenamePattern(const char *FilenamePat,
         lprofCurFilename.MergePoolSize = MergePoolSize;
       }
     }
+  }
 
   lprofCurFilename.NumPids = NumPids;
   lprofCurFilename.NumHosts = NumHosts;

diff  --git a/compiler-rt/test/profile/ContinuousSyncMode/get-filename.c b/compiler-rt/test/profile/ContinuousSyncMode/get-filename.c
new file mode 100644
index 000000000000..d70e11991e18
--- /dev/null
+++ b/compiler-rt/test/profile/ContinuousSyncMode/get-filename.c
@@ -0,0 +1,32 @@
+// REQUIRES: darwin
+
+// RUN: %clang_pgogen -o %t.exe %s
+// RUN: env LLVM_PROFILE_FILE="%c%t.profraw" %run %t.exe %t.profraw
+// RUN: env LLVM_PROFILE_FILE="%t%c.profraw" %run %t.exe %t.profraw
+// RUN: env LLVM_PROFILE_FILE="%t.profraw%c" %run %t.exe %t.profraw
+
+#include <string.h>
+#include <stdio.h>
+
+extern int __llvm_profile_is_continuous_mode_enabled(void);
+extern const char *__llvm_profile_get_filename();
+extern void __llvm_profile_set_dumped(void);
+
+int main(int argc, char **argv) {
+  if (!__llvm_profile_is_continuous_mode_enabled())
+    return 1;
+
+  // Check that the filename is "%t.profraw", followed by a null terminator.
+  size_t n = strlen(argv[1]) + 1;
+  const char *Filename = __llvm_profile_get_filename();
+
+  for (int i = 0; i < n; ++i) {
+    if (Filename[i] != argv[1][i]) {
+      printf("Difference at: %d, Got: %c, Expected: %c\n", i, Filename[i], argv[1][i]);
+      printf("Got: %s\n", Filename);
+      printf("Expected: %s\n", argv[1]);
+      return 1;
+    }
+  }
+  return 0;
+}


        


More information about the llvm-commits mailing list