Compare commits

..

6 Commits

Author SHA1 Message Date
Dianne Skoll
23081b556f Update WHATSNEW 2025-09-19 13:42:50 -04:00
Dianne Skoll
e2cfa46289 Update version to 06.01.02 2025-09-19 13:41:03 -04:00
Dianne Skoll
71384da875 Document default --max-expr-limit. 2025-09-19 13:39:55 -04:00
Dianne Skoll
af69f8779d Don't loop forever if a reminder moves backwards because of a time zone difference.
If we are not making progress, it's because the reminder has expired.
2025-09-19 13:33:23 -04:00
Dianne Skoll
131e77fa18 Use "unsigned long" to track expresison node evaluations. 2025-09-13 11:38:55 -04:00
Dianne Skoll
f153acf7ce Default max-expr-complexity to 10,000,000 2025-09-12 12:56:14 -04:00
11 changed files with 56 additions and 33 deletions

18
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.72 for remind 06.01.01. # Generated by GNU Autoconf 2.72 for remind 06.01.02.
# #
# #
# Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation, # Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation,
@@ -601,8 +601,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='remind' PACKAGE_NAME='remind'
PACKAGE_TARNAME='remind' PACKAGE_TARNAME='remind'
PACKAGE_VERSION='06.01.01' PACKAGE_VERSION='06.01.02'
PACKAGE_STRING='remind 06.01.01' PACKAGE_STRING='remind 06.01.02'
PACKAGE_BUGREPORT='' PACKAGE_BUGREPORT=''
PACKAGE_URL='https://dianne.skoll.ca/projects/remind/' PACKAGE_URL='https://dianne.skoll.ca/projects/remind/'
@@ -1258,7 +1258,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
'configure' configures remind 06.01.01 to adapt to many kinds of systems. 'configure' configures remind 06.01.02 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1320,7 +1320,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of remind 06.01.01:";; short | recursive ) echo "Configuration of remind 06.01.02:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@@ -1408,7 +1408,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
remind configure 06.01.01 remind configure 06.01.02
generated by GNU Autoconf 2.72 generated by GNU Autoconf 2.72
Copyright (C) 2023 Free Software Foundation, Inc. Copyright (C) 2023 Free Software Foundation, Inc.
@@ -1871,7 +1871,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by remind $as_me 06.01.01, which was It was created by remind $as_me 06.01.02, which was
generated by GNU Autoconf 2.72. Invocation command line was generated by GNU Autoconf 2.72. Invocation command line was
$ $0$ac_configure_args_raw $ $0$ac_configure_args_raw
@@ -4848,7 +4848,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by remind $as_me 06.01.01, which was This file was extended by remind $as_me 06.01.02, which was
generated by GNU Autoconf 2.72. Invocation command line was generated by GNU Autoconf 2.72. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@@ -4913,7 +4913,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped' ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\ ac_cs_version="\\
remind config.status 06.01.01 remind config.status 06.01.02
configured by $0, generated by GNU Autoconf 2.72, configured by $0, generated by GNU Autoconf 2.72,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"

View File

