Add $ExpressionTimeLimit system variable.

This commit is contained in:
Dianne Skoll
2024-06-02 14:01:17 -04:00
parent fafb30db05
commit a8bfb41a9e
9 changed files with 74 additions and 21 deletions

View File

@@ -1314,7 +1314,7 @@ int DoSatRemind(Trigger *trig, TimeTrig *tt, ParsePtr p)
free_expr_tree(sat_node);
return E_EXPIRED;
}
r = evaluate_expr_node(sat_node, NULL, &v, &nonconst);
r = evaluate_expression(sat_node, NULL, &v, &nonconst);
if (r) {
free_expr_tree(sat_node);
return r;

View File

@@ -124,6 +124,7 @@
#define E_EXPECTING_WEEKDAY 104
#define E_REPEATED_ARG 105
#define E_EXPR_DISABLED 106
#define E_TIME_EXCEEDED 107
#ifdef MK_GLOBALS
#undef EXTERN
@@ -248,7 +249,8 @@ EXTERN char *ErrMsg[]
/* E_DURATION_NO_AT */ "Cannot specify DURATION without specifying AT",
/* E_EXPECTING_WEEKDAY */ "Expecting weekday name",
/* E_REPEATED_ARG */ "Duplicate argument name",
/* E_EXPR_DISABLED */ "Expression evaluation is disabled"
/* E_EXPR_DISABLED */ "Expression evaluation is disabled",
/* E_TIME_EXCEEDED */ "Time limit for expression evaluation exceeded",
}
#endif /* MK_GLOBALS */
;

View File

@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
/*
The parser parses expressions into an internal tree
@@ -662,6 +663,21 @@ eval_userfunc(expr_node *node, Value *locals, Value *ans, int *nonconst)
return r;
}
int
evaluate_expression(expr_node *node, Value *locals, Value *ans, int *nonconst)
{
int r;
/* Set up time limits */
if (ExpressionEvaluationTimeLimit > 0) {
ExpressionTimeLimitExceeded = 0;
alarm(ExpressionEvaluationTimeLimit);
}
r = evaluate_expr_node(node, locals, ans, nonconst);
alarm(0);
return r;
}
/***************************************************************/
/* */
/* evaluate_expr_node - the top-level expression evaluation */
@@ -691,6 +707,10 @@ evaluate_expr_node(expr_node *node, Value *locals, Value *ans, int *nonconst)
return E_EXPR_DISABLED;
}
if (ExpressionTimeLimitExceeded) {
ExpressionTimeLimitExceeded = 0;
return E_TIME_EXCEEDED;
}
if (!node) {
return E_SWERR;
}
@@ -2370,7 +2390,7 @@ int EvalExpr(char const **e, Value *v, ParsePtr p)
}
/* Evaluate */
r = evaluate_expr_node(n, NULL, v, &nonconst);
r = evaluate_expression(n, NULL, v, &nonconst);
/* Throw away the parsed tree */
free_expr_tree(n);

View File

@@ -23,6 +23,7 @@
#define INIT(var, val) var
#endif
#include <signal.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@@ -74,6 +75,8 @@ EXTERN INIT( int DefaultTDelta, 0);
EXTERN INIT( int DeltaOverride, 0);
EXTERN INIT( int RunDisabled, 0);
EXTERN INIT( int ExpressionEvaluationDisabled, 0);
EXTERN INIT( int ExpressionEvaluationTimeLimit, 0);
EXTERN INIT( volatile sig_atomic_t ExpressionTimeLimitExceeded, 0);
EXTERN INIT( int IgnoreOnce, 0);
EXTERN INIT( int SortByTime, 0);
EXTERN INIT( int SortByDate, 0);

View File

@@ -30,7 +30,6 @@
#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <signal.h>
#ifdef HAVE_INITGROUPS
#include <grp.h>
@@ -1014,30 +1013,14 @@ AddTrustedUser(char const *username)
TrustedUsers[NumTrustedUsers] = pwent->pw_uid;
NumTrustedUsers++;
}
static void
sigalarm(int)
{
write(STDOUT_FILENO, "\nExecution time exceeded.\n", 26);
exit(1);
}
static void
ProcessLongOption(char const *arg)
{
int t;
if (!strcmp(arg, "version")) {
printf("%s\n", VERSION);
exit(EXIT_SUCCESS);
}
if (sscanf(arg, "max-execution-time=%d", &t) == 1) {
if (t <= 0) {
fprintf(ErrFp, "%s: Value of --max-execution-time must be positive\n", ArgV[0]);
return;
}
signal(SIGALRM, sigalarm);
alarm(t);
return;
}
fprintf(ErrFp, "%s: Unknown long option --%s\n", ArgV[0], arg);
}

