Da C a Cyclone


Considera il seguente programma C che dovrebbe stampare la sottostringa della stringa passata come argomento, dopo la x:
#include<stdio.h>
#include<string.h>
char * foo(char *s){
char c[10];
strcpy(c,s);
// questa è una funzione della librerira che cerc aun
// carattere in una string
return strchr(c,'x');
}
int main (int argc, char ** argv){
char * c = foo(argv[1]);
c++;
printf("sottostringa %s",c); return (*c);
}
Se compilo con gcc compila senza warning:
gcc -o ptr_c.exe ptr_c.c
Ma non funziona tanto bene:
ptr_c.exe pippoxcc

sottostringa a
Posso anche avere buffer overflow e non accorgermi oppure accorgermi:
$ ./ptr_c.exe pixxpxffsssaddsdssdfsfdsfds
  17334 [main] ptr_c 1360 _cygtls::handle_exceptions: Error while dumping state
(probably corrupted stack)
Segmentation fault (core dumped)
Per prima cosa devo usare il malloc
char *c = malloc(sizeof(char)*10);
adesso funziona tranne se ho più di 10 caratteri:
<< QUI SOTTO LINUX FUNZIONA, SOTTO WINDOWS NO>>
oppure se non ho una x:
./ptr_corr ISOID
Segmentation fault
oppure se non ho alcun argomento dopo la riga di comando.
 
./ptr_corr
Segmentation fault

in cyclone

Nella prima traduzione semplicemente uso i fat pointer per s e per argv:
Sostituisco * con ?:
#include<string.h>
#include<stdio.h>

char * foo(char ?s){
char * c = malloc(sizeof(char)*10);
strcpy(c,s);

return strchr(c,'x');

}

int main (int argc, char ?? argv){ 
char * c = foo(argv[1]);
c++;

printf("sottostringa %s",c);
return (*c);

}
Se compilo ottengo
cyclone ptr.cyc

ptr.cyc:5: actual argument has type
        char @{1024U}@nozeroterm`foo
 but formal has type
        char ?`foo

  char @{1024U}@nozeroterm`foo and char ?`foo are not compatible.
        (not both zero terminated)
ptr.cyc:6: actual argument has type
        char @{1024U}@nozeroterm`foo
 but formal has type
        const char ?

  `H and `foo are not compatible.
ptr.cyc:6: returns value of type const char ? but requires char *
  @true and @true are not compatible.

Il problema è che la funzione strchr restuituisce un const:
nessun problema, posso modificare e mettere const:
const char * foo(char ?s){ 
...
   const char * c = foo(argv[1]); 
quando però eseguo ho un errore: sto cercando di convertire in char* un char?
Cioè un puntatore fat in uno non fat.
metto char ? foo al posto di char* fooo
const char ? foo(char ?s){ 
...
   const char ? c = foo(argv[1]); 

Adesso funziona tranne in alcuni casi (però non darà  mai segmentation fault).

Nel caso in cui non abbia un 'x' nella string, la strchr restituisce null: devo mettere il controllo a null.

O in questo modo utilizzando il puntatore not null:
const char @ c = foo(argv[1]);

o con if(c!=NULL) ...

Se chiamo il comando con più di 10 caratteri?

Per finire posso costruire il buffer di dimensione giusta (vedi ptr_c_numlets.cyc):
char ? c = malloc(sizeof(char)*numelts(s));

Uso di strumenti per l'analisi statica:

flaw finder

[garganti@pcelvinia cyclone]$ flawfinder ptr_c_1.c
Flawfinder version 1.26, (C) 2001-2004 David A. Wheeler.
Number of dangerous functions in C/C++ ruleset: 158
Examining ptr_c_1.c
ptr_c_1.c:6: [4] (buffer) strcpy:
Does not check for buffer overflows when copying to destination.
Consider using strncpy or strlcpy (warning, strncpy is easily misused).
ptr_c_1.c:5: [2] (buffer) char:
Statically-sized arrays can be overflowed. Perform bounds checking,
use functions that limit length, or ensure that the size is larger than
the maximum possible length.

Hits = 2
Lines analyzed = 18 in 0.54 seconds (454 lines/second)
Physical Source Lines of Code (SLOC) = 18
Hits@level = [0] 0 [1] 0 [2] 1 [3] 0 [4] 1 [5] 0
Hits@level+ = [0+] 2 [1+] 2 [2+] 2 [3+] 1 [4+] 1 [5+] 0
Hits/KSLOC@level+ = [0+] 111.111 [1+] 111.111 [2+] 111.111 [3+] 55.5556 [4+] 55.5556 [5+] 0
Minimum risk level = 1
Not every hit is necessarily a security vulnerability.
There may be other security vulnerabilities; review your code!