@@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
AC_INIT(remind, 06.01.01, , , https://dianne.skoll.ca/projects/remind/) AC_INIT(remind, 06.01.02, , , https://dianne.skoll.ca/projects/remind/)
AC_CONFIG_SRCDIR([src/queue.c]) AC_CONFIG_SRCDIR([src/queue.c])
cat <<'EOF' cat <<'EOF'

View File

@@ -1,5 +1,15 @@
CHANGES TO REMIND CHANGES TO REMIND
* VERSION 6.1 Patch 2 - 2025-09-19
- BUG FIX: remind: A reminder on a specific fixed date and time that
uses the TZ feature could erroneously issue a "Can't compute trigger"
error. This has been fixed.
- CHANGE: remind: The default for --max-expr-complexity is 10,000,000
(ten million) instead of unlimited. This should not affect any
real-world Remind scripts.
* VERSION 6.1 Patch 1 - 2025-09-12 * VERSION 6.1 Patch 1 - 2025-09-12
- NEW FEATURE: remind: Add the new --max-expr-complexity=n - NEW FEATURE: remind: Add the new --max-expr-complexity=n

View File

@@ -620,10 +620,10 @@ queued reminders, the time limit is reset to no limit.
Limit the total complexity of expression valuation for a given line in a script Limit the total complexity of expression valuation for a given line in a script
to \fIn\fR nodes. Roughly speaking, each function call, operator, constant, to \fIn\fR nodes. Roughly speaking, each function call, operator, constant,
variable reference, etc corresponds to one expression node. By default, variable reference, etc corresponds to one expression node. By default,
there's no limit to how many nodes can be evaluated per line, but if you the limit is set to 10000000 (ten million). You can explicitly set it
set this to a high number like 1000000 (one million) or so, you are unlikely to zero if you don't want any limit to apply. The default limit of ten
to cause problems with any real-world scripts while preventing pathological million should never be triggered by any sensible Remind script, however,
behavior from badly-written or malicious expressions. and we don't recommend changing the limit.
.TP .TP
.B \-\-test .B \-\-test
The \fB\-\-test\fR long option is only for use by the acceptance tests The \fB\-\-test\fR long option is only for use by the acceptance tests

View File

@@ -88,10 +88,10 @@ EXTERN INIT( int DeltaOverride, 0);
EXTERN INIT( int RunDisabled, 0); EXTERN INIT( int RunDisabled, 0);
EXTERN INIT( int ExpressionEvaluationDisabled, 0); EXTERN INIT( int ExpressionEvaluationDisabled, 0);
EXTERN INIT( int ExpressionEvaluationTimeLimit, 0); EXTERN INIT( int ExpressionEvaluationTimeLimit, 0);
EXTERN INIT( int ExpressionNodesEvaluated, 0); EXTERN INIT( unsigned long ExpressionNodesEvaluated, 0);
EXTERN INIT( int MaxExprNodesPerLine, 0); EXTERN INIT( unsigned long MaxExprNodesPerLine, 0);
EXTERN INIT( int ExpressionNodesEvaluatedThisLine, 0); EXTERN INIT( unsigned long ExpressionNodesEvaluatedThisLine, 0);
EXTERN INIT( int ExpressionNodeLimitPerLine, 0); EXTERN INIT( unsigned long ExpressionNodeLimitPerLine, 10000000);
EXTERN INIT( volatile sig_atomic_t ExpressionTimeLimitExceeded, 0); EXTERN INIT( volatile sig_atomic_t ExpressionTimeLimitExceeded, 0);
EXTERN INIT( int IgnoreOnce, 0); EXTERN INIT( int IgnoreOnce, 0);
EXTERN INIT( char const *OnceFile, NULL); EXTERN INIT( char const *OnceFile, NULL);

View File

@@ -1154,6 +1154,8 @@ static void
ProcessLongOption(char const *arg) ProcessLongOption(char const *arg)
{ {
int t; int t;
unsigned long tt;
if (!strcmp(arg, "test")) { if (!strcmp(arg, "test")) {
fprintf(stderr, "Enabling test mode: This is meant for the acceptance test.\nDo not use --test in production.\nIn test mode, the system time is fixed at 2025-01-06@19:00\n"); fprintf(stderr, "Enabling test mode: This is meant for the acceptance test.\nDo not use --test in production.\nIn test mode, the system time is fixed at 2025-01-06@19:00\n");
TestMode = 1; TestMode = 1;
@@ -1222,12 +1224,8 @@ ProcessLongOption(char const *arg)
print_sysvar_tokens(); print_sysvar_tokens();
exit(0); exit(0);
} }
if (sscanf(arg, "max-expr-complexity=%d", &t) == 1) { if (sscanf(arg, "max-expr-complexity=%lu", &tt) == 1) {
if (t < 0) { ExpressionNodeLimitPerLine = tt;
fprintf(ErrFp, "%s: --max-expr-complexity must be non-negative\n", ArgV[0]);
return;
}
ExpressionNodeLimitPerLine = t;
return; return;
} }
if (sscanf(arg, "max-execution-time=%d", &t) == 1) { if (sscanf(arg, "max-execution-time=%d", &t) == 1) {

View File

@@ -84,8 +84,8 @@ exitfunc(void)
UnsetAllUserFuncs(); UnsetAllUserFuncs();
print_expr_nodes_stats(); print_expr_nodes_stats();
fprintf(ErrFp, "Max expr node evaluations per line: %d\n", MaxExprNodesPerLine); fprintf(ErrFp, "Max expr node evaluations per line: %lu\n", MaxExprNodesPerLine);
fprintf(ErrFp, "Total expression node evaluations: %d\n", ExpressionNodesEvaluated); fprintf(ErrFp, "Total expression node evaluations: %lu\n", ExpressionNodesEvaluated);
} }
} }

View File

@@ -554,6 +554,7 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig const *tim
y, m, d, omit, y, m, d, omit,
result; result;
int save_nextstart = 0;
trig->expired = 0; trig->expired = 0;
if (save_in_globals) { if (save_in_globals) {
LastTrigValid = 0; LastTrigValid = 0;
@@ -617,14 +618,24 @@ int ComputeTriggerNoAdjustDuration(int today, Trigger *trig, TimeTrig const *tim
/** FIXME: If a timed reminder moves to yesterday because of a time /** FIXME: If a timed reminder moves to yesterday because of a time
zone adjustment, try again! */ zone adjustment, try again! */
if (trig->tz) { if (trig->tz) {
TimeTrig copy = *tim; TimeTrig copy = *tim;
int new_result; int new_result;
ExitTimezone(trig->tz); ExitTimezone(trig->tz);
new_result = AdjustTriggerForTimeZone(trig, result, &copy); new_result = AdjustTriggerForTimeZone(trig, result, &copy);
EnterTimezone(trig->tz); EnterTimezone(trig->tz);
if (new_result + duration_days < today) { if (result + duration_days >= today &&
new_result + duration_days < today) {
/* If we are not making progress, then give up: It's expired */
if (nextstart <= save_nextstart) {
trig->expired = 1;
if (DebugFlag & DB_PRTTRIG) {
fprintf(ErrFp, "%s(%s): %s\n",
GetCurrentFilename(), line_range(LineNoStart, LineNo), GetErr(E_EXPIRED));
}
return -1;
}
save_nextstart = nextstart;
nextstart = start+1; nextstart = start+1;
start = nextstart; start = nextstart;
continue; continue;

View File

@@ -161,6 +161,9 @@ debug -t
EOF EOF
TZ=America/Toronto $REMIND -s - 2025-09-01@00:00 <<'EOF' >> $OUT 2>&1
REM 2025-09-24 AT 09:00 TZ America/Denver MSG Dr. Smith
EOF
cmp -s $OUT $CMP cmp -s $OUT $CMP
if [ "$?" = "0" ] ; then if [ "$?" = "0" ] ; then
echo "Remind: Time zone test PASSED" echo "Remind: Time zone test PASSED"

View File

@@ -1045,7 +1045,7 @@ set a057 value("a05"+"6")
"a05" + "6" => "a056" "a05" + "6" => "a056"
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH" value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
set a058 version() set a058 version()
version() => "06.01.01" version() => "06.01.02"
set a059 wkday(today()) set a059 wkday(today())
today() => 1991-02-16 today() => 1991-02-16
wkday(1991-02-16) => "Saturday" wkday(1991-02-16) => "Saturday"
@@ -2608,7 +2608,7 @@ a056 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
a007 "1991-02-16" a007 "1991-02-16"
a057 "SDFJHSDF KSJDFH KJSDFH KSJDFH" a057 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
a008 "11:44" a008 "11:44"
a058 "06.01.01" a058 "06.01.02"
a059 "Saturday" a059 "Saturday"
a010 12 a010 12
a060 6 a060 6
@@ -5561,8 +5561,8 @@ REM SATISFY ""
REM SATISFY [version() > "01.00.00"] REM SATISFY [version() > "01.00.00"]
../tests/test.rem(1074): SATISFY: expression has no reference to trigdate() or $T... ../tests/test.rem(1074): SATISFY: expression has no reference to trigdate() or $T...
../tests/test.rem(1074): Trig = Saturday, 16 February, 1991 ../tests/test.rem(1074): Trig = Saturday, 16 February, 1991
version() => "06.01.01" version() => "06.01.02"
"06.01.01" > "01.00.00" => 1 "06.01.02" > "01.00.00" => 1
../tests/test.rem(1074): Trig(satisfied) = Saturday, 16 February, 1991 ../tests/test.rem(1074): Trig(satisfied) = Saturday, 16 February, 1991
REM SATISFY [max(x, max(x, 1, 2, 3), 4, 5, 6) * 5] REM SATISFY [max(x, max(x, 1, 2, 3), 4, 5, 6) * 5]
../tests/test.rem(1075): SATISFY: expression has no reference to trigdate() or $T... ../tests/test.rem(1075): SATISFY: expression has no reference to trigdate() or $T...
@@ -23715,7 +23715,7 @@ SECURITY: Won't read world-writable file or directory!
Error reading include_dir/ww: Can't open file Error reading include_dir/ww: Can't open file
SECURITY: Won't read world-writable file or directory! SECURITY: Won't read world-writable file or directory!
Error reading include_dir/ww: No files matching *.rem Error reading include_dir/ww: No files matching *.rem
06.01.01 06.01.02
Enabling test mode: This is meant for the acceptance test. Enabling test mode: This is meant for the acceptance test.
Do not use --test in production. Do not use --test in production.
In test mode, the system time is fixed at 2025-01-06@19:00 In test mode, the system time is fixed at 2025-01-06@19:00

View File

@@ -78,3 +78,4 @@ trig("Mon at 00:00 TZ Australia/Sydney", "Tue at 00:00 TZ America/Toronto", "Wed
-stdin-(14:21): Trig(tz_adj Australia/Sydney) = Saturday, 6 September, 2025 AT 10:00 -stdin-(14:21): Trig(tz_adj Australia/Sydney) = Saturday, 6 September, 2025 AT 10:00
-stdin-(14:21): Trig = Monday, 1 September, 2025 AT 14:42 -stdin-(14:21): Trig = Monday, 1 September, 2025 AT 14:42
2025-09-01 2025-09-01
2025/09/24 * * * 660 11:00am Dr. Smith