Add a fairly low time limit to format evaluation to stop absurdly nested

formats from making tmux appear to hang.
This commit is contained in:
nicm
2026-04-22 07:05:03 +00:00
parent 314f0ae964
commit 303edb71bd

View File

@@ -120,6 +120,9 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
/* Limit on recursion. */ /* Limit on recursion. */
#define FORMAT_LOOP_LIMIT 100 #define FORMAT_LOOP_LIMIT 100
/* Limit on time taken (milliseconds). */
#define FORMAT_TIME_LIMIT 100
/* Format expand flags. */ /* Format expand flags. */
#define FORMAT_EXPAND_TIME 0x1 #define FORMAT_EXPAND_TIME 0x1
#define FORMAT_EXPAND_NOJOBS 0x2 #define FORMAT_EXPAND_NOJOBS 0x2
@@ -169,9 +172,11 @@ RB_GENERATE_STATIC(format_entry_tree, format_entry, entry, format_entry_cmp);
struct format_expand_state { struct format_expand_state {
struct format_tree *ft; struct format_tree *ft;
u_int loop; u_int loop;
uint64_t start_time;
int flags;
time_t time; time_t time;
struct tm tm; struct tm tm;
int flags;
}; };
/* Format modifier. */ /* Format modifier. */
@@ -292,6 +297,7 @@ format_copy_state(struct format_expand_state *to,
to->time = from->time; to->time = from->time;
memcpy(&to->tm, &from->tm, sizeof to->tm); memcpy(&to->tm, &from->tm, sizeof to->tm);
to->flags = from->flags|flags; to->flags = from->flags|flags;
to->start_time = from->start_time;
} }
/* Format job update callback. */ /* Format job update callback. */
@@ -5514,10 +5520,16 @@ format_expand1(struct format_expand_state *es, const char *fmt)
size_t off, len, n, outlen; size_t off, len, n, outlen;
int ch, brackets; int ch, brackets;
char expanded[8192]; char expanded[8192];
uint64_t t = get_timer();
if (fmt == NULL || *fmt == '\0') if (fmt == NULL || *fmt == '\0')
return (xstrdup("")); return (xstrdup(""));
if (t - es->start_time >= FORMAT_TIME_LIMIT) {
format_log(es, "reached time limit (%llu)",
(unsigned long long)(t - es->start_time));
return (xstrdup(""));
}
if (es->loop == FORMAT_LOOP_LIMIT) { if (es->loop == FORMAT_LOOP_LIMIT) {
format_log(es, "reached loop limit (%u)", FORMAT_LOOP_LIMIT); format_log(es, "reached loop limit (%u)", FORMAT_LOOP_LIMIT);
return (xstrdup("")); return (xstrdup(""));
@@ -5683,6 +5695,7 @@ format_expand_time(struct format_tree *ft, const char *fmt)
memset(&es, 0, sizeof es); memset(&es, 0, sizeof es);
es.ft = ft; es.ft = ft;
es.flags = FORMAT_EXPAND_TIME; es.flags = FORMAT_EXPAND_TIME;
es.start_time = get_timer();
return (format_expand1(&es, fmt)); return (format_expand1(&es, fmt));
} }
@@ -5695,6 +5708,7 @@ format_expand(struct format_tree *ft, const char *fmt)
memset(&es, 0, sizeof es); memset(&es, 0, sizeof es);
es.ft = ft; es.ft = ft;
es.flags = 0; es.flags = 0;
es.start_time = get_timer();
return (format_expand1(&es, fmt)); return (format_expand1(&es, fmt));
} }