mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-24 22:40:51 -08:00
Don’t hard-loop on cycles in ‘read’ etc.
Problem for ‘read’ reported by Pip Cet in: https://lists.gnu.org/r/emacs-devel/2019-08/msg00316.html * src/fns.c (Frequire): Protect against circular current-load-list. * src/lread.c (Fget_load_suffixes): Protect against circular load-suffixes or load-file-rep-suffixes. (Fload): Protect against circular loads-in-progress. (openp): Protect against circular PATH and SUFFIXES. (build_load_history): Protect against circular load-history or current-load-list. (readevalloop_eager_expand_eval): Protect against circular SUBFORMS. (read1): Protect against circular data. * test/src/lread-tests.el (lread-circular-hash): New test.
This commit is contained in:
parent
11de1155f8
commit
951ea375d5
3 changed files with 43 additions and 37 deletions
|
|
@ -2950,9 +2950,12 @@ suppressed. */)
|
|||
But not more than once in any file,
|
||||
and not when we aren't loading or reading from a file. */
|
||||
if (!from_file)
|
||||
for (tem = Vcurrent_load_list; CONSP (tem); tem = XCDR (tem))
|
||||
if (NILP (XCDR (tem)) && STRINGP (XCAR (tem)))
|
||||
from_file = 1;
|
||||
{
|
||||
Lisp_Object tail = Vcurrent_load_list;
|
||||
FOR_EACH_TAIL_SAFE (tail)
|
||||
if (NILP (XCDR (tail)) && STRINGP (XCAR (tail)))
|
||||
from_file = true;
|
||||
}
|
||||
|
||||
if (from_file)
|
||||
{
|
||||
|
|
|
|||
68
src/lread.c
68
src/lread.c
|
|
@ -1064,18 +1064,13 @@ required.
|
|||
This uses the variables `load-suffixes' and `load-file-rep-suffixes'. */)
|
||||
(void)
|
||||
{
|
||||
Lisp_Object lst = Qnil, suffixes = Vload_suffixes, suffix, ext;
|
||||
while (CONSP (suffixes))
|
||||
Lisp_Object lst = Qnil, suffixes = Vload_suffixes;
|
||||
FOR_EACH_TAIL (suffixes)
|
||||
{
|
||||
Lisp_Object exts = Vload_file_rep_suffixes;
|
||||
suffix = XCAR (suffixes);
|
||||
suffixes = XCDR (suffixes);
|
||||
while (CONSP (exts))
|
||||
{
|
||||
ext = XCAR (exts);
|
||||
exts = XCDR (exts);
|
||||
lst = Fcons (concat2 (suffix, ext), lst);
|
||||
}
|
||||
Lisp_Object suffix = XCAR (suffixes);
|
||||
FOR_EACH_TAIL (exts)
|
||||
lst = Fcons (concat2 (suffix, XCAR (exts)), lst);
|
||||
}
|
||||
return Fnreverse (lst);
|
||||
}
|
||||
|
|
@ -1290,8 +1285,8 @@ Return t if the file exists and loads successfully. */)
|
|||
the general case; the second load may do something different. */
|
||||
{
|
||||
int load_count = 0;
|
||||
Lisp_Object tem;
|
||||
for (tem = Vloads_in_progress; CONSP (tem); tem = XCDR (tem))
|
||||
Lisp_Object tem = Vloads_in_progress;
|
||||
FOR_EACH_TAIL_SAFE (tem)
|
||||
if (!NILP (Fequal (found, XCAR (tem))) && (++load_count > 3))
|
||||
signal_error ("Recursive load", Fcons (found, Vloads_in_progress));
|
||||
record_unwind_protect (record_load_unwind, Vloads_in_progress);
|
||||
|
|
@ -1611,7 +1606,8 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
|
|||
|
||||
CHECK_STRING (str);
|
||||
|
||||
for (tail = suffixes; CONSP (tail); tail = XCDR (tail))
|
||||
tail = suffixes;
|
||||
FOR_EACH_TAIL_SAFE (tail)
|
||||
{
|
||||
CHECK_STRING_CAR (tail);
|
||||
max_suffix_len = max (max_suffix_len,
|
||||
|
|
@ -1625,12 +1621,17 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
|
|||
|
||||
absolute = complete_filename_p (str);
|
||||
|
||||
AUTO_LIST1 (just_use_str, Qnil);
|
||||
if (NILP (path))
|
||||
path = just_use_str;
|
||||
|
||||
/* Go through all entries in the path and see whether we find the
|
||||
executable. */
|
||||
do {
|
||||
FOR_EACH_TAIL_SAFE (path)
|
||||
{
|
||||
ptrdiff_t baselen, prefixlen;
|
||||
|
||||
if (NILP (path))
|
||||
if (EQ (path, just_use_str))
|
||||
filename = str;
|
||||
else
|
||||
filename = Fexpand_file_name (str, XCAR (path));
|
||||
|
|
@ -1663,8 +1664,9 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
|
|||
memcpy (fn, SDATA (filename) + prefixlen, baselen);
|
||||
|
||||
/* Loop over suffixes. */
|
||||
for (tail = NILP (suffixes) ? list1 (empty_unibyte_string) : suffixes;
|
||||
CONSP (tail); tail = XCDR (tail))
|
||||
AUTO_LIST1 (empty_string_only, empty_unibyte_string);
|
||||
tail = NILP (suffixes) ? empty_string_only : suffixes;
|
||||
FOR_EACH_TAIL_SAFE (tail)
|
||||
{
|
||||
Lisp_Object suffix = XCAR (tail);
|
||||
ptrdiff_t fnlen, lsuffix = SBYTES (suffix);
|
||||
|
|
@ -1808,10 +1810,9 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (absolute || NILP (path))
|
||||
if (absolute)
|
||||
break;
|
||||
path = XCDR (path);
|
||||
} while (CONSP (path));
|
||||
}
|
||||
|
||||
SAFE_FREE ();
|
||||
errno = last_errno;
|
||||
|
|
@ -1838,7 +1839,7 @@ build_load_history (Lisp_Object filename, bool entire)
|
|||
tail = Vload_history;
|
||||
prev = Qnil;
|
||||
|
||||
while (CONSP (tail))
|
||||
FOR_EACH_TAIL (tail)
|
||||
{
|
||||
tem = XCAR (tail);
|
||||
|
||||
|
|
@ -1861,22 +1862,19 @@ build_load_history (Lisp_Object filename, bool entire)
|
|||
{
|
||||
tem2 = Vcurrent_load_list;
|
||||
|
||||
while (CONSP (tem2))
|
||||
FOR_EACH_TAIL (tem2)
|
||||
{
|
||||
newelt = XCAR (tem2);
|
||||
|
||||
if (NILP (Fmember (newelt, tem)))
|
||||
Fsetcar (tail, Fcons (XCAR (tem),
|
||||
Fcons (newelt, XCDR (tem))));
|
||||
|
||||
tem2 = XCDR (tem2);
|
||||
maybe_quit ();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
prev = tail;
|
||||
tail = XCDR (tail);
|
||||
maybe_quit ();
|
||||
}
|
||||
|
||||
|
|
@ -1918,10 +1916,9 @@ readevalloop_eager_expand_eval (Lisp_Object val, Lisp_Object macroexpand)
|
|||
if (EQ (CAR_SAFE (val), Qprogn))
|
||||
{
|
||||
Lisp_Object subforms = XCDR (val);
|
||||
|
||||
for (val = Qnil; CONSP (subforms); subforms = XCDR (subforms))
|
||||
val = readevalloop_eager_expand_eval (XCAR (subforms),
|
||||
macroexpand);
|
||||
val = Qnil;
|
||||
FOR_EACH_TAIL (subforms)
|
||||
val = readevalloop_eager_expand_eval (XCAR (subforms), macroexpand);
|
||||
}
|
||||
else
|
||||
val = eval_sub (call2 (macroexpand, val, Qt));
|
||||
|
|
@ -2861,16 +2858,19 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
|
|||
/* Now use params to make a new hash table and fill it. */
|
||||
ht = Fmake_hash_table (param_count, params);
|
||||
|
||||
while (CONSP (data))
|
||||
{
|
||||
Lisp_Object last = data;
|
||||
FOR_EACH_TAIL_SAFE (data)
|
||||
{
|
||||
key = XCAR (data);
|
||||
data = XCDR (data);
|
||||
if (!CONSP (data))
|
||||
error ("Odd number of elements in hash table data");
|
||||
break;
|
||||
val = XCAR (data);
|
||||
data = XCDR (data);
|
||||
last = XCDR (data);
|
||||
Fputhash (key, val, ht);
|
||||
}
|
||||
}
|
||||
if (!NILP (last))
|
||||
error ("Hash table data is not a list of even length");
|
||||
|
||||
return ht;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,4 +220,7 @@ literals (Bug#20852)."
|
|||
(* most-positive-fixnum most-positive-fixnum)))
|
||||
(should (= n (string-to-number (format "%d." n))))))
|
||||
|
||||
(ert-deftest lread-circular-hash ()
|
||||
(should-error (read "#s(hash-table data #0=(#0# . #0#))")))
|
||||
|
||||
;;; lread-tests.el ends here
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue