@@ -96,12 +96,75 @@ static void RecursiveCreateParentDirs(char *path) {
9696 }
9797}
9898
99+ // / Parse the report path \p pattern and copy the parsed path to \p dest.
100+ // /
101+ // / * `%%` becomes `%`
102+ // / * `%H` expands to the environment variable `HOME`
103+ // / * `%t` expands to the environment variable `TMPDIR`
104+ // / * `%p` expands to the process ID (PID)
105+ static void ParseAndSetPath (const char *pattern, char *dest,
106+ const uptr dest_size) {
107+ CHECK (pattern);
108+ CHECK (dest);
109+ CHECK_GT (dest_size, 1 );
110+ dest[0 ] = ' \0 ' ;
111+ uptr next_substr_start_idx = 0 ;
112+ for (uptr i = 0 ; i < internal_strlen (pattern) - 1 ; i++) {
113+ if (pattern[i] != ' %' )
114+ continue ;
115+ int bytes_to_copy = i - next_substr_start_idx;
116+ // Copy over previous substring.
117+ CHECK_LT (internal_strlcat (dest, pattern + next_substr_start_idx,
118+ internal_strlen (dest) + bytes_to_copy + 1 ),
119+ dest_size);
120+ const char *str_to_concat;
121+ switch (pattern[++i]) {
122+ case ' %' :
123+ str_to_concat = " %" ;
124+ break ;
125+ case ' H' :
126+ str_to_concat = GetEnv (" HOME" );
127+ break ;
128+ case ' t' :
129+ str_to_concat = GetEnv (" TMPDIR" );
130+ break ;
131+ case ' p' : {
132+ // Use printf directly to write the PID since it's not a static string.
133+ int remaining_capacity = dest_size - internal_strlen (dest);
134+ int bytes_copied =
135+ internal_snprintf (dest + internal_strlen (dest), remaining_capacity,
136+ " %ld" , internal_getpid ());
137+ CHECK_GT (bytes_copied, 0 );
138+ CHECK_LT (bytes_copied, remaining_capacity);
139+ str_to_concat = " " ;
140+ break ;
141+ }
142+ default : {
143+ // Invalid pattern: fallback to original pattern.
144+ const char *message = " ERROR: Unexpected pattern: " ;
145+ WriteToFile (kStderrFd , message, internal_strlen (message));
146+ WriteToFile (kStderrFd , pattern, internal_strlen (pattern));
147+ WriteToFile (kStderrFd , " \n " , internal_strlen (" \n " ));
148+ CHECK_LT (internal_strlcpy (dest, pattern, dest_size), dest_size);
149+ return ;
150+ }
151+ }
152+ CHECK (str_to_concat);
153+ CHECK_LT (internal_strlcat (dest, str_to_concat, dest_size), dest_size);
154+ next_substr_start_idx = i + 1 ;
155+ }
156+ CHECK_LT (internal_strlcat (dest, pattern + next_substr_start_idx, dest_size),
157+ dest_size);
158+ }
159+
99160void ReportFile::SetReportPath (const char *path) {
100161 if (path) {
101162 uptr len = internal_strlen (path);
102163 if (len > sizeof (path_prefix) - 100 ) {
103- Report (" ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n " , path[0 ], path[1 ],
104- path[2 ], path[3 ], path[4 ], path[5 ], path[6 ], path[7 ]);
164+ const char *message = " ERROR: Path is too long: " ;
165+ WriteToFile (kStderrFd , message, internal_strlen (message));
166+ WriteToFile (kStderrFd , path, 8 );
167+ WriteToFile (kStderrFd , " \n " , internal_strlen (" \n " ));
105168 Die ();
106169 }
107170 }
@@ -115,7 +178,7 @@ void ReportFile::SetReportPath(const char *path) {
115178 } else if (internal_strcmp (path, " stdout" ) == 0 ) {
116179 fd = kStdoutFd ;
117180 } else {
118- internal_snprintf (path_prefix, kMaxPathLength , " %s " , path );
181+ ParseAndSetPath (path, path_prefix, kMaxPathLength );
119182 RecursiveCreateParentDirs (path_prefix);
120183 }
121184}
0 commit comments