View File

@@ -67,6 +67,13 @@ exitfunc(void)
fflush(stderr);
}
static void sigalrm(int)
{
if (ExpressionEvaluationTimeLimit) {
ExpressionTimeLimitExceeded = 1;
}
}
/***************************************************************/
/***************************************************************/
/** **/
@@ -78,6 +85,8 @@ int main(int argc, char *argv[])
{
int pid;
struct sigaction act;
#ifdef HAVE_SETLOCALE
setlocale(LC_ALL, "");
#endif
@@ -90,6 +99,15 @@ int main(int argc, char *argv[])
ArgV = (char const **) argv;
InitRemind(argc, (char const **) argv);
act.sa_handler = sigalrm;
sigemptyset(&act.sa_mask);
if (sigaction(SIGALRM, &act, NULL) < 0) {
fprintf(stderr, "%s: sigaction() failed: %s\n",
argv[0], strerror(errno));
exit(1);
}
DBufInit(&(LastTrigger.tags));
ClearLastTriggers();
@@ -676,7 +694,7 @@ int EvaluateExpr(ParsePtr p, Value *v)
return E_SWERR;
}
r = evaluate_expr_node(node, NULL, v, &nonconst);
r = evaluate_expression(node, NULL, v, &nonconst);
free_expr_tree(node);
if (r) return r;
if (nonconst) {

View File

@@ -59,6 +59,7 @@ int ParseLiteralDate (char const **s, int *dse, int *tim);
int ParseLiteralTime (char const **s, int *tim);
expr_node *parse_expression(char const **e, int *r, Var *locals);
int evaluate_expression(expr_node *node, Value *locals, Value *ans, int *nonconst);
int evaluate_expr_node(expr_node *node, Value *locals, Value *ans, int *nonconst);
void print_expr_tree(expr_node *node, FILE *fp);
expr_node *free_expr_tree(expr_node *node);

View File

@@ -310,6 +310,9 @@ void HandleQueuedReminders(void)
struct sigaction sa;
char qid[64];
/* Disable any potential pending SIGALRMs */
alarm(0);
/* Turn off sorting -- otherwise, TriggerReminder has no effect! */
SortByDate = 0;

View File

@@ -319,6 +319,28 @@ static int datetime_sep_func(int do_set, Value *val)
return OK;
}
static int expr_time_limit_func(int do_set, Value *val)
{
if (!do_set) {
val->type = INT_TYPE;
val->v.val = ExpressionEvaluationTimeLimit;
return OK;
}
if (val->type != INT_TYPE) return E_BAD_TYPE;
if (val->v.val < 0) return E_2LOW;
if (!TopLevel()) {
/* Ignore attempts to set from non-toplevel unless it's
lower than current value */
if (val->v.val <= ExpressionEvaluationTimeLimit) {
return OK;
}
}
ExpressionEvaluationTimeLimit = val->v.val;
return OK;
}
static int default_color_func(int do_set, Value *val)
{
int col_r, col_g, col_b;
@@ -808,6 +830,7 @@ static SysVar SysVarArr[] = {
{"DontTrigAts", 0, INT_TYPE, &DontIssueAts, 0, 0 },
{"EndSent", 1, STR_TYPE, &EndSent, 0, 0 },
{"EndSentIg", 1, STR_TYPE, &EndSentIg, 0, 0 },
{"ExpressionTimeLimit", 1, SPECIAL_TYPE, expr_time_limit_func, 0, 0 },
{"February", 1, STR_TYPE, &DynamicMonthName[1], 0, 0 },
{"FirstIndent", 1, INT_TYPE, &FirstIndent, 0, 132 },
{"FoldYear", 1, INT_TYPE, &FoldYear, 0, 1 },