Skip to content

Commit bfb93cd

Browse files
committed
Processing (Linux): enhances robustness when extracting process name and related fields
... by accurately handling process names with spaces or special characters.
1 parent 0998b1e commit bfb93cd

File tree

1 file changed

+36
-33
lines changed

1 file changed

+36
-33
lines changed

src/common/processing_linux.c

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -439,57 +439,60 @@ const char* ffProcessGetBasicInfoLinux(pid_t pid, FFstrbuf* name, pid_t* ppid, i
439439
#if defined(__linux__) || defined(__GNU__)
440440

441441
char procFilePath[64];
442-
if (ppid)
442+
#if __linux__
443+
if (ppid || tty)
444+
#endif
443445
{
444446
snprintf(procFilePath, sizeof(procFilePath), "/proc/%d/stat", (int)pid);
445447
char buf[PROC_FILE_BUFFSIZ];
446448
ssize_t nRead = ffReadFileData(procFilePath, sizeof(buf) - 1, buf);
447449
if(nRead <= 8)
448450
return "ffReadFileData(/proc/pid/stat, PROC_FILE_BUFFSIZ-1, buf) failed";
449-
buf[nRead] = '\0';
451+
buf[nRead] = '\0'; // pid (comm) state ppid pgrp session tty
450452

451-
*ppid = 0;
452-
static_assert(sizeof(*ppid) == sizeof(int), "");
453+
const char* pState = NULL;
453454

454-
ffStrbufEnsureFixedLengthFree(name, 255);
455-
int tty_;
456-
if(
457-
sscanf(buf, "%*s (%255[^)]) %*c %d %*d %*d %d", name->chars, ppid, &tty_) < 2 || //stat (comm) state ppid pgrp session tty
458-
name->chars[0] == '\0'
459-
)
460-
return "sscanf(stat) failed";
455+
{
456+
// comm in `/proc/pid/stat` is not encoded, and may contain ' ', ')' or even `\n`
457+
const char* start = memchr(buf, '(', (size_t) nRead);
458+
if (!start)
459+
return "memchr(stat, '(') failed";
460+
start++;
461+
const char* end = memrchr(start, ')', (size_t) nRead - (size_t) (start - buf));
462+
if (!end)
463+
return "memrchr(stat, ')') failed";
464+
ffStrbufSetNS(name, (uint32_t) (end - start), start);
465+
ffStrbufTrimRightSpace(name);
466+
pState = end + 2; // skip ") "
467+
}
461468

462-
ffStrbufRecalculateLength(name);
463-
if (tty)
464-
*tty = tty_ & 0xFF;
469+
#if !__linux__
470+
if (ppid || tty)
471+
#endif
472+
{
473+
int ppid_, tty_;
474+
if(
475+
sscanf(pState + 2, "%d %*d %*d %d", &ppid_, &tty_) < 2 ||
476+
name->chars[0] == '\0'
477+
)
478+
return "sscanf(stat) failed";
479+
480+
if (ppid)
481+
*ppid = (pid_t) ppid_;
482+
if (tty)
483+
*tty = tty_ & 0xFF;
484+
}
465485
}
486+
#if __linux__
466487
else
467488
{
468-
#ifndef __GNU__
469489
snprintf(procFilePath, sizeof(procFilePath), "/proc/%d/comm", (int)pid);
470490
ssize_t nRead = ffReadFileBuffer(procFilePath, name);
471491
if(nRead <= 0)
472492
return "ffReadFileBuffer(/proc/pid/comm, name) failed";
473493
ffStrbufTrimRightSpace(name);
474-
#else
475-
// No /proc/1/comm on Hurd so read /proc/1/stat again
476-
snprintf(procFilePath, sizeof(procFilePath), "/proc/%d/stat", (int)pid);
477-
char buf[PROC_FILE_BUFFSIZ];
478-
ssize_t nRead = ffReadFileData(procFilePath, sizeof(buf) - 1, buf);
479-
if(nRead <= 8)
480-
return "ffReadFileData(/proc/pid/stat, PROC_FILE_BUFFSIZ-1, buf) failed";
481-
buf[nRead] = '\0';
482-
483-
const char* start = memchr(buf, '(', (size_t) nRead);
484-
if (!start)
485-
return "memchr(stat, '(') failed";
486-
start++;
487-
const char* end = memchr(start, ')', (size_t) nRead - (size_t) (start - buf));
488-
if (!end)
489-
return "memchr(stat, ')') failed";
490-
ffStrbufSetNS(name, (uint32_t) (end - start), start);
491-
#endif
492494
}
495+
#endif
493496

494497
#elif defined(__APPLE__)
495498

0 commit comments

Comments
 (0)