Skip to content

Commit eb5fcd3

Browse files
committed
Rewrite the line splitting logic to avoid stack buffers
The new logic reads the source buffer exactly once and moves the accumulated buffer in the dedicated buffer. This implementation avoids VLAs and instead uses a dedicated buffer allocated with xCalloc. The buffer is guaranteed to be at least 40 characters wide, meaning on narrow displays horizontal scrolling will be necessary. Doing so ensures a half-decent chance for arguments to fit fully in one line.
1 parent d2617e2 commit eb5fcd3

File tree

1 file changed

+26
-14
lines changed

1 file changed

+26
-14
lines changed

CommandScreen.c

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,33 @@ static void CommandScreen_scan(InfoScreen* this) {
2525
Panel_prune(panel);
2626

2727
const char* p = Process_getCommand(this->process);
28-
char line[COLS + 1];
29-
int line_offset = 0, last_spc = -1;
30-
for (; *p != '\0'; p++, line_offset++) {
31-
assert(line_offset >= 0 && (size_t)line_offset < sizeof(line));
32-
line[line_offset] = *p;
33-
if (*p == ' ') {
34-
last_spc = line_offset;
35-
}
3628

37-
if (line_offset == COLS) {
38-
int len = last_spc <= 0 ? line_offset : last_spc;
39-
line[len] = '\0';
29+
size_t line_maxlen = COLS < 40 ? 40 : COLS;
30+
size_t line_offset = 0;
31+
size_t last_space = 0;
32+
char* line = xCalloc(line_maxlen + 1, sizeof(char));
33+
34+
for (; *p != '\0'; p++) {
35+
if (line_offset >= line_maxlen) {
36+
assert(line_offset <= line_maxlen);
37+
assert(last_space <= line_maxlen);
38+
39+
size_t line_len = last_space <= 0 ? line_offset : last_space;
40+
char tmp = line[line_len];
41+
line[line_len] = '\0';
4042
InfoScreen_addLine(this, line);
43+
line[line_len] = tmp;
44+
45+
assert(line_len <= line_offset);
46+
line_offset -= line_len;
47+
memmove(line, line + line_len, line_offset);
4148

42-
line_offset -= len;
43-
last_spc = -1;
44-
memcpy(line, p - line_offset, line_offset + 1);
49+
last_space = 0;
50+
}
51+
52+
line[line_offset++] = *p;
53+
if (*p == ' ') {
54+
last_space = line_offset;
4555
}
4656
}
4757

@@ -50,6 +60,8 @@ static void CommandScreen_scan(InfoScreen* this) {
5060
InfoScreen_addLine(this, line);
5161
}
5262

63+
free(line);
64+
5365
Panel_setSelected(panel, idx);
5466
}
5567

0 commit comments

Comments
 (0)