Ciclón (lenguaje de programación)
El lenguaje de programación Cyclone pretende ser un dialecto seguro del lenguaje C. Cyclone está diseñado para evitar desbordamientos de búfer y otras vulnerabilidades que son posibles en los programas C, sin perder el poder y la conveniencia de C como herramienta para la programación del sistema.
El desarrollo de Cyclone se inició como un proyecto conjunto de AT&T Labs Research y el grupo de Greg Morrisett en Cornell en 2001. La versión 1.0 se lanzó el 8 de mayo de 2006.
Características del idioma
Cyclone intenta evitar algunas de las trampas comunes de C, mientras mantiene su aspecto y rendimiento. Con este fin, Cyclone impone los siguientes límites a los programas:
NULL
se insertan cheques para evitar fallos de segmentación- Aritmética puntero es limitado
- Los punteros deben ser inicializados antes del uso (esto se aplica mediante un análisis de asignación definido)
- Los punteros se evitan mediante análisis de regiones y límites libres()
- Sólo se admiten castas y sindicatos "seguros"
- Goto into scopes is disallowed
- las etiquetas de conmutación en diferentes ámbitos están desactivadas
- Funciones de devolución de punteros deben ejecutar
return
- setjmp y longjmp no son compatibles
Para mantener el conjunto de herramientas al que están acostumbrados los programadores de C, Cyclone ofrece las siguientes extensiones:
- Nunca...
NULL
Los punteros no requierenNULL
cheques - "Fat" punteros soporte puntero aritmético con plazos de ejecución comprobando
- Las regiones cultivables apoyan una forma de gestión de memoria manual segura
- Coleccion de basura para valores heap-allocated
- Los sindicatos etiquetados apoyan argumentos variando tipo
- Las inyecciones ayudan a automatizar el uso de uniones etiquetadas para programadores
- El polimorfismo reemplaza algunos usos del vacío *
- varargs se implementan como punteros de grasa
- Las excepciones reemplazan algunos usos de
setjmp
ylongjmp
Para obtener una mejor introducción de alto nivel a Cyclone, el razonamiento detrás de Cyclone y la fuente de estas listas, consulte este documento.
Cyclone, en general, se parece mucho a C, pero debe verse como un lenguaje similar a C.
Tipos de puntero
Cyclone implementa tres tipos de puntero:
*
(el tipo normal)@
(el nunca...NULL
puntero), y?
(el único tipo con puntero aritmético permitido, punteros "fat").
El propósito de presentar estos nuevos tipos de punteros es evitar problemas comunes al usar punteros. Tomemos, por ejemplo, una función llamada foo
que lleva un puntero a un int:
int Foo()int *);
Aunque la persona que escribió la función foo
podría haber insertado comprobaciones NULL
, supongamos que no lo hizo por razones de rendimiento. Llamar a foo(NULL);
dará como resultado un comportamiento indefinido (por lo general, aunque no necesariamente, se envía una señal SIGSEGV a la aplicación). Para evitar este tipo de problemas, Cyclone introduce el tipo de puntero @
, que nunca puede ser NULL
. Por lo tanto, la "caja fuerte" la versión de foo
sería:
int Foo()int @);
Esto le dice al compilador de Cyclone que el argumento para foo
nunca debe ser NULL
, evitando el comportamiento indefinido mencionado anteriormente. El simple cambio de *
a @
evita que el programador tenga que escribir comprobaciones NULL
y que el sistema operativo tenga que interceptar NULL
desreferencias de puntero. Sin embargo, este límite adicional puede ser un obstáculo bastante grande para la mayoría de los programadores de C, que están acostumbrados a poder manipular sus punteros directamente con la aritmética. Aunque esto es deseable, puede conducir a desbordamientos de búfer y otros errores de estilo 'off-by-one'. Para evitar esto, el tipo de puntero ?
está delimitado por un límite conocido, el tamaño de la matriz. Aunque esto agrega sobrecarga debido a la información adicional almacenada sobre el puntero, mejora la seguridad y la protección. Tomemos, por ejemplo, una función strlen
simple (e ingenua), escrita en C:
int strlen()const char *s) {} int iter = 0; si ()s == NULL) retorno 0; mientras ()s[iter] ! '0') {} iter++; } retorno iter; }
Esta función asume que la cadena que se pasa termina en NULL (''). Sin embargo, ¿qué pasaría si char buf[6] = {'h','e','l','l','o','!'};
a esta cadena? Esto es perfectamente legal en C, pero causaría que strlen
itere a través de la memoria no necesariamente asociada con la cadena s
. Hay funciones, como strnlen
que se pueden usar para evitar tales problemas, pero estas funciones no son estándar con todas las implementaciones de ANSI C. La versión Cyclone de strlen
no es tan diferente de la versión C:
int strlen()const char ? s) {} int iter, n = s.tamaño; si ()s == NULL) retorno 0; para ()iter = 0; iter . n; iter++, s++) {} si ()*s == '0') retorno iter; } retorno n; }
Aquí, strlen
se limita a sí mismo por la longitud de la matriz que se le pasa, por lo que no supera la longitud real. Cada uno de los tipos de tipo de puntero se puede convertir de forma segura a cada uno de los demás, y el compilador convierte automáticamente las matrices y las cadenas a ?
. (La conversión de ?
a *
invoca una verificación de límites, y la conversión de ?
a @
invoca tanto un NULL
verificación y una verificación de límites. La conversión de *
a ?
da como resultado ninguna verificación; el puntero ?
resultante tiene una tamaño de 1.)
Indicadores colgantes y análisis de regiones
Considere el siguiente código, en C:
char *itoa()int i) {} char buf[20]; sprintf()buf,"%d",i); retorno buf; }
La función itoa
asigna una matriz de caracteres buf
en la pila y devuelve un puntero al inicio de buf
. Sin embargo, la memoria utilizada en la pila para buf
se desasigna cuando la función regresa, por lo que el valor devuelto no se puede usar de manera segura fuera de la función. Si bien gcc y otros compiladores advertirán sobre dicho código, lo siguiente normalmente se compilará sin advertencias:
char *itoa()int i) {} char buf[20] *z; sprintf()buf,"%d",i); z = buf; retorno z; }
gcc puede generar advertencias para dicho código como un efecto secundario de la opción -O2 o -O3, pero no hay garantías de que se detecten todos esos errores.
Cyclone realiza un análisis regional de cada segmento de código, evitando punteros colgantes, como el que devuelve esta versión de itoa
. Todas las variables locales en un ámbito determinado se consideran parte de la misma región, separadas del montón o de cualquier otra región local. Por lo tanto, al analizar itoa
, el compilador de Cyclone vería que z
es un puntero a la pila local y reportaría un error.
Contenido relacionado
Mente cargando
Información general
Protocolo ligero de acceso a directorios