From: Juan Pablo Hierro Álvarez
Subject: How to eval a function from a string with its name?
Date: 
Message-ID: <slrn9iuoil.5gd.hierro@otilio.cps.unizar.es>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Let us say there is a (defun foo () 'a)
and there is also a (setq *name* "foo")

Is there any way to evaluate the function when only *name* is known?

I am thinking of a shell script with the name of the file to be loaded as
a first argument (no problems with a string) and the name of the function
to be evaluated as a second argument (it is passed as a string, too!).
___
······@ideafix.litec.csic.es
Public key: A8707ADF at pgp.rediris.es
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.4 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iEYEARECAAYFAjsvYl0ACgkQd1aMoahwet9zsQCgkH4aa/2dKrLe6l8RMvvB4SGc
BawAnidrxxdqPIX3Y8EKF11jxxsCzdKo
=TOi7
-----END PGP SIGNATURE-----

From: Jose Carlos Senciales
Subject: Re: How to eval a function from a string with its name?
Date: 
Message-ID: <3B2F68D1.7B9344FD@lcc.uma.es>
Juan Pablo Hierro �lvarez wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Let us say there is a (defun foo () 'a)
> and there is also a (setq *name* "foo")
>
> Is there any way to evaluate the function when only *name* is known?
>
> I am thinking of a shell script with the name of the file to be loaded as
> a first argument (no problems with a string) and the name of the function
> to be evaluated as a second argument (it is passed as a string, too!).
> ___
> ······@ideafix.litec.csic.es
> Public key: A8707ADF at pgp.rediris.es
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.0.4 (GNU/Linux)
> Comment: For info see http://www.gnupg.org
>
> iEYEARECAAYFAjsvYl0ACgkQd1aMoahwet9zsQCgkH4aa/2dKrLe6l8RMvvB4SGc
> BawAnidrxxdqPIX3Y8EKF11jxxsCzdKo
> =TOi7
> -----END PGP SIGNATURE-----

hello , you can do this, for example:

CL-USER 1 > (defun foo (x y) (+ x y))
FOO

CL-USER 2 > (setf a "foo")
"foo"

CL-USER 3 > (funcall (read-from-string a) 1 2)
3

bye.. :-)

--
*

          *                *

*
-------------------------------------------------------
              Jos� Carlos Senciales Chaves
(reverse (concatenate 'string ···········@" "nescoj"))
-------------------------------------------------------
From: Kent M Pitman
Subject: Re: How to eval a function from a string with its name?
Date: 
Message-ID: <sfwk828lacz.fsf@world.std.com>
Jose Carlos Senciales <······@lcc.uma.es> writes:

> Juan Pablo Hierro �lvarez wrote:
> 
> > Let us say there is a (defun foo () 'a)
> > and there is also a (setq *name* "foo")
> >
> > Is there any way to evaluate the function when only *name* is known?
> >
> > I am thinking of a shell script with the name of the file to be loaded as
> > a first argument (no problems with a string) and the name of the function
> > to be evaluated as a second argument (it is passed as a string, too!).
> > ___
>
> hello , you can do this, for example:
> 
> CL-USER 1 > (defun foo (x y) (+ x y))
> FOO
> 
> CL-USER 2 > (setf a "foo")
> "foo"
> 
> CL-USER 3 > (funcall (read-from-string a) 1 2)
> 3

The thing to know is that READ-FROM-STRING can be made to construct an
arbitrary form, allowing trojan horses.  You may want to only accept 
symbols.

One additional piece of information to know is that the Lisp reader will,
by default, upcase your symbols in the reader.  So
 (defun foo () 'a)
is the same as
 (DEFUN FOO () 'A)
and the name stored is "FOO", not "foo".  You can cause lowercase to be
preserved in various ways, such as by prefixing \ before a character whose
case is to be preserved or using |...| around a set of characters whose
case is to be preserved.  So \f\o\o and |foo| both refer to the symbol
"foo" while foo and Foo and FOO all refer to the symbol named "FOO" because
unescaped names get uppercased by the reader.

Given this knowledge, you might want to say:

 (defun foo (x y) (+ x y))

 (defun \f\o\o (x y) (* x y))

 (defun call-named-function (function-name &rest args)
   (apply (intern function-name) args))

 (call-named-function "FOO" 3 4)
 => 7

 (call-named-function "foo" 3 4)
 => 12

or you might want to make your command system also be case-translating, 
so that

 (defun call-named-function (function-name &rest args)
   (apply (intern (string-upcase function-name)) args))

 (call-named-function 'foo 3 4)
 => 7

 (call-named-function "FOO" 3 4)
 => 7

 (call-named-function "foo" 3 4)
 => 7

 (call-named-function '|foo| 3 4)
 => 7
        
 (call-named-function '\f\o\o 3 4)
 => 7

or you might want to make your command system be provisionally 
case-translating only in certain situations. e.g.,

 (defun call-named-function (function-name &rest args)
   (apply (etypecase function-name
            (string (intern (string-upcase function-name)))
	    (symbol function-name))
          args))

 (call-named-function 'foo 3 4) ;symbol used literally
 => 7

 (call-named-function "FOO" 3 4) ;string case-translated (no-op)
 => 7

 (call-named-function "foo" 3 4) ;string case-translated
 => 7

 (call-named-function '|foo| 3 4) ;symbol used literally
 => 12
        
 (call-named-function '\f\o\o 3 4) ;symbol used literally
 => 12
From: Jose Carlos Senciales
Subject: Re: How to eval a function from a string with its name?
Date: 
Message-ID: <3B2F9148.F8C8A681@lcc.uma.es>
A very good remark.

Thanks :-)
--
*

          *                *

*
-------------------------------------------------------
              Jos� Carlos Senciales Chaves
(reverse (concatenate 'string ···········@" "nescoj"))
                   ······@lcc.uma.es
-------------------------------------------------------
From: Joel Ray Holveck
Subject: Re: How to eval a function from a string with its name?
Date: 
Message-ID: <y7cae337tcf.fsf@sindri.juniper.net>
>>> Let us say there is a (defun foo () 'a)
>>> and there is also a (setq *name* "foo")
>>>  Is there any way to evaluate the function when only *name* is known?
>>> I am thinking of a shell script with the name of the file to be loaded as
>>> a first argument (no problems with a string) and the name of the function
>>> to be evaluated as a second argument (it is passed as a string, too!).
>> CL-USER 3 > (funcall (read-from-string a) 1 2)
> The thing to know is that READ-FROM-STRING can be made to construct an
> arbitrary form, allowing trojan horses.  You may want to only accept 
> symbols.

Just to introduce a few suggestions:

As you mentioned, using the method you describe (which I clipped), you
lose out on all the case-conversion and escaping; specifically, you
either have to always enter UPPER-CASE symbols, or are limited to
symbols which are already all upper-case.  That may be a good thing,
it may not.

Another thing which may or may not be good is that you lose package
access, so the guy can't call FOO::BAR unless *PACKAGE* happens to be
the FOO package.

Speaking of which, you probably want to bind *PACKAGE* around this
call, or pass an explicit package to INTERN.

Finally-- and possibly most significantly-- if the symbol is bound to
a macro or special operator, then things may blow up in any arbitrary
(but possibly crafted by an attacker) manner.

My start of a suggestion:

(defun call-function-named (name &rest args)
  (let ((function-symbol
	 (with-standard-io-syntax
	  (let ((*read-eval* nil)
		(*package* (find-package :whatever-your-functions-are-in)))
	    (read-from-string name)))))
    (when (or (macro-function function-symbol)
	      ;; We have to do a bit of trickery here, since ANSI
	      ;; renamed SPECIAL-FORM-P to SPECIAL-OPERATOR-P, with no
	      ;; provision for backwards compatibility.  (Kent, did
	      ;; you ever figure out if Moon endorsed this change?)
	      (funcall (if (fboundp 'special-operator-p)
			   #'special-operator-p
			 #'special-form-p)
		       function-symbol))
      (cerror "Try it anyway"
	      "Attempt to call-by-name macro and/or special operator ~A; this has undefined effects."
	      function-symbol))
    ;; We rely on the fact that an error is signaled if
    ;; SYMBOL-FUNCTION is passed anything other than a symbol that is
    ;; fboundp.  If it just acted like FUNCTION, then you could
    ;; probably hand it something like #'(lambda (&rest x)
    ;; (do-something-evil)).
    (apply (symbol-function function-symbol) args)))

Now, you can still pass it something that may invoke an error in the
reader, and I'm not sure what the consequences would be.  I ran into
an interesting manifestation of that while testing this:

* (call-function-named "user:+")

Reader error at 6 on #<String-Input Stream>:
The symbol "+" is not external in the COMMON-LISP-USER package.

Restarts:
  0: [CONTINUE] Use symbol anyway.
  1: [ABORT   ] Return to Top-Level.

Debug  (type H for help)

(#<error printing object> #<String-Input Stream> #\u)
0] 1
* (call-function-named "user:+")

Reader error at 6 on #<String-Input Stream>:
The symbol "+" is not external in the COMMON-LISP-USER package.

Restarts:
  0: [CONTINUE] Use symbol anyway.
  1: [ABORT   ] Return to Top-Level.

Debug  (type H for help)

(#<error printing object> #<String-Input Stream> #\u)
0] abort

Reader error on #<Synonym Stream to 








Help! 11 nested errors.  KERNEL:*MAXIMUM-ERROR-DEPTH* exceeded.

Debug  (type H for help)

(COMMON-LISP::READ-TOKEN #<Synonym Stream to *TERMINAL-IO*> #\a)
0]] 1
1
0]] 0
0] 1
* 

Presumably, you should wrap the READ-FROM-STRING in a HANDLER-CASE or
the like (and replace the CERROR call) if you don't want to trap to
the debugger on invalid input.  (For instance, (call-function-named
"(") is guaranteed to signal an error in the reader.)

However, I'm not sure if there's any case in which "it is an error"
for the reader to encounter a certain sequence of characters.  If so,
then there may still be undefined effects-- which is presumably to be
avoided.

So, now I'm considering something by which you get all the nifty
escaping and case handling of the reader, but not its infinite
possibility for errors.  I suppose you'd have to hand-craft an escape
processor, then pass the result to INTERN like Kent did.

Of course, if security is a goal, then the idea of accepting arbitrary
function names from an unknown source is probably not desirable to
begin with.

And to think I started out with a quick message in mind.

joelh
From: Kent M Pitman
Subject: Re: How to eval a function from a string with its name?
Date: 
Message-ID: <sfwpubzn878.fsf@world.std.com>
Joel Ray Holveck <·····@juniper.net> writes:

> My start of a suggestion:
> 
> (defun call-function-named (name &rest args)
>   (let ((function-symbol
> 	 (with-standard-io-syntax
> 	  (let ((*read-eval* nil)
> 		(*package* (find-package :whatever-your-functions-are-in)))
> 	    (read-from-string name)))))

;; Probably should verify that in fact a symbol was seen.
(check-type function-symbol symbol)

>     (when (or (macro-function function-symbol)
> 	      ;; We have to do a bit of trickery here, since ANSI
> 	      ;; renamed SPECIAL-FORM-P to SPECIAL-OPERATOR-P, with no
> 	      ;; provision for backwards compatibility.  (Kent, did
> 	      ;; you ever figure out if Moon endorsed this change?)
> 	      (funcall (if (fboundp 'special-operator-p)
> 			   #'special-operator-p
> 			 #'special-form-p)
> 		       function-symbol))
>       (cerror "Try it anyway"
> 	      "Attempt to call-by-name macro and/or special operator ~A; this has undefined effects."
> 	      function-symbol))
>     ;; We rely on the fact that an error is signaled if
>     ;; SYMBOL-FUNCTION is passed anything other than a symbol that is
>     ;; fboundp.  If it just acted like FUNCTION, then you could
>     ;; probably hand it something like #'(lambda (&rest x)
>     ;; (do-something-evil)).
>     (apply (symbol-function function-symbol) args)))
From: Joel Ray Holveck
Subject: Re: How to eval a function from a string with its name?
Date: 
Message-ID: <y7cvglr3ene.fsf@sindri.juniper.net>
>> (defun call-function-named (name &rest args)
>>   (let ((function-symbol
>> 	 (with-standard-io-syntax
>> 	  (let ((*read-eval* nil)
>> 		(*package* (find-package :whatever-your-functions-are-in)))
>> 	    (read-from-string name)))))
> ;; Probably should verify that in fact a symbol was seen.
> (check-type function-symbol symbol)

Possibly, but the standard guarantees that it will signal an error if
that's not the case:

[snip]
>>     ;; We rely on the fact that an error is signaled if
>>     ;; SYMBOL-FUNCTION is passed anything other than a symbol that is
>>     ;; fboundp.  If it just acted like FUNCTION, then you could
>>     ;; probably hand it something like #'(lambda (&rest x)
>>     ;; (do-something-evil)).
>>     (apply (symbol-function function-symbol) args)))

Naturally, in a security application, it's not the best practice to
depend on the error reporting of your implementation on odd cases.

Thanks,
joelh
From: Kent M Pitman
Subject: Re: How to eval a function from a string with its name?
Date: 
Message-ID: <sfwofrjad23.fsf@world.std.com>
Joel Ray Holveck <·····@juniper.net> writes:

> 
> >> (defun call-function-named (name &rest args)
> >>   (let ((function-symbol
> >> 	 (with-standard-io-syntax
> >> 	  (let ((*read-eval* nil)
> >> 		(*package* (find-package :whatever-your-functions-are-in)))
> >> 	    (read-from-string name)))))
> > ;; Probably should verify that in fact a symbol was seen.
> > (check-type function-symbol symbol)
> 
> Possibly, but the standard guarantees that it will signal an error if
> that's not the case:

No, it doesn't.

"Should signal an error of type type-error if symbol is not a symbol."

This means:

"In safe code, must signal an error of type type-error if symbol is not a
symbol.  Otherwise, has undefined consequences."

There has been no attempt made here to assure any particular safety level.

> [snip]
> >>     ;; We rely on the fact that an error is signaled if
> >>     ;; SYMBOL-FUNCTION is passed anything other than a symbol that is
> >>     ;; fboundp.  If it just acted like FUNCTION, then you could
> >>     ;; probably hand it something like #'(lambda (&rest x)
> >>     ;; (do-something-evil)).
> >>     (apply (symbol-function function-symbol) args)))
> 
> Naturally, in a security application, it's not the best practice to
> depend on the error reporting of your implementation on odd cases.

This has nothing to do with being a "security application", IMO.
It has to do with ordinary garden-variety good style.

I think it's bad style to rely on error reporting of something where
you have no reasonable expectation that anything has gone to trouble
to assure the something is true.  READ doesn't return something that
is obliged to be a symbol, and the right place to do a check is after
calling READ.  This catches the error in a timely way.  Passing an
object along until it gets to the point that something bad happens, if
this is the first point of expectation, just means signaling will
occur ever farther from the point of useful debugging.
From: Joel Ray Holveck
Subject: Re: How to eval a function from a string with its name?
Date: 
Message-ID: <y7csngv328u.fsf@sindri.juniper.net>
>>> ;; Probably should verify that in fact a symbol was seen.
>>> (check-type function-symbol symbol)
>> Possibly, but the standard guarantees that it will signal an error if
>> that's not the case:
> No, it doesn't.
> "Should signal an error of type type-error if symbol is not a symbol."
> This means:
> "In safe code, must signal an error of type type-error if symbol is not a
> symbol.  Otherwise, has undefined consequences."
> There has been no attempt made here to assure any particular safety level.

Eep!  You're right; I should have read more carefully.  Thanks!

>>>>     ;; We rely on the fact that an error is signaled if
>>>>     ;; SYMBOL-FUNCTION is passed anything other than a symbol that is
>>>>     ;; fboundp.  If it just acted like FUNCTION, then you could
>>>>     ;; probably hand it something like #'(lambda (&rest x)
>>>>     ;; (do-something-evil)).
>>>>     (apply (symbol-function function-symbol) args)))
>> Naturally, in a security application, it's not the best practice to
>> depend on the error reporting of your implementation on odd cases.
> This has nothing to do with being a "security application", IMO.
> It has to do with ordinary garden-variety good style.

I was referring to the fact that this entire jaunt is to prevent
trojans; otherwise a plain old (read-from-string...) would suffice
nicely.

But I agree, it would be better style to perform the type checking
earlier.

joelh
From: Kent M Pitman
Subject: Re: How to eval a function from a string with its name?
Date: 
Message-ID: <sfwhexb6x56.fsf@world.std.com>
Joel Ray Holveck <·····@juniper.net> writes:

> I was referring to the fact that this entire jaunt is to prevent
> trojans; otherwise a plain old (read-from-string...) would suffice
> nicely.

Oh.  Another way to do *that* is to use equalp hash tables and gethash
instead of intern, of course.  That gives you case-insensitivity plus a
finite universe of presumably security-screened functionality.
From: Erik Naggum
Subject: Re: How to eval a function from a string with its name?
Date: 
Message-ID: <3202068662626900@naggum.net>
* Juan Pablo Hierro �lvarez
> Is there any way to evaluate the function when only *name* is known?

  Three steps in principle: From name to symbol, from symbol to function,
  evaluating function.  When you type in (name) to the Lisp read-eval-print
  loop, you get the whole package.  However, if you want to do it yourself,
  it is more work.  Because Common Lisp symbols are case sensitive, but the
  Common Lisp reader by default is not, the first snag is to get from the
  most common way to write symbol names these days to the "internal" name
  of the same symbol in Common Lisp.  (Various efforts to fix this problem
  have ran into political problems.  The problem is not so much that there
  is a specific case internally as the fact that we have no standard tools
  to convert between string and symbol except by going through the reader
  and printer, both very, very expensive facilities.)

  Here's a shot at the conversion between string (name) and symbol, more
  elaborate than efficient to show the concepts involved more clearly:

(defun string-cases-with-mask (string quoted-character-mask)
  "Returns the cases used in the string.
The return value is either nil, for no cases, :lower for all lower-case,
:upper for all upper-case, or :both for the existence of both lower- and
upper-case letters.  Only characters that satisfy both-case-p are tested.
The quoted-character-mask must be a vector of boolean values or bits, and
causes non-nil/non-zero entries to exclude characters from consideration at
the corresponding position in the string."
  (let ((lower nil)
	(upper nil))
    (map nil (lambda (char mask)
	       (when (and (or (not mask) (zerop mask)) (both-case-p char))
		   (if (lower-case-p char)
		       (setq lower t)
		     (setq upper t))))
	 string
	 quoted-character-mask)
    (cond ((and lower upper) :both)
	  (lower :lower)
	  (upper :upper)
	  (t nil))))

(defun string-upcase-with-mask (string quoted-character-mask)
  "Returns a new string which has all unmasked characters upcased that
satisfy both-case-p, as some lower-case characters may not have a
corresponding upper-case version.
The quoted-cahracter-mask must be a vector of boolean values or bits, and
causes non-nil/non-zero entries to exclude characters from consideration at
the corresponding position in the string."
  (map 'string (lambda (char mask)
		 (if (and (or (not mask) (zerop mask)) (both-case-p char))
		     (char-upcase char)
		   char))
       string quoted-character-mask))

(defun string-downcase-with-mask (string quoted-character-mask)
  "Returns a new string which has all unmasked characters downcased that
satisfy both-case-p, as some upper-case characters may not have a
corresponding lower-case version.
The quoted-character-mask must be a vector of boolean values or bits, and
causes non-nil/non-zero entries to exclude characters from consideration at
the corresponding position in the string."
  (map 'string (lambda (char mask)
		 (if (and (or (not mask) (zerop mask)) (both-case-p char))
		     (char-downcase char)
		   char))
       string quoted-character-mask))

(defun string-symbol (string
		      &key (package *package*)
			   (readtable *readtable*)
			   (quoted-character-mask nil)
			   (if-does-not-exist nil))
  "Returns the symbol named by string as if read by the Lisp reader.
Obeys the readtable-case of the specified (or current) readtable.  If the
symbol is found in the specified (or current) package, it is returned like
find-symbol does.  If the symbol does not exist, if-does-not-exist controls
the behavior and return values:  nil, the default, returns nil and nil as
find-symbol does.  :intern interns the symbol in the specified (or current)
package and returns the symbol and nil.  :error signals an error of type
simple-error.
The quoted-character-mask, if supplied, must be a vector of boolean values
\(nil/t or 0/1 are accepted) , and causes non-nil/non-zero entries to
exclude characters from consideration at the corresponding position in the
string."
  (unless quoted-character-mask
    (setq quoted-character-mask
      (make-array (length string) :element-type bit :initial-element 0)))
  ;; Do error handling early, instead of after all the work.
  (ecase if-does-not-exist ((:intern error nil)))
  (let ((internal-string
	 (ecase (readtable-case readtable)
	   (:upcase (string-upcase-with-mask string quoted-character-mask))
	   (:downcase (string-downcase-with-mask string quoted-character-mask))
	   (:preserve string)
	   (:invert
	    (case (string-cases-with-mask string quoted-character-mask)
	      ((:both nil) string)
	      (:upper (string-downcase-with-mask string quoted-character-mask))
	      (:ower (string-upcase-with-mask string quoted-character-mask)))))))
    (multiple-value-bind (symbol status)
	(find-symbol internal-string package)
      (if status
	  (values symbol status)
	(case if-does-not-exist
	  (:intern (intern internal-string package))
	  (:error (error "No symbol with name ~s found in ~s."
			 internal-string (package-name package)))
	  ((nil) (values nil nil)))))))

  Now, since funcall and apply both accept symbols (which they interpret to
  mean the global function binding), you can simply call the symbol with
  the arguments you have already evaluated according to whatever rules your
  language defines for argument evaluation.

> I am thinking of a shell script with the name of the file to be loaded as
> a first argument (no problems with a string) and the name of the function
> to be evaluated as a second argument (it is passed as a string, too!).

  Shell scripts that invoke functions (commands and other shell scripts)
  are actually using the file system as their package implementation, and
  they have a very, very inefficient way of searching through it, even
  though some shells have disvoered hash tables and manage to avoid the
  lookup in some cases.  If you must, you can think of the search for the
  symbol in Common Lisp as if searching a case-insensitive file system for
  a command you have invoked in a shell script, although this does more to
  tell you how incredibly silly file systems and shell languages are done
  compared to real symbol tables (in any language, actually, but usually
  they live only inside compilers).

#:Erik
-- 
  Travel is a meat thing.