diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2023-05-12 19:54:47 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2023-05-12 19:54:47 -0700 |
commit | 5162fde5237ce801f74e8db2bc680f72f00fb0ce (patch) | |
tree | 729aa6955e623211520b3fd3839e6be0a345b3e8 | |
parent | d4e7b8644f1824b268cb738d11cecba07b0bf9b2 (diff) | |
download | txr-5162fde5237ce801f74e8db2bc680f72f00fb0ce.tar.gz txr-5162fde5237ce801f74e8db2bc680f72f00fb0ce.tar.bz2 txr-5162fde5237ce801f74e8db2bc680f72f00fb0ce.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.
-rw-r--r-- | eval.c | 4 |
1 files changed, 3 insertions, 1 deletions
@@ -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); |