#LyX 1.1 created this file. For more info see http://www.lyx.org/ \lyxformat 218 \textclass article \language spanish \inputencoding latin1 \fontscheme default \graphics default \paperfontsize default \spacing single \papersize Default \paperpackage a4 \use_geometry 0 \use_amsmath 0 \paperorientation portrait \secnumdepth 3 \tocdepth 3 \paragraph_separation indent \defskip medskip \quotes_language english \quotes_times 2 \papercolumns 1 \papersides 1 \paperpagestyle default \layout Title Seguridad en scripts de Perl \layout Author Gunnar Eyal Wolf Iszaevich \newline gwolf@gwolf.cx \newline http://www.gwolf.cx \layout Standard \begin_inset LatexCommand \tableofcontents{} \end_inset \layout Section Introducción \layout Subsection Qué es Perl? \layout Standard Perl es un lenguaje de programación de todo propósito y fácilmente extensible que se ha vuelto muy popular en los últimos años. Tanto la especificación del lenguaje como su implementación son libres, lo que ha hecho que Perl sea utilizado como lenguaje independiente y sea embebido en una gran cantidad de proyectos con muy diversas naturalezas cada vez más frecuentemente. \layout Standard Si bien Perl tiene características que nos ayudan a crear código más seguro, tiene varias sutilezas que si no manejamos correctamente pueden actuar en nuestra contra. \layout Subsection Puntos a favor de Perl \layout Standard Los programadores habituales de Perl hablamos maravillas del lenguaje en muchos aspectos --- Nos gusta su forma de escritura, con reglas de sintaxis casi como las de un lenguaje natural. Nos gusta la riqueza del lenguaje. Nos gustan muchísimas cosas. Sin embargo, ¿cuáles de ellas son relevantes para la seguridad? Principalmente, las siguientes: \layout Subsubsection Variables no tipificadas \layout Standard En Perl, las variables no requieren ser declaradas como de cierto tipo o magnitud. Perl se encargará siempre de poner nuestros datos en una variable del tamaño y tipo adecuados, sin que tengamos manualmente que especificarlo. \layout Standard Va lo mismo para los arreglos. Al crear un arreglo no requerimos saber de antemano cuántos elementos llevará, ni el tipo de cada uno de ellos. Los arreglos son de longitud variable, cada uno de sus elementos puede ser de diferente tipo, y si bien no están soportados formalmente en el lenguaje, se pueden crear arreglos multidimentsionales sin dolor utilizando referencias. \layout Subsubsection Memoria manejada automáticamente \layout Standard Muchos lenguajes requieren que el programador maneje manualmente la memoria asignada dinámicamente. En Perl, la memoria es asignada automáticamente cuando es requerida y los mecanismos de \emph on recolección de basura \emph default propios del lenguaje se encargan de reclamar el espacio que sea liberado. Esto significa que no nos tendremos que preopcupar por \emph on buffer overflows \emph default , tamaños de arreglos, complejidad de estructuras de datos y demás detalles. Esto hace no sólo que el tiempo de desarrollo disminuya sensiblemente, sino que evita los frecuentes errores humanos en procesos repetitivos y tediosos. \layout Subsubsection Alta extensibilidad \layout Standard Perl es un lenguaje tremendamente extensible. Hay módulos que le permiten hacer prácticamente cualquier cosa, por lo que, sin obligar al programador a emplear paradigmas muchas veces estorbosos y lentos (como Java y sus omnipresentes y obligatorios objetos), favorece una gran reutilización de código probado y conocido. \layout Standard Una de las mayores virtudes de Perl es el CPAN (Comprehensive Perl Archive Network, \begin_inset LatexCommand \cite{CPAN} \end_inset ), un gran depósito de módulos de Perl cubriendo prácticamente cualquier área del desarrollo. Es una muy buena idea asomarse al CPAN antes de comenzar con un proyecto y en las diversas fases de su desarrollo, que muy frecuentemente nos ahorrará tiempo y errores de implementación. \layout Subsubsection Rápida compilación \layout Standard Si bien hay gente que ve a este punto más como una debilidad que como una ventaja, a mí se me hace uno de los factores clave del éxito de Perl. \layout Standard Perl no es, pese a lo que muchos dicen, un lenguaje interpretado --- Todo código de Perl se compila antes de ser ejecutado. Se compila, eso sí, a memoria. Podemos (usando los módulos B, O y el script perlcc \begin_inset LatexCommand \cite{compilacion} \end_inset ) compilar a imágenes binarias en disco, pero no es mucha la diferencia en tiempo de ejecución gracias al altamente optimizado compilador de Perl. \layout Standard Esta rápida compilación lleva a que el tiempo de desarrollo (especialmente de depuración) disminuya fuertemente, al poder probar rápidamente pequeños cambios en el código. \layout Subsection Puntos en contra de Perl \layout Standard Si bien me gusta pintar la vida en el mundo de Perl de color rosa, no todo es perfecto. Hay muchos puntos peligrosos que tenemos que tomar en cuenta. Algunos de ellos son: \layout Subsubsection Mucha ---tal vez demasiada--- sencillez y poder \layout Standard Perl es un lenguaje que permite interactuar fácilmente con el sistema, motivo por el cual el programador puede obviar ciertas acciones que debería tomar en cuenta para efectuar los procesos de manera segura, resultando en tremendos agujeros en la seguridad del sistema. \layout Subsubsection Funciones sin prototipos \layout Standard El no tipificar funciones es una gran cualidad de Perl --- Una misma función puede presentar diferentes comportamientos basandose en los argumentos que reciba, en el contexto en que sea llamada, o basicaemnte, en lo que el programador decida. Sin embargo, si bien esto proporciona una gran flexibilidad, tiene dos grandes desventajas: \layout Itemize El programador debe proporcionar la inteligencia para asegurarse que la función fue invocada con los parametros en el formato correcto. \layout Itemize Contribuye a que el código sea más difícil de leer y de mantener \layout Subsubsection Los objetos son esencialmente un parche \layout Standard A partir de la versión 5 de Perl tenemos la posibilidad de programar orientado a objetos. Sin embargo, no cuesta trabajo darse cuenta que esta implementación es esencialmente un parche, no una implementaición limpia de objetos. Programar con objetos en Perl suele involucrar varios pasos que en otros lenguajes podemos dar por sentado y son mera \emph on talacha \emph default . \layout Subsection Tipos de Perl \layout Standard Fiel a la filosofía TIMTOWTDI ( \emph on There Is More Than One Way To Do It \emph default , Hay más de una manera de hacerlo), hay diferentes maneras de utilizar Perl. Las más comunes son: \layout Subsubsection Tradicional \layout Standard El binario de Perl es invocado junto con el nombre del programa a ser ejecutado. Perl lee, compila y ejecuta al programa al momento de invocación. \layout Standard El compilador de Perl es altamente eficiente. Sin embargo, este proceso lleva algo de tiempo. Si un mismo programa es solicitado con alta frecuencia, el tiempo perdido compilando se vuelve importante. \layout Standard Este es el Pelr tradicional, con todas las ventajas y desventajas que ello conlleva. \layout Subsubsection Perl como módulo o parte de otra aplicación \layout Standard Perl, al haber sido concebido como un \emph on lenguaje pegamento \emph default , ha sido convertido en módulo, en lenguaje embebido. Probablemente el mejor ejemplo de esto es mod_perl, que embebe a Perl en el popular servidor de web Apache. \layout Standard mod_perl es una respuesta para la problemática descrita anteriormente. Perl reside dentro del proceso del servidor Apache. Este, claro está, es mayor en memoria a lo que sería si no incluyera Perl y toma algo de tiempo adicional en incializar. Sin embargo, cuando un programa es solicitado en repetidas ocasiones (p. ej., un CGI muy demandado), la imagen binaria compilada estará ya lista en memoria, por lo que los tiempos de ejecución bajarán notablemente. \layout Standard Hay varias maneras de utilizazr mod_perl. Probablemente la más socorrida, aunque desperdicie la mayor parte de las capacidades de mod_perl, es a través del script Apache::Register --- Esto nos permitirá correr, prácticamente sin modificaciones, los CGIs escritos al estilo tradicional. \layout Standard Por otro lado tenemos a Mason, eperl y varias alternativas similares, que nos permiten ---al estilo PHP o ASP--- que nos permiten embeber el código en HTML. \layout Standard La mejor manera, sin embargo, de sacar el mayor provecho de mod_perl es programar directamente módulos de Apache. Esto nos da la potencia de participar en cada etapa por la que atraviesa el servidor, desde la misma inicialización y cada etapa por la que atraviesa. El API completo de Apache está a nuestra disposición si utilizamos mod_perl, y hay muchas cosas que podemos hacer con él que unicamente podremos lograr con Perl y con C ---y que muchos estarán de acuerdo conmigo al afirmar que sólamente conviene hacerlas con Perl. \layout Subsection Lenguajes comparables con Perl \layout Standard Sin ánimo de iniciar una guerra religiosa, una de las mejores maneras de definir los factores que hacen único a un lenguaje es compararlo con otros. Claro, comparar contra todos los lenguajes de programación sería tedioso y ridículo. Lo comparo, pues, con los que más comunmente compite. \layout Subsubsection Shell \layout Standard Perl es un maravilloso lenguaje para auxiliarnos en la administración de sistemas. En esta área, claro está, la alternativa lógica son los lenguajes de shell de Unix (Bourne, Korn, C-Shell y sus derivados). Estos lenguajes califican perfectamente como lenguajes de propósito general, y son suficientemente poderosos para llevar a cabo casi cualquier tarea sencilla. Sin embargo, al llegar a proyectos intermedios, rápidamente nos damos cuenta de la imposibilidad de llevarlos a cabo limpiamente: Las variables y funciones son globales, no existen ni siquiera las estructuras de datos básicas (y es \emph on bastante \emph default complejo implementarlas) y es muy difícil mantener un estilo de programación modular. \layout Subsubsection PHP \layout Standard PHP fue desde un inicio pensado únicamente para el diseño de páginas Web interactivas (rol que fue ocupado por Perl prácticamente desde el inicio de las páginas interactivas), aunque ya hay extensiones del lenguaje que permiten su uso para scripts de administración y otros muchos roles. Exhibe claramente su herencia, pensado para mejorar varios aspectos de Perl, haciéndolo más simple para los diseñadores de páginas HTML. \layout Standard Tiene una sintaxis muy similar a Perl, si bien los perleros siempre encontraremo s piezas faltantes en PHP. A diferencia de Perl, sin embargo, PHP casi siempre lo veremos como porciones de código HTML mezclado con porciones de código en PHP, cosa que muchos vemos como demasiado \emph on sucia \emph default . \layout Standard PHP es un lenguaje puramente interpretado, mientras que Perl compila el programa completo a memoria, lo cual muchas veces hace más lenta y complicada la depuración de código en PHP. \layout Standard Típicamente la ejecución de un programa en PHP es más rápida que la de uno equivalente en Perl, dado que el intérprete está embebido en el servidor de Web y no requiere ser cargado a cada invocación. Esta tendencia claramente se revierte si utilizamos mod_perl con Apache (el cual es ya parte de la distribución base de Apache a partir de la versión 2.0), el cual además de una gran mejora de velocidad nos da acceso a una mucha mayor funcionalidad y control del servidor Web. \layout Subsubsection Python \layout Standard Python es probablemente el lenguaje con el que Perl \begin_inset Quotes eld \end_inset compita \begin_inset Quotes erd \end_inset más directamente. Comparte muchas de sus características, pero tiene una diferencia fundamental de diseño: Mientras que la máxima de Perl es \emph on Hay más de una manera de hacerlo \emph default (TIMTOWTDI, \emph on There Is More Than One Way To Do It \emph default ), Guido van Rossum ---creador de Python--- prefiere \emph on Debe haber sólo una manera de hacerlo \emph default . \layout Standard Python enfatiza en la legibilidad del código, utilizando estructuras mucho más claras, evitando crear código inmantenible. Muchos defensores de Perl se quejan de la falta de naturalidad de Python --- Perl fue diseñado por el linguista, Larry Wall, quien modeló a su creación para ser tan cercano como sea posible a un lenguaje natural. \layout Subsubsection Java \layout Standard Java es un concepto mal entendido, creado en Sun Microsystems, buscando tener un sistema universalmente portable, compilando el código no al lenguaje máquina de cada plataforma sino que a un código intermedio llamado \emph on bytecode \emph default , el cual es posteriormente compilado a la hora de ejecución en la computadora destino en una máquina virtual Java (JVM). \layout Standard Java incluye provisiones para ser ejecutado embebiéndolo en un navegador, por lo que tiene un \emph on cajón de arena \emph default (sandbox) que evita que un programa descargado de la red lleve a cabo ciertas acciones que puedan llevar a compromisos de seguridad. \layout Standard En Java, todo lo que hagamos debe ser orientado a objetos. Si bien el paradigma de programación orientada a objetos puede ser muy útil para ciertos proyectos, el obligarlo en cualquier aplicacion hace a la programación en Java muy tediosa. \layout Standard Java es, desafortunadamente, demasiado lento para aplicaciones medianas o grandes, y las diferentes versiones que tienen amplia presencia pueden presentar fuertes incompatiblidades. \layout Subsubsection Javascript \layout Standard Pese a lo que el nombre nos indica, Javascript no tiene nada que ver con Java. Javascript es un lenguaje de propósito específico, corriendo como parte de un navegador Web, estrictamente del lado del cliente, y es típicamente utilizado para validaciones en formas (nos asegura que los datos estén en el formato correcto antes de enviarlos al servidor a ser procesados), para crear páginas con HTML dinámico y similares. \layout Standard Javascript desafortunadamente también sufre de tener una gran cantidad de implementaciones no completamente compatibles entre sí. Si bien la especificación del lenguaje es muy clara y ---dicen los que saben--- muy elegante, utilizarlo es muchas veces muy problemático por las características que pueden o no estar implementadas en determinado cliente. \layout Standard Muchas veces veremos que CGIs en Perl generan código Javascript que será ejecutado del lado del cliente. \layout Section Evitando prácticas inseguras de programación: El pragma \family typewriter strict \layout Standard Los \emph on pragmas \emph default son directivas que indican al compilador de Perl que debe actuar de determinada manera para cierta parte del código, permitiendo o exigiendo cierto comportamie nto, o produciendo código de diferentes maneras. A lo largo de este tutorial hablaremos acerca de varios diferentes pragmas, pero a mi entender, uno de los más útiles e importantes ---y que mejor ilustra el comportamiento de los pragmas--- es \latex latex { \backslash tt \latex default strict \latex latex } \latex default . \layout Standard Una nota importante de los pragmas: Si nuestro programa consta de varios archivos, dividido en módulos o bibliotecas, el activar un pragma en uno de ellos no lo activa en los demás. Es buena práctica iniciar todos nuestros módulos o bibliotecas activando los mismos pragmas, para que el compilador tenga un comportamiento consistente en todo el código. \layout Subsection Introducción a \latex latex { \backslash tt \latex default strict \latex latex } \layout Standard El propósito de \latex latex { \backslash tt \latex default strict \latex latex } \latex default es exigirnos que no caigamos en prácticas inseguras, si bien a veces muy cómodas, de programación. Perl normalmente acepta ciertas maneras de referirnos a variables, subrutinas o referencias poco seguras. \latex latex { \backslash tt \latex default strict \latex latex } \latex default nos evita caer en esos vicios, abortando la compilación al detectar que estamos haciendo algo mal. \layout Standard Sí, es incómodo que el compilador esté quejándose y no nos permita programar a gusto, pero es fundamental que nos acostumbremos a incluir y a obedecer a \latex latex { \backslash tt \latex default strict \latex latex } \latex default en todo programa que hagamos que planeemos ejecutar más de una vez. \layout Subsubsection Activación/desactivación de \latex latex { \backslash tt \latex default strict \latex latex } \layout Standard Para indicarle al compilador que active los chequeos de \latex latex { \backslash tt \latex default strict \latex latex } \latex default a partir del punto actual, le indicamos: \layout Quote \latex latex { \backslash tt \latex default use strict; \latex latex } \layout Standard Y si deseamos desactivar a partir de cierto punto este comportamiento, le indicamos: \layout Quote \latex latex { \backslash tt \latex default no strict; \latex latex } \layout Standard Podemos especifiar que queremos activar o desactivar uno sólo de los tres modos principales de \latex latex { \backslash tt \latex default strict \latex latex } \latex default indicándoselo de la siguiente manera: \layout Quote \latex latex { \backslash tt \latex default use strict 'vars'; \latex latex } \layout Quote \latex latex { \backslash tt \latex default use strict 'subs'; \latex latex } \layout Quote \latex latex { \backslash tt \latex default no strict 'refs'; \latex latex } \layout Standard El no especificar modo implica que nos estamos refiriendo a los tres modos. \layout Standard Para mayor información al respecto de este pragma, sugiero consultar la documentación de strict \begin_inset LatexCommand \cite{strict} \end_inset . \layout Subsection \latex latex { \backslash tt \latex default strict 'vars' \latex latex } \latex default --- Ámbitos de las variables \layout Standard Este modo hará que Perl genere un error en tiempo de compilación si intentamos utilizar una variable que no haya sido declarada con \latex latex { \backslash tt \latex default use vars \latex latex } \latex default , localizada con \latex latex { \backslash tt \latex default my \latex latex } \latex default o con \latex latex { \backslash tt \latex default our \latex latex } \latex default , o llamada por su nombre completo calificado. No permite el uso siquiera del ámbito \latex latex { \backslash tt \latex default local \latex latex } \latex default . \layout Standard Para comprender esto mejor, analicemos brevemente los ámbitos posibles de las variables en Perl. \layout Standard Cabe mencionar que \latex latex { \backslash tt \latex default strict 'vars' \latex latex } \latex default no evitará el uso de las variables globales especiales de Perl ( \latex latex { \backslash tt \latex default $| \latex latex } \latex default , \latex latex { \backslash tt \latex default $_ \latex latex } \latex default , \latex latex { \backslash tt \latex default $^W \latex latex } \latex default , etc.) Estas variable \emph on podrán \emph default ser utilizadas en nuestros programas independientemente de \latex latex { \backslash tt \latex default strict 'vars' \latex latex } \latex default . \layout Subsubsection Ámbito global \layout Itemize Ámbito por omisión en Perl \layout Itemize Las variables globales están disponibles en \emph on cualquier \emph default lugar del programa. \layout Itemize Si queremos utilizar una variable global con \latex latex { \backslash tt \latex default strict \latex latex } \latex default activado, podemos predeclararlas de la siguiente manera: \layout Quote \latex latex { \backslash tt \latex default use vars qw($var1 @var2 %var3); \latex latex } \layout Itemize El ámbito global es equivalente a utilizar explícitamente el paquete Main. Esto quiere decir que en vez de predeclarar como lo mostramos aquí, podríamos referirnos explícitamente a estas variables como \latex latex { \backslash tt \latex default $Main::var1 \latex latex } \latex default , \latex latex { \backslash tt \latex default @Main::var2 \latex latex } \latex default y \latex latex { \backslash tt \latex default %Main::var3 \latex latex } \latex default . Recomiendo, sin embargo, por claridad predeclarar las variables en vez de utilizar esta sintaxis. \layout Subsubsection Ámbito global en un paquete ( \latex latex { \backslash tt \latex default our \latex latex } \latex default ) \layout Itemize Este ámbito existe únicamente en Perl 5.6.0 y posteriores \layout Itemize Actúa como una variable global dentro de un paquete. El paquete debe haber sido indicado explícitamente antes. \layout Standard Las siguientes expresiones son equivalentes: \layout Quote \latex latex { \backslash tt \latex default $miPaquete::variable = 1; \latex latex } \layout Standard y \layout Quote \latex latex { \backslash tt \latex default package miPaquete; \layout Quote our $variable = 1; \latex latex } \layout Standard Adicionalmente, ambas son válidas utilizando \latex latex { \backslash tt \latex default strict \latex latex } \latex default . \layout Subsubsection Ámbito local \layout Itemize Las variables estarán definidas dentro del bloque actual y cualquier bloque que de él derive: \layout Quote \latex latex { \backslash tt \latex default sub func { \newline local $a = 1; \newline func2(); \latex latex { \backslash scriptsize \latex default # Aquí $a está definido, y func2 imprime 1. \latex latex } \latex default \newline print $a; \latex latex { \backslash scriptsize \latex default # Estamos dentro del bloque donde definimos $a, e imprime 1. \latex latex } \latex default \newline } \newline func2(); \latex latex { \backslash scriptsize \latex default # Aquí $a está indefinido, y func2 no imprime nada. \latex latex } \latex default \newline sub func2 { \newline print $a; \newline } \latex latex } \layout Itemize No es un ámbito válido en \latex latex { \backslash tt \latex default strict \latex latex } \latex default . \layout Subsubsection Variables léxicas ( \latex latex { \backslash tt \latex default my \latex latex } \latex default ) \layout Itemize Las variables existirán únicamente dentro del bloque en que fueron creadas, y serán destruidas y su espacio en memoria reclamado al salir de él. \layout Quote \latex latex { \backslash tt \latex default sub func { \newline my $a = 1; \newline func2(); \latex latex { \backslash scriptsize \latex default # func2 no tiene cómo ver a $a, que está indefinida fuera de su bloque. \latex latex } \latex default \newline print $a; \latex latex { \backslash scriptsize \latex default # Estamos dentro del bloque donde definimos $a, e imprime 1. \latex latex } \latex default \newline } \newline func2(); \latex latex { \backslash scriptsize \latex default # Aquí $a ya no existe, y func2 no imprime nada. \latex latex } \latex default \newline sub func2 { \newline print $a; \newline } \latex latex } \layout Itemize Este es el ámbito recomendado para prácticamente cualquier variable que utilicemos en nuestro programa. \layout Subsubsection ¿Por qué evitar el uso de variables globales? \layout Itemize Varios módulos o funciones pueden interfirir entre sí. \newline Al programar todos nosotros somos muy predecibles. ¿Cuántas veces no escribimos programas con variables como \latex latex { \backslash tt \latex default $i \latex latex } \latex default , \latex latex { \backslash tt \latex default $tmp \latex latex } \latex default , \latex latex { \backslash tt \latex default $num \latex latex } \latex default , etc.? ¿Cuántas otras funciones que utilicemos, hechas por terceros, no tendrán nombres de variables similares? Si utilizamos variables globales tendremos que cuidarnos manualmente de no interferir con las variables que utilicen otros fragmentos del programa. \layout Itemize Código más difícil de mantener \newline El manejar variables globales nos obliga a documentarlas también de manera global, no sólo para evitar los problemas que mencionamos, sino para facilitar la extensibilidad a futuro. Utilizar variables de ámbito más limitado nos permite documentarlas siempre al inicio de cada función o bloque. \layout Itemize Mayor uso de memoria \newline El recolector de basura de Perl es muy bueno --- Reclama el espacio utilizado por los datos tan pronto como estos dejan de ser necesarios. Sin embargo, cuando las variables son globales, el recolector de basura jamás podrá predecir que los datos de una variable no volverán a ser necesitado s. Al utilizar ámbitos más limitados, el recolector de basura reclamará el espacio tan pronto salgamos del bloque en que fueron creadas. \layout Subsubsection Comportamiento del ámbito global con \latex latex { \backslash tt \latex default strict \latex latex } \layout Standard Si intentamos utilizar variables globales sin declararlas ni referirnos a ellas por su nombre completa, Perl generará los siguientes errores: \layout Quote \latex latex { \backslash tt \latex default use strict; \layout Quote $var = 1234; \layout Quote \emph on Global symbol \begin_inset Quotes eld \end_inset $var \begin_inset Quotes erd \end_inset requires explicit package name at programa.pl line 2. \emph default \latex latex { \backslash scriptsize \latex default # Este error es inmediato, al procesar el código \latex latex } \layout Quote \emph on Execution of programa.pl aborted due to compilation errors. \emph default \latex latex { \backslash scriptsize \latex default # Este error es emitido a la hora de ejecución \latex latex }} \layout Subsection \latex latex { \backslash tt \latex default strict 'subs' \latex latex } \latex default --- Subrutinas no explícitas \layout Standard \latex latex { \backslash tt \latex default strict 'subs' \latex latex } \latex default requerirá que todas las palabras sueltas ( \emph on barewords \emph default ) sean llamadas a función válidas, que estén entre llaves o que estén del lado izquierdo de un operador =>. Eso significa que están permitidos: \layout Itemize \latex latex { \backslash tt \latex default $var{llave} \latex latex } \layout Itemize \latex latex { \backslash tt \latex default (llave1 => 'valor1', llave2 => 'valor2') \latex latex } \layout Itemize \latex latex { \backslash tt \latex default funcion \latex latex } \latex default (siempre que sea el nombre de una función existente) \layout Standard Mientras que los siguientes causarán un error de compilación: \layout Itemize \latex latex { \backslash tt \latex default $hola = mundo; \latex latex } \latex default (a menos que mundo sea el nombre de una función existente) \layout Itemize \latex latex { \backslash tt \latex default (llave1 => valor1, llave2 => valor2) \latex latex } \latex default (a menos que valor1 y valor2 sean nombres de funciones existentes) \layout Subsection \latex latex { \backslash tt \latex default strict 'refs' \latex latex } \latex default --- Referencias simbólicas \layout Standard Una característica bastante obscura de Perl 5 es el uso de referencias simbólica s. Es un concepto bonito y divertido, pero tan peligroso que a la vez que fue introducido, fue también agregado este comportamiento a \latex latex { \backslash tt \latex default strict \latex latex } \latex default , evitando que utilicemos este tipo de referencias. \layout Subsubsection ¿Qué son las referencias simbólicas? \layout Standard A diferencia de las referencias duras, que son las que normalmente encontraremos en Perl, las referencias simbólicas no apuntan a la dirección en memoria de una variable, sino que a su nombre. La mejor manera de explicar este curioso concepto es a través de un ejemplo tomado directamente del manual ( \begin_inset LatexCommand \cite{perlref} \end_inset ): \layout Quote \latex latex { \backslash tt \latex default $name = 'foo'; \newline $$name = 1; \latex latex { \backslash scriptsize \latex default # Guarda 1 en $foo \latex latex } \latex default \newline ${$name} = 2; \latex latex { \backslash scriptsize \latex default # Guarda 2 en $foo \latex latex } \latex default \newline ${$name x 2} = 3; \latex latex { \backslash scriptsize \latex default # Guarda 3 en $foofoo \latex latex } \latex default \newline $name->[0] = 4; \latex latex { \backslash scriptsize \latex default # Guarda 4 en $foo[0] \latex latex } \latex default \newline @$name = (); \latex latex { \backslash scriptsize \latex default # Vacía @foo \latex latex } \latex default \newline &$name(); \latex latex { \backslash scriptsize \latex default # Llama a la función &foo() \latex latex } \latex default \newline $pack = "THAT"; \newline ${"${pack}::$name"} = 5; \latex latex { \backslash scriptsize \latex default # Guarda 5 en $THAT::foo --- sin requerir eval \latex latex }} \layout Subsubsection ¿Y qué tienen de malo las referencias simbólicas? \layout Itemize Tienden a hacer nuestro código más difícil de entender... Basta con repasar el ejemplo anterior (¡y eso que viene directo del manual!) para entender por qué. \layout Itemize Su comportamiento puede parecer impredecible. Por ejemplo, si tenemos una variable global \latex latex { \backslash tt \latex default $val \latex latex } \latex default con el valor \latex latex { \backslash tt \latex default 'mivalor' \latex latex } \latex default y tenemos también una variable con el mismo nombre dentro de un bloque con el valor \latex latex { \backslash tt \latex default 'otro' \latex latex } \latex default , y desde dentro del bloque llamamos a \latex latex { \backslash tt \latex default $$val \latex latex } \latex default , nos estaremos refiriendo a \latex latex { \backslash tt \latex default $mivalor \latex latex } \latex default pues si bien el \latex latex { \backslash tt \latex default $val \latex latex } \latex default interno es el válido, sólamente el externo aparece en la tabla global de símbolos. \layout Itemize Este comportamiento, en caso de ser requerido, puede ser logrado a través de \latex latex { \backslash tt \latex default eval \latex latex } \latex default de una manera mucho más clara. \layout Section Reporte de advertencias ( \latex latex { \backslash tt \latex default warnings \latex latex } \latex default ) \layout Standard Perl tiene la capacidad de advertir al programador por la salida estándar (STDOUT) que puede estar haciendo algo mal, invitándolo a revisar el código para comprobar que no sea un error que pueda causar algún fallo bajo ciertas circunstancias. \layout Standard Si bien el reporte de advertencias ha sido parte de Perl por ya un buen tiempo, su comportamiento cambió fuertemente a partr de la versión 5.6.0 \layout Subsection Usando \latex latex { \backslash tt \latex default warnings \latex latex } \latex default con Perl < 5.6.0 \layout Standard Con versiones de Perl anteriores a la 5.6.0, el comportamiento de los warnings es definido por un switch a la hora de ejecución o por una variable local especial, con las siguientes reglas: \layout Itemize Si invocamos a Perl con el switch \latex latex { \backslash tt \latex default -w \latex latex } \latex default , esto obligará a que la variable global especial \latex latex { \backslash tt \latex default $^W \latex latex } \latex default tenga un valor verdadero. Podemos invocar a Perl con este switch llamando a nuestro programa con \latex latex { \backslash tt \latex default perl -w programa.pl \latex latex } \latex default o incluyendo la línea \latex latex { \backslash tt \latex default #!/usr/bin/perl -w \latex latex } \latex default como primera línea de nuestro programa. \layout Itemize Si invocamos a Perl con el switch \latex latex { \backslash tt \latex default -W \latex latex } \latex default , esto obligará a que los warnings sean reportados, independientemente del valor de \latex latex { \backslash tt \latex default $^W \latex latex } \latex default . \layout Itemize Si invocamos a Perl con el switch \latex latex { \backslash tt \latex default -X \latex latex } \latex default , esto obligará a que los warnings \emph on no \emph default sean reportados, independientemente del valor de \latex latex { \backslash tt \latex default $^W \latex latex } \latex default . \layout Itemize Tomadas en cuenta estas reglas, los warnings serán reportados siempre que la variable global \latex latex { \backslash tt \latex default $^W \latex latex } \latex default tenga un valor verdadero. \layout Subsection Usando \latex latex { \backslash tt \latex default warnings \latex latex } \latex default léxicos con Perl >= 5.6.0 \layout Standard Con Perl 5.6 el comportamiento descrito sigue funcionando, pero un nuevo comportamiento mucho más flexible y poderoso ha sido introducido: El uso de los warnings como pragma. Sugiero referirse a la página de manual de warnings léxicos \begin_inset LatexCommand \cite{perllexwarn} \end_inset . Cabe también recordarles que los pragmas aplican únicamente al archivo donde son declarados. \layout Standard El activar el reporte de warnings como un pragma nos permite activar o desactiva r las advertencias por categorías. En la página de manual se definen las categorías \latex latex { \backslash tt \latex default chmod \latex latex } \latex default , \latex latex { \backslash tt \latex default closure \latex latex } \latex default , \latex latex { \backslash tt \latex default exiting \latex latex } \latex default , \latex latex { \backslash tt \latex default glob \latex latex } \latex default , \latex latex { \backslash tt \latex default io \latex latex } \latex default (que se subdivide en \latex latex { \backslash tt \latex default closed \latex latex } \latex default , \latex latex { \backslash tt \latex default exec \latex latex } \latex default , \latex latex { \backslash tt \latex default newline \latex latex } \latex default , \latex latex { \backslash tt \latex default pipe \latex latex } \latex default y \latex latex { \backslash tt \latex default unopened \latex latex } \latex default ), \latex latex { \backslash tt \latex default misc \latex latex } \latex default , \latex latex { \backslash tt \latex default numeric \latex latex } \latex default , \latex latex { \backslash tt \latex default once \latex latex } \latex default , \latex latex { \backslash tt \latex default overflow \latex latex } \latex default , \latex latex { \backslash tt \latex default pack \latex latex } \latex default , \latex latex { \backslash tt \latex default portable \latex latex } \latex default , \latex latex { \backslash tt \latex default recursion \latex latex } \latex default , \latex latex { \backslash tt \latex default redefine \latex latex } \latex default , \latex latex { \backslash tt \latex default regexp \latex latex } \latex default , \latex latex { \backslash tt \latex default severe \latex latex } \latex default (que se subdivide en \latex latex { \backslash tt \latex default debugging \latex latex } \latex default , \latex latex { \backslash tt \latex default inplace \latex latex } \latex default , \latex latex { \backslash tt \latex default internal \latex latex } \latex default y \latex latex { \backslash tt \latex default malloc \latex latex } \latex default ), \latex latex { \backslash tt \latex default signal \latex latex } \latex default , \latex latex { \backslash tt \latex default substr \latex latex } \latex default , \latex latex { \backslash tt \latex default syntax \latex latex } \latex default (que se subdivide en \latex latex { \backslash tt \latex default ambiguous \latex latex } \latex default , \latex latex { \backslash tt \latex default bareword \latex latex } \latex default , \latex latex { \backslash tt \latex default deprecated \latex latex } \latex default , \latex latex { \backslash tt \latex default digit \latex latex } \latex default , \latex latex { \backslash tt \latex default parenthesis \latex latex } \latex default , \latex latex { \backslash tt \latex default precedence \latex latex } \latex default , \latex latex { \backslash tt \latex default printf \latex latex } \latex default , \latex latex { \backslash tt \latex default prototype \latex latex } \latex default , \latex latex { \backslash tt \latex default qw \latex latex } \latex default , \latex latex { \backslash tt \latex default reserved \latex latex } \latex default y \latex latex { \backslash tt \latex default semicolon \latex latex } \latex default ), \latex latex { \backslash tt \latex default taint \latex latex } \latex default , \latex latex { \backslash tt \latex default umask \latex latex } \latex default , \latex latex { \backslash tt \latex default uninitialized \latex latex } \latex default , \latex latex { \backslash tt \latex default unpack \latex latex } \latex default , \latex latex { \backslash tt \latex default untie \latex latex } \latex default , \latex latex { \backslash tt \latex default utf8 \latex latex } \latex default , \latex latex { \backslash tt \latex default void \latex latex } \latex default y \latex latex { \backslash tt \latex default y2k \latex latex } \latex default . Cada una de estas categorías puede ser activada o desactivada individualmente. Por ejemplo, si queremos activar el reporte de advertencias acerca de símbolos utilizados una sóla vez y acerca de uso de manipuladores de archivos no abiertos, y queremos ignorar el reporte de advertencias de recursión y de uso de valores sin inicializar: \layout Quote \latex latex { \backslash tt \latex default use warnings qw(once unopened); \layout Quote no warnings qw(recursion uninitialized); \latex latex } \layout Standard Adicionalmente, podemos elevar el nivel de estas categorías para convertirlas en errores fatales. Por ejemplo, si queremos que si redefinimos alguna función (esto es, definimos dos funciones con el mismo nombre) Perl lance un error fatal en vez de redefinirla, podemos utilizar: \layout Quote \latex latex { \backslash tt \latex default use warnings FATAL => qw(redefine); \latex latex } \layout Standard Si definimos un comportamiento de warnings por pragma, éste tendrá precedencia sobre el comportamiento de la variable \latex latex { \backslash tt \latex default $^W \latex latex } \latex default o del switch \latex latex { \backslash tt \latex default -w \latex latex } \latex default . Sin embargo, si invocamos a Perl con el switch \latex latex { \backslash tt \latex default -W \latex latex } \latex default o con \latex latex { \backslash tt \latex default -X \latex latex } \latex default , éstos últimos tendrán precedencia. \layout Section Manejo de datos sucios ( \emph on tainted \emph default ) \layout Standard La mayor parte de los programas no se limitan a hacer un procesamiento de datos interno o a generar un conjunto de datos --- La mayor parte de los programas, más bien, toma un conjunto de datos de entrada y genera datos correspondientes de salida. Esto es natural, pero puede convertirse en problemático y peligroso cuando estos datos pueden afectar el proceso de ejecución de nuestro programa. \layout Standard Para información más detallada al respecto, les sugiero revisar la documentación oficial --- \begin_inset LatexCommand \cite{perlsec} \end_inset \layout Subsection ¿Qué son los datos sucios? \layout Standard Perl cuenta con un modo en el que nos reportará cualquier uso \emph on externo \emph default que demos a datos \emph on sucios \emph default sin antes \emph on limpiarlos \emph default , esto es, cualquier cosa que intentemos hacer que tenga efectos fuera de nuestro programa a datos externos no validados sin pasar por un proceso de validación. \layout Standard Clarificando un poco más, un dato es considerado sucio si: \layout Itemize Proviene de interacción directa con el usuario \layout Itemize Las variables de ambiente \layout Itemize Parámetros recibidos por una forma Web \layout Standard y Perl nos negará el utilizarlos para: \layout Itemize Utilizar estos datos en cualquier comando que invoque a un shell \layout Itemize Usar estos datos en un comando que modifique archivos o directorios \layout Itemize Emplear estos datos en un comando que interactúe con la tabla de procesos \layout Standard \emph on Negar utilizarlos \emph default significa que si intentamos efectuar una operación de este tipo con datos sucios, Perl lanzará una excepción en tiempo de ejecución, \begin_inset Quotes eld \end_inset matando \begin_inset Quotes erd \end_inset al proceso. \layout Subsection Activando el reporte de datos sucios \layout Standard Perl seguirá este comportamiento si: \layout Itemize Al correr el programa le indicamos \latex latex { \backslash tt \latex default perl -T programa.pl \latex latex } \layout Itemize En la primera línea de nuestro programa dice: \latex latex { \backslash tt \latex default #!/usr/bin/perl -T \latex latex } \layout Itemize Si el programa está corriendo con los bits \latex latex { \backslash tt \latex default SUID \latex latex } \latex default o \latex latex { \backslash tt \latex default SGID \latex latex } \latex default activados \layout Standard Una vez que entramos en modo \emph on tainted \emph default , ya no será posible salir de este modo. \layout Subsubsection Detectando datos sucios \layout Standard Para detectar datos sucios, podemos utilizar esta función (sugerida en \begin_inset LatexCommand \cite{perlsec} \end_inset ): \layout Quote \latex latex { \backslash tt \latex default sub is_tainted { \layout Quote \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ return ! eval { join ('', @_), kill 0; \layout Quote 1; \layout Quote }} \latex latex } \layout Standard Podemos también utilizar el módulo \latex latex { \backslash tt \latex default taint \latex latex } \latex default , disponible en el CPAN \begin_inset LatexCommand \cite{CPAN} \end_inset de la siguiente manera: \layout Standard \latex latex { \backslash tt \latex default use Taint; \layout Standard warn \begin_inset Quotes eld \end_inset Datos sucios \begin_inset Quotes erd \end_inset if tainted ($var1,@var2, $3var3, %var4); \layout Standard \latex latex } \layout Standard Evitando así posibles caídas del programa. \layout Standard Hay ciertos valores que siempre estarán sucios, pues provienen del mundo externo. Por ejemplo, el path de ejecución ( \latex latex { \backslash tt \latex default $ENV{PATH} \latex latex } \latex default es heredado, y Perl no tiene manera de saber si éste es seguro. Cualquier programa externo que ejecutemos desde Perl (con \latex latex { \backslash tt \latex default system() \latex latex } \latex default , \latex latex { \backslash tt \latex default exec \latex latex } \latex default , \latex latex { \backslash tt \latex default qx \latex latex } \latex default , comillas inversas, etc.) requiere que \latex latex { \backslash tt \latex default $ENV{PATH} \latex latex } \latex default esté limpio para permitir su ejecución. \layout Subsubsection Limpiando datos sucios \layout Standard Muy bien, sabemos de qué debemos cuidarnos. Ahora, ¿cómo podemos marcar un valor como limpio? La respuesta corta es que no podemos. La respuesta larga es que Perl nos permite extraer información respecto a un valor por medio de las instrucciones. Esto puede hacerse a través de las variables de substitución: \layout Quote \latex latex { \backslash tt \latex default $datos = ; \latex latex { \backslash scriptsize \latex default # Los datos vienen de fuera y están sucios \latex latex } \layout Quote if ( $datos =~ /^([ \backslash w \backslash b \backslash d]+)$/ ) { \latex latex { \backslash scriptsize \latex default # Acepta sólo el patrón que esperamos \latex latex } \layout Quote \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ $datos_limpio = $1; \latex latex { \backslash scriptsize \latex default # $1 contiene el texto que coincidió con la expresión \latex latex } \layout Quote } else { \layout Quote \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ die \begin_inset Quotes eld \end_inset No esperaba que me dijeras $datos \begin_inset Quotes erd \end_inset ; \layout Quote } \layout Quote \latex latex } \layout Standard En este ejemplo, \latex latex { \backslash tt \latex default $datos \latex latex } \latex default sigue teniendo datos sucios. De hecho, tal vez podríamos preferir que la última línea guardara los resultado s en la variable de origen. \layout Subsubsection Advertencia sobre la limpieza inconsciente \layout Standard Podríamos vernos tentados a hacer algo así: \layout Quote \latex latex { \backslash tt \latex default $datos = ; \layout Quote $datos =~ /^(.+)$/; \layout Quote $datos = $1; \latex latex } \layout Standard Sin embargo, el aceptar cualquier dato que recibamos hace inutil el que estemos utilizando \emph on Tainted \emph default . No es imposible que realmente queramos hacer algo así, pero sí es muy important e analizarlo si llegamos a encontarlo. \layout Standard La limpieza inconsciente puede hacernos más daño del que creemos. Muchos esquemas de seguridad en cómputo de todo tipo fallan al hacer creer al usuario que está completamente seguro, si bien son únicamente una ayuda para elevar la seguridad general del sistema. \layout Section Sugerencias para el uso de funciones \layout Standard Hay muchas sutilezas concernientes al uso de funciones. Los principales puntos a mi entender son: \layout Subsection Llamando funciones \layout Standard Si no utilizamos \latex latex { \backslash tt \latex default strict \latex latex } \latex default , Perl nos permitirá invocar a las funciones directamente, dando únicamente el nombre de la función. Esto puede llevar a confusiones a leer el código, y puede chocar con una palabra reservada en alguna futura versión de Perl. Las funciones serán llamadas preferiblemente como \latex latex { \backslash tt \latex default funcion() \latex latex } \latex default , como si tuvieran argumentos aún si no los tienen, indicando claramente que ese texto es una llamada a función. \layout Standard Mucha gente le agrega el prefijo \latex latex { \backslash tt \latex default & \latex latex } \latex default , lo cual es heredado de versiones anteriores de Perl. Si deciden utilizar esta sintaxis, es importante también poner explícita la lista de argumentos ( \latex latex { \backslash tt \latex default &funcion() \latex latex } \latex default ), aún si es una lista vacía, pues de no hacerlo así la función invocada heredará a la lista de argumentos de la función actual ( \latex latex { \backslash tt \latex default @_ \latex latex } \latex default ). \layout Subsection \begin_inset LatexCommand \label{rec_param} \end_inset Recibiendo parámetros \layout Standard Es muy común ver que la primera línea de una función es: \layout Quote \latex latex { \backslash tt \latex default my ($var1, $var2, $var3) = @_; \latex latex } \layout Standard o \layout Quote \latex latex { \backslash tt \latex default my $var1 = shift; my $var2 = shift; my $var3 = shift; \latex latex } \layout Standard Esta sintaxis es completamente correcta, sin embargo, si asumimos que la función fue llamada correctamente podemos terminar con parámetros con valor indefinido o ignorando argumentos. Es muy recomendable revisar cada uno de los parámetros que recibimos, buscando valores indefinidos, tipos de datos incorrectos (p.ej., texto cuando estamos esperando números, o un valor escalar cuando esperamos una referencia como veremos en \begin_inset LatexCommand \ref{ref} \end_inset ). El tener el tipo de datos incorrecto puede causar comportamiento errático y difícil de detectar. \layout Subsubsection Nota respecto al por qué de \latex latex { \backslash tt \latex default @_ \latex latex } \layout Standard Mucha gente se pregunta por qué Perl maneja el \emph on arreglo default \emph default \latex latex { \backslash tt \latex default @_ \latex latex } \latex default . ¿A qué me refiero? Lo explico con un par de ejemplos. En C declaramos una función de esta manera: \layout Quote \latex latex { \backslash tt \latex default int func (int var1, char* var2); \latex latex } \layout Standard En Python: \layout Quote \latex latex { \backslash tt \latex default def func (var1, var2): \latex latex } \layout Standard En PHP: \layout Quote \latex latex { \backslash tt \latex default function func ($var1, $var2) { (...) } \latex latex } \layout Standard Y así es prácticamente en cualquier lenguaje moderno. ¿Por qué en Perl tenemos que hacer malabares como lo comentábamos en la sección anterior ( \begin_inset LatexCommand \ref{rec_param} \end_inset )? \layout Standard Esto es, por más increíble que parezca, por diseño. En las primeras versiones de Perl no existían las variables léxicas. Al declarar una función con todo y los nombres de variables, esto impactaría en el espacio de nombres global. Y no es que los argumentos recibidos no tengan nombre --- Tienen un nombre claramente definido: El arreglo default, \latex latex { \backslash tt \latex default @_ \latex latex } \latex default . De hecho, si nuestra función va a ser corta y esto no hará menos legible nuestro código (y con mucho mayor razón si la llamamos frecuentemente), les recomiendo utilizar al arreglo default directamente dentro de sus funciones , ya que con esto ahorramos la creación y asignación de variables. Sí, esto puede ser una mejoría casi indetectable, pero a través de la repetició n, puede hacerse sensible. \layout Subsection Manejo de variables internas \layout Standard Esto lo hemos repetido ya varias veces. Es muy importante manejar tanto como nos sea posible todas las variables como léxicas (ámbito \latex latex { \backslash tt \latex default my \latex latex } \latex default ). Esto evitará que los datos se afecten a los de otras funciones, así como para optimizar el uso de la memoria. \layout Subsection \begin_inset LatexCommand \label{ref} \end_inset Cuidado al utilizar referencias - \family typewriter ref \layout Standard Al usar referencias en una función es importante revisar que sean efectivamente referencias, y que se refieran al tipo de datos indicado. Invariablemente es preferible regresar de la función con un error y permitir que el programa o la función que invocó maneje un error a que se genere un error en tiempo de ejecución que lleve a abortar el programa, o peor aún, manejar datos erróneos. \layout Standard Para detectar a tiempo estos errores, podemos recurrir a la función \latex latex { \backslash tt \latex default ref \latex latex } \latex default dela siguiente manera: \layout Standard \added_space_top 0.3cm \added_space_bottom 0.3cm \align center \begin_inset Tabular \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default $var \latex latex } \end_inset \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default ref($var) \latex latex } \end_inset \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default \backslash \backslash \backslash $algo \latex latex } \end_inset \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default 'REF' \latex latex } \end_inset \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default \backslash $datos \latex latex } \end_inset \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default 'SCALAR' \latex latex } \end_inset \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default \backslash @arr \latex latex } \latex default o \latex latex { \latex default [1, 2, 3] \latex latex } \end_inset \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default 'ARRAY' \latex latex } \end_inset \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default \backslash %hash \latex latex } \end_inset \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default 'HASH' \latex latex } \end_inset \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default \backslash &cosa \latex latex } \end_inset \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default 'CODE' \latex latex } \end_inset \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default \backslash *otro \latex latex } \end_inset \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default 'GLOB' \latex latex } \end_inset \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default $no_ref \latex latex } \end_inset \begin_inset Text \layout Standard \latex latex { \backslash tt \latex default '' \latex latex } \latex default (cadena vac'ia, no \latex latex { \backslash tt \latex default undef \latex latex } \latex default ) \end_inset \end_inset \layout Subsubsection Las referencias a \latex latex { \backslash tt \latex default GLOB \latex latex } \latex default s \layout Standard Un tipo especial de referencia es la de \latex latex { \backslash tt \latex default GLOB \latex latex } \latex default s --- A \emph on cualquier cosa \emph default . \layout Standard En los espacio de nombres no sólamente entran los tipos de datos que aparecen en la tabla anterior --- escalares, arreglos, hashes y código (subrutinas). Además de esto entran también los manipuladores de archivo ( \emph on filehandles \emph default ). Si queremos, por ejemplo, pasar un manipulador de archivo como argumento, la manera tradicional es hacerlo por medio de una referencia global: \latex latex { \backslash tt \latex default func(*STDOUT) \latex latex } \latex default . Esto convierte al primer argumento de \latex latex { \backslash tt \latex default func \latex latex } \latex default en un objeto de tipo \latex latex { \backslash tt \latex default IO::Handle \latex latex } \latex default . \layout Standard Sí, en su momento los \latex latex { \backslash tt \latex default GLOB \latex latex } \latex default s fueron una salida necesaria y elegante a una necesidad legítima del lenguaje. Sin embargo, hoy en día lo que mejor puede hacer un \latex latex { \backslash tt \latex default GLOB \latex latex } \latex default es confundirnos. Para pasar manipuladores de archivo entre funciones, sugiero utilizar la implementación nativa orientada a objetos de \latex latex { \backslash tt \latex default open \latex latex } \latex default , a través del paquete \latex latex { \backslash tt \latex default IO::Handle \latex latex } \latex default (o alguna de sus subclases, como \latex latex { \backslash tt \latex default IO::File \latex latex } \latex default o \latex latex { \backslash tt \latex default IO::Socket \latex latex } \latex default : \layout Quote \latex latex { \backslash tt \latex default use IO::File; \layout Quote if (necesito_abrir()) { \layout Quote \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ my $handle = new IO::File; \layout Quote \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ open($handle, 'archivo') or die $!; \layout Quote \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ procesa_archivo($handle); \layout Quote } \latex latex } \layout Standard En este caso, $handle tiene todos los atributos de una variable léxica: Se la podemos pasar a la función \latex latex { \backslash tt \latex default procesa_archivo \latex latex } \latex default como parámetro, se cierra y desaparece automáticamente al salir del bloque en el que la declaramos, etc. \layout Subsection Entregando resultados \layout Standard Al salir de una función, busquemos la manera más sencilla de regresar datos. Muchas veces será más fácil procesar los datos si resultados múltiples de una sola operación quedaran en una sola referencia a un arreglo o en la estructura lógica que elijamos a que si pasaran como varios valores escalares independientes. \layout Standard Toda función \emph on debe \emph default tener un valor o un procedimiento específico para reportar errores, con objeto de evitar que el programa asuma éxito en el proceso. \layout Section Sugerencias para el uso de objetos \layout Standard Perl 5 introdujo importantes ventajas sobre Perl 4. Probablemente la más importante de ellas sea el soporte de la programación orientada a objetos. Sin embargo, como veremos a continuación, la implementación de objetos de Perl no es ni completa ni limpia, si seguimos los criterios formales y tradicionales para definirlos. Utilizándolos bien como están implementados, sin embargo, puede ser muy cómodo y conveniente una vez que se dominan las particularidades. \layout Standard Para porder trabajar óptimamente con módulos, les sugiero leer las páginas referidas en \begin_inset LatexCommand \cite{perlobj} \end_inset , \begin_inset LatexCommand \cite{perltoot} \end_inset y \begin_inset LatexCommand \cite{perlbot} \end_inset . \layout Subsection Viviendo con una implementación \emph on parchada \emph default de objetos \layout Standard La sintaxis de los objetos en Perl muchas veces obliga al programador a escribir más de lo que lo haría en otros lenguajes, y para ojos no experimentad os el estilo no es muy claro, llevando a posibles confusiones. Por ejemplo, un atributo es llamado utilizando \latex latex { \backslash tt \latex default $obj->{atributo} \latex latex } \latex default , mientras que una llamada a método se hace con \latex latex { \backslash tt \latex default $obj->metodo() \latex latex } \latex default . Un error común es intentar hacer \latex latex { \backslash tt \latex default $obj->atributo \latex latex } \latex default , lo cual Perl entenderá como una llamada a un método. En caso de existir el método \latex latex { \backslash tt \latex default atributo \latex latex } \latex default , lo llamará causando probablemente un comportamiento inesperado. En caso de no existir, llevará a un error en tiempo de ejecución que abortará la ejecución de nuestro programa. \layout Standard En los lenguajes tradicionalmente orientados a objetos estamos acostumbrados a manejar atributos y métodos públicos y privados. Perl nos invita a no pensar de esta manera --- Perl nos invita a asumir todo como público. Citando a Larry Wall, \emph on te dejo entrar a mi casa, y sé que no te llevarás mis cosas porque confío en tí, no porque las haya escondido en el desván \emph default . Si bien sí hay manera de implementar tanto métodos como atributos privados, aunque parecen más magia negra y contorsionismo que llamadas. \layout Subsection Revisar atributos requeridos / opcionales \layout Standard Al crear un objeto, es importante revisar por un lado que tengamos todos los parámetros requeridos, y por otro lado que no nos hayan invocado con algún parámetro que no sepamos manejar. Para esto, sugiero incluir en sus métodos constructores: \layout Standard \latex latex { \backslash tt \latex default @necesarias = qw(color tamano tipo); \layout Standard $temporal{$_} = validas{$_} = 1 foreach (keys(%$self)); \layout Standard $validas{$_} = 1 foreach (qw(textura temperatura)); \layout Standard foreach (@necesarias) { \layout Standard \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ if (defined $temporal{$_}) { \layout Standard \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ delete $temporal{$_}; \layout Standard \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ } else { \layout Standard \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ die \begin_inset Quotes eld \end_inset Me falta $_ ! \begin_inset Quotes erd \end_inset ; \layout Standard \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ } \layout Standard } \layout Standard if (@tmp2 = keys(%temporal)) { \layout Standard \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ die \begin_inset Quotes eld \end_inset Elementos desconocidos: @tmp2 \begin_inset Quotes erd \end_inset ; \layout Standard } \latex latex } \layout Section Sugerencias para el uso de bibliotecas y módulos \layout Standard Un proyecto grande puede ser mucho mejor manejado si es construido utilizando módulos, dividiendo un programa en varios archivos separados. Esto tiene la ventaja adicional de simplifcar grandemente la reutilización de código. \layout Standard Además de modularizar nuestro código, en Perl utilizamos frecuentemente módulos ajenos, pues contamos con una gran cantidad de módulos, casi todos ellos contribuciones voluntarias de los usuarios del lenguaje, organizados en el CPAN ( \begin_inset LatexCommand \cite{CPAN} \end_inset ). \layout Standard Hay una sutil diferencia entre módulos y bibliotecas: Una biblioteca es únicamente una colección de funciones, en tanto que un módulo está diseñado para la orientación a objetos. Claro, se puede invocar a un módulo como a una biblioteca o al revés, pero el diseño favorece hacerlo de esta manera. Abundo al respecto en \begin_inset LatexCommand \ref{met_incl} \end_inset . \layout Subsection Paquetes y espacios de nombres \layout Standard Es práctica común ---y muy recomendable--- utilizar un espacio de nombres separado cuando utilizamos módulos. Esto nos ayuda a evitar que las funciones y variables globales que requiramos utilizar choquen con otras, definidas con el mismo nombre en el programa principal. El espacio de nombres por omisión es \latex latex { \backslash tt \latex default main \latex latex } \latex default , y al nombre completo de cualquier función o variable en Perl ( \latex latex { \backslash tt \latex default $var \latex latex } \latex default , \latex latex { \backslash tt \latex default &func \latex latex } \latex default , \latex latex { \backslash tt \latex default @arr \latex latex } \latex default ) se le antepone su paquete --- El nombre real de estos símbolos es en realidad \latex latex { \backslash tt \latex default $main::var \latex latex } \latex default , \latex latex { \backslash tt \latex default &main::func \latex latex } \latex default o \latex latex { \backslash tt \latex default @main::arr \latex latex } \latex default . Estos espacios de nombres se aplican a todo símbolo definido por el programador (variables de cualquier tipo, función, manipuladores de archivo, etc). Si especificamos un espacio de nombres nulo (p. ej., \latex latex { \backslash tt \latex default $::var \latex latex } \latex default ), es equivalente a referirnos explícitamente a \latex latex { \backslash tt \latex default $main::var \latex latex } \latex default . \layout Standard Con el comando \latex latex { \backslash tt \latex default package \latex latex } \latex default cambiamos el espacio de nombres en el que estamos trabajando, como vemos a continuación. \layout Quote \latex latex { \backslash tt \latex default $var = 'valor'; \layout Quote $Otro::var = 250; \layout Quote print $var; \latex latex { \backslash scriptsize \latex default # valor \latex latex } \layout Quote package Otro; \layout Quote print $var; \latex latex { \backslash scriptsize \latex default # 250 \latex latex } \layout Quote print $main::var; \latex latex { \backslash scriptsize \latex default # Siempre será valor \latex latex } \layout Quote print $Otro::var; \latex latex { \backslash scriptsize \latex default # Siempre será 250 \latex latex } \layout Quote print $::var; \latex latex { \backslash scriptsize \latex default # Siempre será valor \latex latex }} \layout Standard Las variables léxicas (aquellas declaradas con \latex latex { \backslash tt \latex default my \latex latex } \latex default ) \emph on no \emph default son afectadas por los paquetes. \layout Subsection \begin_inset LatexCommand \label{met_incl} \end_inset Métodos para la inclusión de módulos y bibliotecas \layout Standard Hay tres métodos para incluir archivos de código: \latex latex { \backslash tt \latex default do \latex latex } \latex default , \latex latex { \backslash tt \latex default require \latex latex } \latex default y \latex latex { \backslash tt \latex default use \latex latex } \latex default . Los archivos incluidos con los dos primeros son bibliotecas, mientras que los incluidos con \latex latex { \backslash tt \latex default use \latex latex } \latex default son módulos. \layout Standard Podemos utilizar los tres siguientes métodos para incluir código: \layout Subsubsection \latex latex { \backslash tt \latex default do \latex latex } \layout Standard Su efecto es exactamente el de incluir el texto del archivo a ser incluído en el punto exacto de la ejecución en que es llamado. Citando a la definición de \latex latex { \backslash tt \latex default do \latex latex } \latex default ( \begin_inset LatexCommand \cite{perlfunc} \end_inset ), incluir código de esta manera ( \latex latex { \backslash tt \latex default do ' \emph on archivo.pl \emph default '; \latex latex } \latex default ) es equivalente (aunque más eficiente) a hacer \latex latex { \backslash tt \latex default scalar eval `cat \emph on archivo.pl \emph default `; \latex latex } \latex default . Cada vez que encontramos un \latex latex { \backslash tt \latex default do \latex latex } \latex default , el archivo es nuevamente evaluado, por lo cual no nos conviene llamarlo desde dentro de un ciclo. \layout Standard El valor que regresa la inclusión del archivo es el de la última expresión evaluada en el archivo. En caso de no poderlo incluir, el valor retornado será \latex latex { \backslash tt \latex default undef \latex latex } \latex default , y en la variable especial \latex latex { \backslash tt \latex default $! \latex latex } \latex default el código de error. En caso de poderlo leer pero de no poder ser compilado exitosamente, recibimos \latex latex { \backslash tt \latex default undef \latex latex } \latex default , y en la variable \latex latex { \backslash tt \latex default $@ \latex latex } \latex default recibimos el error. \layout Standard \latex latex { \backslash tt \latex default do \latex latex } \latex default es utilizado normalmente para leer archivos de configuración. Robando nuevamente de la documentación ( \begin_inset LatexCommand \cite{perlfunc} \end_inset ): \layout Standard \latex latex { \backslash tt \latex default unless ($return = do '/usr/local/etc/myconf') { \layout Standard \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ warn "couldn't parse $file: $@" if $@; \layout Standard \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ warn "couldn't do $file: $!" unless defined $return; \layout Standard \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ \SpecialChar ~ warn "couldn't run $file" unless $return; \layout Standard } \latex latex } \layout Subsubsection \latex latex { \backslash tt \latex default require \latex latex } \layout Standard \latex latex { \backslash tt \latex default require \latex latex } \latex default va un poco más allá que \latex latex { \backslash tt \latex default do \latex latex } \latex default . Las principales diferencias son: \layout Itemize El archivo a incluir debe existir. De no existir, se genera un error en tiempo de ejecución y Perl aborta la ejecución. \layout Itemize La última expresión evaluada en el archivo debe ser verdadera ---En caso de no ser así, la ejecución del programa terminará con el mensaje \latex latex { \backslash tt \emph on \latex default biblioteca \emph default did not return a true value \latex latex } \latex default . Por esta razón, es común que la última instrucción de una biblioteca sea \latex latex { \backslash tt \latex default 1; \latex latex } \latex default . \layout Itemize El archivo será evaluado y ejecutado una sola vez. Al incluir un archivo con \latex latex { \backslash tt \latex default require \latex latex } \latex default , su nombre es agregado al arreglo \latex latex { \backslash tt \latex default %INC \latex latex } \latex default , y si existe ya el archivo en cuestión, no es incluido nuevamente. \layout Itemize Si el argumento que damos a \latex latex { \backslash tt \latex default require \latex latex } \latex default es una palabra suelta ( \emph on bareword \emph default ), Perl buscará el archivo fuente en todos los directorios especificados en \latex latex { \backslash tt \latex default @INC \latex latex } \latex default , asume la extensión \latex latex { \backslash tt \latex default .pm \latex latex } \latex default y substituye los caracteres \latex latex { \backslash tt \latex default :: \latex latex } \latex default por \latex latex { \backslash tt \latex default / \latex latex } \latex default . Si damos el argumento como una cadena o por medio de una variable, si bien Perl sí busca en \latex latex { \backslash tt \latex default @INC \latex latex } \latex default , estas substituciones no se hacen. \layout Itemize Si el argumento que damos a \latex latex { \backslash tt \latex default require \latex latex } \latex default es numérico, la ejecución se abortará si la versión de Perl es menor a la especificada. \layout Subsubsection \latex latex { \backslash tt \latex default use \latex latex } \layout Standard Este método de inclusión nace con Perl 5, y está pensado para su uso con objetos. Al incluir un archivo con \latex latex { \backslash tt \latex default use \latex latex } \latex default , en adición al comportamiento de \latex latex { \backslash tt \latex default require \latex latex } \latex default , presenta las siguientes características: \layout Itemize La inclusión se hace al tiempo de compilación, no al tiempo de ejecución. El código incluido con \latex latex { \backslash tt \latex default use \latex latex } \latex default , aún si son incluidos en la última línea, podrá ser utilizado desde la primera. \layout Itemize Es \emph on indispensable \emph default que el argumento de \latex latex { \backslash tt \latex default use \latex latex } \latex default sea un \emph on bareword \emph default . \layout Itemize Se puede especificar, después del nombre del módulo, una lista de funciones a ser importadas al espacio de nombres del invocador. Se puede solicitar explícitamente que no sea modificado nuestro espacio de nombres suministrando una lista vacía. \layout Itemize Dada la flexibilidad de la sintaxis de \latex latex { \backslash tt \latex default use \latex latex } \latex default , lo utilizamos también para la activación de pragmas. \layout Itemize Si un módulo proporciona la función \latex latex { \backslash tt \latex default unimport \latex latex } \latex default , podemos liberar nuestro espacio de nombres de funcionalidad concerniente a dicho módulo utilizando \latex latex { \backslash tt \latex default no \emph on modulo \emph default ( \emph on lista \emph default ) \latex latex } \latex default . \layout Standard Sugiero leer la sección respecto a \latex latex { \backslash tt \latex default use \latex latex } \latex default en la documentación de Perl ( \begin_inset LatexCommand \cite{perlfunc} \end_inset ), así como la documentación respecto a los objetos ( \begin_inset LatexCommand \cite{perlmod} \end_inset ). \layout Subsection Los módulos y el comportamiento del compilador \layout Standard Si definimos algún pragma dentro de uno de nuestros módulos o bibliotecas (o del mismo programa central), el comportamiento que este pragma defina \emph on no será heredado \emph default por ningún otro de los archivos que utilicemos. Los pragmas deberán ser incluídos en cada uno de nuestros archivos si deseamos utilizarlos. \layout Section Compartimientos restringidos: El módulo \latex latex { \backslash tt \latex default Safe \latex latex } \latex default (visto desde arriba) \layout Standard Si no confiamos en el código de determinado programa, por lo que queremos correrlo imponiéndole ciertas restricciones de seguridad, podemos acudir a los compartimientos restringidos que nos proporciona el módulo \latex latex { \backslash tt \latex default Safe \latex latex } \latex default , parte de la distribución estándar de Perl. Sugiero leer su página de manual ( \begin_inset LatexCommand \cite{Safe} \end_inset ). \layout Standard Para crear un compartimento restringido: \layout Quote \latex latex { \backslash tt \latex default use Safe; \layout Quote $compart = new Safe; \latex latex } \layout Subsection Espacio de nombres restringido \layout Standard Podemos definir un espacio de nombres al que esté limitado el código a ejecutar, sin permiso de interactuar con ningún símbolo localizado fuera de éste. Para intercambiar datos con el código que esté dentro del compartimiento, podemos utilizar las variables default ( \latex latex { \backslash tt \latex default $_ \latex latex } \latex default , \latex latex { \backslash tt \latex default @_ \latex latex } \latex default , \latex latex { \backslash tt \latex default %_ \latex latex } \latex default ), así como las que le declaremos explícitamente al crear el compartimiento como variables compartibles. \layout Standard El espacio de nombres por omisión es \latex latex { \backslash tt \latex default Safe::Root0 \latex latex } \latex default para el primer compartimiento, \latex latex { \backslash tt \latex default Safe::Root1 \latex latex } \latex default para el segundo, etc. Para interrogar a un compartimiento acerca del espacio en que está corriendo, utilizamos el método \latex latex { \backslash tt \latex default root \latex latex } \latex default . \layout Standard Podemos especificar el espacio de nombres que queremos que use el compartimiento llamándolo así: \layout Quote \latex latex { \backslash tt \latex default $compart = new Safe 'escondido'; \layout Quote print $compart->root; \latex latex } \layout Standard Esto causa que el espacio de nombres que utilice sea \latex latex { \backslash tt \latex default escondido \latex latex } \latex default , que es lo que nos imprime. \layout Subsection Máscaras de Opcodes \layout Standard Una manera de controlar la ejecución de código es limitando las operaciones que podrán ser utilizadas por él. Si usamos un compartimento restringido, podemos especificar qué Opcodes serán válidos en el código, y abortar la ejecución en caso de incluir algún Opcode marcado como inválido. La máscara por omisión es \latex latex { \backslash tt \latex default :default \latex latex } \latex default , permitir todos los Opcodes. \layout Standard Se designa \emph on Opcode \emph default al código de las diferentes acciones que pude realizar Perl, traducidas ya a un formato intermedio al realizar la compilación. \layout Standard Este tema va más allá del alcance de este texto, para mayor información al respecto sugiero consultar la página de manual referente a los opcodes ( \begin_inset LatexCommand \cite{Opcode} \end_inset ). \layout Subsection De qué \emph on no \emph default nos protege \latex latex { \backslash tt \latex default Safe \latex latex } \layout Standard Como cualquier herramienta de seguridad, \latex latex { \backslash tt \latex default Safe \latex latex } \latex default es muy útil, mas no es la panacea --- y es muy importante saber sus límites. El manual de \latex latex { \backslash tt \latex default Safe \latex latex } \latex default ( \begin_inset LatexCommand \cite{Safe} \end_inset ) nos menciona los siguientes casos en los que no nos será de gran ayuda. Algunos de estos incisos, claro, pueden ser evitados prohibiendo el Opcode correspondiente, pero es muy difícil considerar todos los casos. \layout Itemize Código que agote los recursos, como un simple \latex latex { \backslash tt \latex default while (1) {} \latex latex } \latex default . \layout Itemize Código que espíe y envíe información del sistema a algún otro lugar. \layout Itemize Generar señales que afecten a la ejecución del programa, aprovechando manejadore s de señales deficientemente construidos \layout Itemize Operaciones que afectan al programa entero (por ejemplo, \latex latex { \backslash tt \latex default chdir \latex latex } \latex default ). \layout Itemize La verificación se hace a la hora de compilación, por lo que un \latex latex { \backslash tt \latex default eval \begin_inset Quotes eld \end_inset \emph on (...) \emph default \begin_inset Quotes erd \end_inset \latex latex } \latex default no sufrirá las restricciones relativas a Opcodes. \layout Section Si persisten las molestias... \layout Standard Perl tiene una muy gran cantidad de recursos en línea. Además de las referencias al final de este documento, les sugiero asomarse a los siguientes recursos: \layout Itemize Lista de discusión del grupo de usuarios de Perl en México, \latex latex { \backslash tt \latex default perl@tlali.iztacala.unam.mx \latex latex } \latex default (página de información: \latex latex { \backslash tt \latex default http://tlali.iztacala.unam.mx/mailman/listinfo/perl \latex latex } \layout Itemize \latex latex { \backslash tt \latex default http://www.perl.org \latex latex } \layout Itemize \latex latex { \backslash tt \latex default http://www.perl.com \latex latex } \layout Itemize \latex latex { \backslash tt \latex default http://use.perl.org \latex latex } \layout Itemize \latex latex { \backslash tt \latex default http://www.pm.org \latex latex } \layout Standard Y muchas más :-) \layout Bibliography \bibitem {CPAN} CPAN \layout Bibliography \bibitem {compilacion} Compilación de scripts de Perl: Módulos B, O y script perlcc \layout Bibliography \bibitem {strict} Página de manual \latex latex { \backslash tt \latex default perldoc strict \latex latex } \latex default --- Pragma para restringir construcciones inseguras (instalación default de Perl) \layout Bibliography \bibitem {perlref} Página de manual \latex latex { \backslash tt \latex default perldoc perlref \latex latex } \latex default --- Manejo de referencias y estructuras de datos anidadas (instalación default de Perl) \layout Bibliography \bibitem {perllexwarn} Página de manual \latex latex { \backslash tt \latex default perldoc perllexwarn \latex latex } \latex default --- Reporte léxico de advertencias (instalación default de Perl >= 5.6) \layout Bibliography \bibitem {perlsec} Página de manual \latex latex { \backslash tt \latex default perldoc perlsec \latex latex } \latex default --- Seguridad en Perl (instalación default de Perl) \layout Bibliography \bibitem {perlobj} Página de manual \latex latex { \backslash tt \latex default perldoc perlobj \latex latex } \latex default ---Objetos en Perl (parte de la instalación default de Perl) \layout Bibliography \bibitem {perltoot} Página de manual \latex latex { \backslash tt \latex default perldoc perltoot \latex latex } \latex default --- Tutorial de Perl orientado a objetos (instalación default de Perl) \layout Bibliography \bibitem {perlbot} Página de manual \latex latex { \backslash tt \latex default perldoc perlbot \latex latex } \latex default --- \begin_inset Quotes eld \end_inset Bolsa de trucos \begin_inset Quotes erd \end_inset para la programación orientada a objetos (instalación default de Perl) \layout Bibliography \bibitem {perlfunc} Página de manual \latex latex { \backslash tt \latex default perldoc perlfunc \latex latex } \latex default --- Funciones internas de Perl (instalación default de Perl) \layout Bibliography \bibitem {perlmod} Página de manual \latex latex { \backslash tt \latex default perldoc perlmod \latex latex } \latex default --- Módulos de Perl: Paquetes y tablas de símbolos (instalación default de Perl) \layout Bibliography \bibitem {Safe} Página de manual \latex latex { \backslash tt \latex default perldoc Safe \latex latex } \latex default --- Módulo Safe (instalación default de Perl) \layout Bibliography \bibitem {Opcode} Página de manual \latex latex { \backslash tt \latex default perldoc Opcode \latex latex } \latex default --- Códigos de operación en el formato intermedio de compilación (instalación default de Perl) \the_end