Function: unsafep

unsafep is an autoloaded and byte-compiled function defined in unsafep.el.gz.

Signature

(unsafep FORM &optional VARS)

Documentation

Return nil if evaluating FORM couldn't possibly do any harm.

Otherwise result is a reason why FORM is unsafe. VARS is a list of symbols with local bindings like unsafep-vars.

View in manual

Probably introduced at or before Emacs version 22.1.

Source Code

;; Defined in /usr/src/emacs/lisp/emacs-lisp/unsafep.el.gz
;;;###autoload
(defun unsafep (form &optional vars)
  "Return nil if evaluating FORM couldn't possibly do any harm.
Otherwise result is a reason why FORM is unsafe.
VARS is a list of symbols with local bindings like `unsafep-vars'."
  (catch 'unsafep
    (if (or (eq safe-functions t)	    ;User turned off safety-checking
	    (atom form))		    ;Atoms are never unsafe
	(throw 'unsafep nil))
    (let* ((unsafep-vars vars)
	   (fun    (car form))
	   (reason (unsafep-function fun))
	   arg)
      (cond
       ((not reason)
	;;It's a normal function - unsafe if any arg is
	(unsafep-progn (cdr form)))
       ((eq fun 'quote)
	;;Never unsafe
	nil)
       ((memq fun '(apply mapc mapcar mapconcat))
	;;Unsafe if 1st arg isn't a quoted lambda
	(setq arg (cadr form))
	(cond
	 ((memq (car-safe arg) '(quote function))
	  (setq reason (unsafep-function (cadr arg))))
	 ((eq (car-safe arg) 'lambda)
	  ;;Self-quoting lambda
	  (setq reason (unsafep arg unsafep-vars)))
	 (t
	  (setq reason `(unquoted ,arg))))
	(or reason (unsafep-progn (cddr form))))
       ((eq fun 'lambda)
	;;First arg is temporary bindings
	(mapc #'(lambda (x)
		  (or (memq x '(&optional &rest))
		      (let ((y (unsafep-variable x t)))
			(if y (throw 'unsafep y))
			(push x unsafep-vars))))
	      (cadr form))
	(unsafep-progn (cddr form)))
       ((eq fun 'let)
	;;Creates temporary bindings in one step
	(setq unsafep-vars (nconc (mapcar #'unsafep-let (cadr form))
				  unsafep-vars))
	(unsafep-progn (cddr form)))
       ((eq fun 'let*)
	;;Creates temporary bindings iteratively
	(dolist (x (cadr form))
	  (push (unsafep-let x) unsafep-vars))
	(unsafep-progn (cddr form)))
       ((eq fun 'setq)
	;;Safe if odd arguments are local-var syms, evens are safe exprs
	(setq arg (cdr form))
	(while arg
	  (setq reason (or (unsafep-variable (car arg) nil)
			   (unsafep (cadr arg) unsafep-vars)))
	  (if reason (throw 'unsafep reason))
	  (setq arg (cddr arg))))
       ((eq fun 'pop)
	;;safe if arg is local-var sym
	(unsafep-variable (cadr form) nil))
       ((eq fun 'push)
	;;Safe if 2nd arg is a local-var sym
	(or (unsafep (cadr form) unsafep-vars)
	    (unsafep-variable (nth 2 form) nil)))
       ((eq fun 'add-to-list)
	;;Safe if first arg is a quoted local-var sym
	(setq arg (cadr form))
	(if (not (eq (car-safe arg) 'quote))
	    `(unquoted ,arg)
	  (or (unsafep-variable (cadr arg) nil)
	      (unsafep-progn (cddr form)))))
       ((eq fun 'cond)
	;;Special form with unusual syntax - safe if all args are
	(dolist (x (cdr form))
	  (setq reason (unsafep-progn x))
	  (if reason (throw 'unsafep reason))))
       ((memq fun '(dolist dotimes))
	;;Safe if COUNT and RESULT are safe.  VAR is bound while checking BODY.
	(setq arg (cadr form))
	(or (unsafep-progn (cdr arg))
	    (let ((unsafep-vars (cons (car arg) unsafep-vars)))
	      (unsafep-progn (cddr form)))))
       ((eq fun 'condition-case)
	;;Special form with unusual syntax - safe if all args are
	(or (unsafep-variable (cadr form) t)
	    (unsafep (nth 2 form) unsafep-vars)
	    (let ((unsafep-vars (cons (cadr form) unsafep-vars)))
	      ;;var is bound only during handlers
	      (dolist (x (nthcdr 3 form))
		(setq reason (unsafep-progn (cdr x)))
		(if reason (throw 'unsafep reason))))))
       ((eq fun '\`)
	;; Backquoted form - safe if its expansion is.
	(unsafep (cdr (backquote-process (cadr form)))))
       (t
	;;First unsafep-function call above wasn't nil, no special case applies
	reason)))))