summaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2023-05-12 19:54:47 -0700
committerKaz Kylheku <kaz@kylheku.com>2023-05-12 19:54:47 -0700
commit0cbf1af59cd18c389443d777db6f7e88f8522e52 (patch)
tree729aa6955e623211520b3fd3839e6be0a345b3e8 /eval.c
parenta018667b2a6754b24594857db1f8640d8db7eab0 (diff)
downloadtxr-0cbf1af59cd18c389443d777db6f7e88f8522e52.tar.gz
txr-0cbf1af59cd18c389443d777db6f7e88f8522e52.tar.bz2
txr-0cbf1af59cd18c389443d777db6f7e88f8522e52.zip
fix crash if built-in variable is unbound.
We use lookup_var_l in many places to look up the current dynamic value of a built-in variable such as *stdout*. Those places assume that a a valid location is returned which can be subject to a deref. If the application calls makunbound to remove such a variable, that deref will crash due to a null pointer dereference. Possible repro steps are numerous, possible for many variables. One example: (makunbound '*stdout*) (put-line) * eval.c (lookukp_var_l): If the binding is not found, do not return a nulloc, but throw an error exception.
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/eval.c b/eval.c
index ca9fe25d..0e247fda 100644
--- a/eval.c
+++ b/eval.c
@@ -588,7 +588,9 @@ val lookup_sym_lisp1(val env, val sym)
loc lookup_var_l(val env, val sym)
{
val binding = lookup_var(env, sym);
- return if3(binding, cdr_l(binding), nulloc);
+ if (binding)
+ return cdr_l(binding);
+ uw_throwf(error_s, lit("variable ~s unexpectedly unbound"), sym, nao);
}
static val lookup_mac(val menv, val sym);