Ciclone (linguagem de programação)
A linguagem de programação Cyclone pretende ser um dialeto seguro da linguagem C. O Cyclone foi projetado para evitar estouros de buffer e outras vulnerabilidades possíveis em programas C, sem perder o poder e a conveniência do C como ferramenta para programação do sistema.
O desenvolvimento do Cyclone foi iniciado como um projeto conjunto da AT&T Labs Research e do grupo de Greg Morrisett na Cornell University em 2001. A versão 1.0 foi lançada em 8 de maio de 2006.
Recursos de linguagem
O Cyclone tenta evitar algumas das armadilhas comuns do C, mantendo sua aparência e desempenho. Para esse fim, o Cyclone impõe os seguintes limites aos programas:
NULL
verificações são inseridas para evitar falhas de segmentação- A aritmética de ponteiro é limitada
- Os ponteiros devem ser inicializados antes do uso (isso é aplicado pela análise de atribuição definida)
- Os ponteiros de estrangulamento são impedidos através da análise da região e dos limites
free()
- Apenas os moldes e sindicatos "seguros" são permitidos
- goto em escopos é desalvado
- etiquetas de interruptor em diferentes escopos são desalvados
- Funções de retorno de ponteiros devem executar
return
- setjmp e longjmp não são suportados
Para manter o conjunto de ferramentas com o qual os programadores C estão acostumados, o Cyclone fornece as seguintes extensões:
- Nunca...
NULL
ponteiros não exigemNULL
verificações - Os ponteiros "Fat" suportam aritmética ponteiro com verificação de limites de tempo de execução
- Regiões cultivadas suportam uma forma de gestão de memória manual segura
- Coleta de lixo para valores heap-allocated
- Tagged unions support type-varying arguments
- As injeções ajudam a automatizar o uso de sindicatos marcados para programadores
- O polimorfismo substitui alguns usos do vazio *
- varargs são implementados como ponteiros de gordura
- Exceções substituem alguns usos de
setjmp
elongjmp
Para uma melhor introdução de alto nível ao Cyclone, o raciocínio por trás do Cyclone e a fonte dessas listas, consulte este artigo.
Cyclone se parece, em geral, com C, mas deve ser visto como uma linguagem semelhante a C.
Tipos de ponteiro
O Cyclone implementa três tipos de ponteiro:
*
(o tipo normal)@
(o nunca...NULL
ponteiro), e?
(o único tipo com aritmética ponteiro permitido, ponteiros "fat").
O objetivo de introduzir esses novos tipos de ponteiro é evitar problemas comuns ao usar ponteiros. Tomemos, por exemplo, uma função chamada foo
que leva um ponteiro para um int:
- Não. Foo(- Não. *);
Embora a pessoa que escreveu a função foo
pudesse ter inserido verificações NULL
, vamos assumir que por motivos de desempenho não o fez. Chamar foo(NULL);
resultará em um comportamento indefinido (normalmente, embora não necessariamente, um sinal SIGSEGV sendo enviado ao aplicativo). Para evitar tais problemas, o Cyclone introduz o tipo de ponteiro @
, que nunca pode ser NULL
. Assim, o "seguro" versão de foo
seria:
- Não. Foo(- Não. @);
Isso diz ao compilador Cyclone que o argumento para foo
nunca deve ser NULL
, evitando o comportamento indefinido mencionado anteriormente. A simples mudança de *
para @
evita que o programador tenha que escrever verificações NULL
e o sistema operacional de ter que interceptar NULL
desreferências de ponteiro. Esse limite extra, no entanto, pode ser um grande obstáculo para a maioria dos programadores C, que estão acostumados a manipular seus ponteiros diretamente com aritmética. Embora isso seja desejável, pode levar a estouros de buffer e outros erros do estilo "off-by-one". Para evitar isso, o tipo de ponteiro ?
é delimitado por um limite conhecido, o tamanho do array. Embora isso acrescente sobrecarga devido às informações extras armazenadas sobre o ponteiro, ele melhora a segurança. Tomemos, por exemplo, uma função strlen
simples (e ingênua), escrita em C:
- Não. Esforços(Não. Charlie. *S) ( - Não. Eu... = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 0; se (S - Sim. NULL) retorno 0; enquanto (SNão.Eu...] ! '') ( Eu...++; ? retorno Eu...; ?
Esta função assume que a string que está sendo passada é terminada por NULL
(''
). No entanto, o que aconteceria se char buf[6] = {'h','e','l','l','o',' !'};
foram passados para esta string? Isso é perfeitamente legal em C, mas faria strlen
iterar através da memória não necessariamente associada à string s
. Existem funções, como strnlen
que podem ser usadas para evitar tais problemas, mas essas funções não são padrão em todas as implementações de ANSI C. A versão Cyclone de strlen
não é tão diferente da versão C:
- Não. Esforços(Não. Charlie. ? S) ( - Não. Eu..., n = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = S.tamanho; se (S - Sim. NULL) retorno 0; para (Eu... = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 0; Eu... < n; Eu...++, S++) ( se (*S - Sim. '') retorno Eu...; ? retorno n; ?
Aqui, strlen
limita-se pelo comprimento do array passado para ele, não ultrapassando o comprimento real. Cada um dos tipos de tipo de ponteiro pode ser convertido com segurança para cada um dos outros, e arrays e strings são convertidos automaticamente para ?
pelo compilador. (A conversão de ?
para *
invoca uma verificação de limites e a conversão de ?
para @
invoca um NULL
e uma verificação de limites. A conversão de *
para ?
resulta em nenhuma verificação; o ponteiro ?
resultante tem um tamanho de 1.)
Ponteiros pendentes e análise de região
Considere o seguinte código, em C:
Charlie. *- Sim.(- Não. Eu...) ( Charlie. O que se passa?Não.20.] Sprintf(O que se passa?,"%d",Eu...); retorno O que se passa?; ?
A função itoa
aloca um array de caracteres buf
na pilha e retorna um ponteiro para o início de buf
. No entanto, a memória usada na pilha para buf
é desalocada quando a função retorna, então o valor retornado não pode ser usado com segurança fora da função. Embora o GNU Compiler Collection e outros compiladores avisem sobre esse código, o seguinte normalmente compilará sem avisos:
Charlie. *- Sim.(- Não. Eu...) ( Charlie. O que se passa?Não.20.] *zangão.; Sprintf(O que se passa?,"%d",Eu...); zangão. = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = O que se passa?; retorno zangão.; ?
GNU Compiler Collection pode produzir avisos para tal código como um efeito colateral da opção -O2
ou -O3
, mas não há garantias de que todos esses erros serão detectados.
O Cyclone faz uma análise regional de cada segmento de código, evitando ponteiros pendentes, como o retornado desta versão do itoa
. Todas as variáveis locais em um determinado escopo são consideradas parte da mesma região, separadas do heap ou de qualquer outra região local. Assim, ao analisar itoa
, o compilador Cyclone veria que z
é um ponteiro para a pilha local e reportaria um erro.
Contenido relacionado
MU
Matriz de portas programável em campo
Lynx (linguagem de programação)
Kevin Warwick
Computador Atanasoff-Berry