stringtranslate.com

Comprobación de límites

En programación de computadoras , la verificación de límites es cualquier método para detectar si una variable está dentro de algunos límites antes de usarse. Generalmente se usa para garantizar que un número se ajuste a un tipo determinado (verificación de rango), o que una variable que se utiliza como índice de matriz esté dentro de los límites de la matriz (verificación de índice). Una verificación de límites fallida generalmente resulta en la generación de algún tipo de señal de excepción .

Como realizar la verificación de límites durante cada uso puede llevar mucho tiempo, no siempre se hace. La eliminación de verificación de límites es una técnica de optimización del compilador que elimina la verificación de límites innecesaria.

Comprobación de rango

Una verificación de rango es una verificación para asegurarse de que un número esté dentro de un rango determinado; por ejemplo, para garantizar que un valor que está a punto de asignarse a un entero de 16 bits esté dentro de la capacidad de un entero de 16 bits (es decir, compararlo con el ajuste envolvente ). Esto no es exactamente lo mismo que la verificación de tipos . [ ¿cómo? ] Otras comprobaciones de alcance pueden ser más restrictivas; por ejemplo, se puede declarar que una variable que contenga el número de un mes calendario acepte solo el rango de 1 a 12.

Comprobación de índice

La verificación de índice significa que, en todas las expresiones que indexan una matriz, el valor del índice se compara con los límites de la matriz (que se establecieron cuando se definió la matriz) y, si el índice está fuera de los límites, se suspende la ejecución posterior a través de algún tipo de error. Debido a que leer o especialmente escribir un valor fuera de los límites de una matriz puede provocar un mal funcionamiento del programa, un bloqueo o habilitar vulnerabilidades de seguridad (ver desbordamiento del búfer ), la verificación de índices es parte de muchos lenguajes de alto nivel .

Los primeros lenguajes de programación compilados con capacidad de verificación de índices incluían ALGOL 60 , ALGOL 68 y Pascal , así como lenguajes de programación interpretados como BASIC .

Muchos lenguajes de programación, como C , nunca realizan comprobaciones automáticas de límites para aumentar la velocidad. Sin embargo, esto deja sin detectar muchos errores puntuales y desbordamientos del búfer . Muchos programadores creen que estos lenguajes sacrifican demasiado para una ejecución rápida. [1] En su conferencia del Premio Turing de 1980, CAR Hoare describió su experiencia en el diseño de ALGOL 60 , un lenguaje que incluía la verificación de límites, diciendo:

Una consecuencia de este principio es que cada aparición de cada subíndice de cada variable con subíndice se verificó en cada ocasión en tiempo de ejecución con los límites declarados superior e inferior de la matriz. Muchos años después, preguntamos a nuestros clientes si deseaban que les ofreciéramos una opción para desactivar estas comprobaciones en aras de la eficiencia en las series de producción. Unánimemente, nos instaron a no hacerlo; ya sabían con qué frecuencia ocurren errores de subíndice en las ejecuciones de producción, donde no detectarlos podría ser desastroso. Observo con miedo y horror que ni siquiera en 1980 los diseñadores y usuarios del lenguaje han aprendido esta lección. En cualquier rama respetable de la ingeniería, el incumplimiento de tales precauciones elementales habría sido ilegal durante mucho tiempo.

Los lenguajes convencionales que imponen la verificación del tiempo de ejecución incluyen Ada , C# , Haskell , Java , JavaScript , Lisp , PHP , Python , Ruby , Rust y Visual Basic . Los lenguajes D y OCaml tienen límites de tiempo de ejecución que verifican si están habilitados o deshabilitados con un modificador del compilador. En C++, la verificación del tiempo de ejecución no es parte del lenguaje, sino parte del STL y se habilita con un modificador del compilador (_GLIBCXX_DEBUG=1 o _LIBCPP_DEBUG=1). C# también admite regiones inseguras : secciones de código que (entre otras cosas) suspenden temporalmente la verificación de límites para aumentar la eficiencia. Son útiles para acelerar pequeños cuellos de botella en los que el tiempo es crítico sin sacrificar la seguridad de todo un programa.

El lenguaje de programación JS++ es capaz de analizar si un índice de matriz o clave de mapa está fuera de los límites en el momento de la compilación utilizando tipos existentes, que es un tipo nominal que describe si el índice o la clave está dentro o fuera de los límites y guía la generación de código. Se ha demostrado que los tipos existentes añaden solo 1 ms de sobrecarga a los tiempos de compilación. [2]

Comprobación de límites de hardware

La seguridad agregada por la verificación de límites necesariamente cuesta tiempo de CPU si la verificación se realiza en software; sin embargo, si las comprobaciones se pueden realizar mediante hardware, entonces la seguridad se puede proporcionar "gratis" sin coste de tiempo de ejecución. Uno de los primeros sistemas con verificación de límites de hardware fue la computadora central de la serie ICL 2900 anunciada en 1974. [3] La computadora VAX tiene una instrucción de ensamblaje INDEX para la verificación del índice de matriz que requiere seis operandos, todos los cuales pueden usar cualquier modo de direccionamiento VAX. La B6500 y computadoras Burroughs similares realizaron comprobaciones vinculantes mediante hardware, independientemente del lenguaje de computadora que se hubiera compilado para producir el código de máquina. Un número limitado de CPU posteriores tienen instrucciones especializadas para comprobar límites, por ejemplo, la instrucción CHK2 en la serie Motorola 68000 .

Se han realizado investigaciones desde al menos 2005 sobre métodos para utilizar la unidad de administración de memoria virtual incorporada de x86 para garantizar la seguridad de los accesos a la matriz y al búfer. [4] En 2015, Intel proporcionó sus extensiones Intel MPX en su arquitectura de procesador Skylake que almacena límites en un registro de CPU y una tabla en la memoria. A principios de 2017, al menos GCC admite extensiones MPX.

Ver también

Referencias

  1. ^ Cowan, C; Wagle, F; Calton Pu; Beattie, S; Walpole, J (1999). "Desbordamientos de búfer: ataques y defensas para la vulnerabilidad de la década". Actas Conferencia y exposición sobre supervivencia de la información de DARPA. DISCEX'00 . vol. 2. págs. 119-129. doi :10.1109/DISCEX.2000.821514. ISBN 978-0-7695-0490-2. S2CID  167759976.
  2. ^ "JS++ 0.9.0: Análisis eficiente del tiempo de compilación de errores fuera de límites - Blog de JS++". 11 de enero de 2019. Archivado desde el original el 12 de enero de 2019.
  3. ^ Hebilla JK (1978). La serie ICL 2900 (PDF) . Serie de informática de Macmillan. págs.17, 77. ISBN 978-0-333-21917-1. Archivado desde el original (PDF) el 20 de abril de 2018 . Consultado el 20 de abril de 2018 .
  4. ^ Lap-Chung Lam; Tzi-Cker Chiueh (2005). "Comprobación de la infracción del límite de matriz mediante hardware de segmentación". 2005 Conferencia internacional sobre sistemas y redes confiables (DSN'05) . págs. 388–397. doi :10.1109/DSN.2005.25. ISBN 0-7695-2282-3. S2CID  6278708.

enlaces externos