La creación y llamada dinámica de funciones es uno de los mecanismos más flexibles de Perl, heredado de las tradiciones del latex y los scripts de shell. Desde las primeras versiones, Perl permite llamar funciones por cadenas (a través de enlaces simbólicos/globs), almacenar referencias a subprogramas en variables y arreglos asociativos, así como la construcción AUTOLOAD para generar funciones sobre la marcha.
El principal problema de este enfoque es la seguridad (la posibilidad de llamar a una función no deseada a través de una cadena manipulada) y el rendimiento (la resolución simbólica de nombres es más lenta que la llamada directa). También es importante el control sobre el ámbito de las funciones y la entrega del número correcto de argumentos.
La solución es utilizar un hash de despachadora (mapeo de cadena/palabra clave a coderef), evitar eval para ejecutar código del usuario y definir claramente la lista de funciones permitidas para ser llamadas.
Ejemplo de código (despacho por clave):
my %dispatch = ( add => sub { $_[0] + $_[1] }, sub => sub { $_[0] - $_[1] }, mult => sub { $_[0] * $_[1] }, ); my $key = 'add'; if (exists $dispatch{$key}) { print $dispatch{$key}->(2, 3); # Imprimirá 5 } else { die "Acción desconocida $key"; }
Características clave:
¿Se puede llamar a una función por su nombre, utilizando solo una cadena?
Respuesta: Sí, pero es peligroso; llamar $fn_name->() o a través de un enlace simbólico directo &$fn_name(); no se recomienda con datos externos (del usuario), ya que podría llevar a vulnerabilidades potenciales.
¿Hay una diferencia entre una referencia de código y el nombre de una función en Perl?
Respuesta: Sí, el nombre de la función siempre es global, mientras que la referencia a la función (coderef) puede ser léxica, local, pasarse entre subprogramas y mantener una función anónima.
my $coderef = sub { ... }; my $named = \&fn_name;
¿Qué sucede si se llama a una función no existente a través de un hash de despachadora?
Respuesta: Si la clave no existe, se generará un error. Por lo tanto, siempre se requiere la verificación exists antes de llamar y el manejo de comandos no reconocidos, de lo contrario habrá un intento de llamar a undef (error fatal).
Un comando en el sitio acepta el nombre de la función desde un parámetro GET y lo llama a través de eval; cualquier usuario puede invocar funciones peligrosas como system, unlink y otras.
Ventajas:
Desventajas:
Se utiliza un hash con una lista blanca de funciones, todas las entradas se validan, eval no se utiliza, los errores se capturan y se registran.
Ventajas:
Desventajas: