@@ -178,7 +178,16 @@ static int spt_copyargs(int argc, char *argv[]) {
178178 return 0 ;
179179} /* spt_copyargs() */
180180
181-
181+ /* Initialize and populate SPT to allow a future setproctitle()
182+ * call.
183+ *
184+ * As setproctitle() basically needs to overwrite argv[0], we're
185+ * trying to determine what is the largest contiguous block
186+ * starting at argv[0] we can use for this purpose.
187+ *
188+ * As this range will overwrite some or all of the argv and environ
189+ * strings, a deep copy of these two arrays is performed.
190+ */
182191void spt_init (int argc , char * argv []) {
183192 char * * envp = environ ;
184193 char * base , * end , * nul , * tmp ;
@@ -187,24 +196,39 @@ void spt_init(int argc, char *argv[]) {
187196 if (!(base = argv [0 ]))
188197 return ;
189198
199+ /* We start with end pointing at the end of argv[0] */
190200 nul = & base [strlen (base )];
191201 end = nul + 1 ;
192202
203+ /* Attempt to extend end as far as we can, while making sure
204+ * that the range between base and end is only allocated to
205+ * argv, or anything that immediately follows argv (presumably
206+ * envp).
207+ */
193208 for (i = 0 ; i < argc || (i >= argc && argv [i ]); i ++ ) {
194209 if (!argv [i ] || argv [i ] < end )
195210 continue ;
196211
197- end = argv [i ] + strlen (argv [i ]) + 1 ;
212+ if (end >= argv [i ] && end <= argv [i ] + strlen (argv [i ]))
213+ end = argv [i ] + strlen (argv [i ]) + 1 ;
198214 }
199215
216+ /* In case the envp array was not an immediate extension to argv,
217+ * scan it explicitly.
218+ */
200219 for (i = 0 ; envp [i ]; i ++ ) {
201220 if (envp [i ] < end )
202221 continue ;
203222
204- end = envp [i ] + strlen (envp [i ]) + 1 ;
223+ if (end >= envp [i ] && end <= envp [i ] + strlen (envp [i ]))
224+ end = envp [i ] + strlen (envp [i ]) + 1 ;
205225 }
206226 envc = i ;
207227
228+ /* We're going to deep copy argv[], but argv[0] will still point to
229+ * the old memory for the purpose of updating the title so we need
230+ * to keep the original value elsewhere.
231+ */
208232 if (!(SPT .arg0 = strdup (argv [0 ])))
209233 goto syerr ;
210234
@@ -225,7 +249,7 @@ void spt_init(int argc, char *argv[]) {
225249 setprogname (tmp );
226250#endif
227251
228-
252+ /* Now make a full deep copy of the environment and argv[] */
229253 if ((error = spt_copyenv (envc , envp )))
230254 goto error ;
231255
@@ -294,3 +318,14 @@ void setproctitle(const char *fmt, ...) {
294318
295319#endif /* __linux || __APPLE__ */
296320#endif /* !HAVE_SETPROCTITLE */
321+
322+ #ifdef SETPROCTITLE_TEST_MAIN
323+ int main (int argc , char * argv []) {
324+ spt_init (argc , argv );
325+
326+ printf ("SPT.arg0: [%p] '%s'\n" , SPT .arg0 , SPT .arg0 );
327+ printf ("SPT.base: [%p] '%s'\n" , SPT .base , SPT .base );
328+ printf ("SPT.end: [%p] (%d bytes after base)'\n" , SPT .end , (int ) (SPT .end - SPT .base ));
329+ return 0 ;
330+ }
331+ #endif
0 commit comments