[C/GCC] probleem compileren oude code

Pagina: 1
Acties:

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 11:51
Ik moet voor mijn werk onderzoeksgegevens omzetten van ouderwets bestandsformaat (OSIRIS) omzetten naar een bruikbaar formaat (uiteindelijk SPSS). Het zelf doorgronden van het bestandsformaat is niet echt een optie qua tijd en de weinige methoden die beschreven zijn op internet zijn niet echt bruikbaar omdat ze uitgaan van software uit de jaren 80/90 - waar niet echt aan te komen is. Dit ter inleiding want ik heb 1 lichtpuntje gevonden, een aantal programmatjes geschreven in C.

Het probleem is dat deze niet goed compileren. GCC laat me achter met de volgende waarschuwingen:
/tmp/ccck8Uhb.o(.text+0x595): In function `tx':
: warning: the `gets' function is dangerous and should not be used.

Wanneer ik daarna de uitvoer run krijg ik een "Segmentation fault" en dat is het. Volgens GDB wordt deze gegenereerd door een call naar strcpy().

Mijn kennis van C is beroerd (maar willing to learn). Wat ik graag zou willen is een aanwijzing hoe ik deze code zou kunnen omschrijven naar iets dat wel werkt. De code stamt uit 1996, wss geschreven voor een of andere UNIX. De broncode is welhaast onleesbaar, slecht gecomment en de schrijver onbekend. Een leesbarein elk geval indente variant van de tx() functie waar gcc naar verwijst is deze:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
tx(int f,int t,int n) {
    int p,pp;unsigned char b;
    for (p=f;p<n+f;p++)  {
        if(asr[r1[p]]==-1) { 
            if (que[p]!='?') {
                if (nyuc) { 
                    wn+=4; 
                    fprintf(stderr, "\nAn EBCDIC code %u not defined in file '%s' is found in line %d at position %d\n",r1[p],ct,l,p);
                    fprintf(stderr,"The conversion table in %s gives the following character set:\n",ct);
                    for(pp=0;pp<256;pp++)  {
                        if (inv[pp]==-1) putc(' ',stderr); 
                        else putc(pp,stderr);
                        
                        if(pp%64==63)putc('\n',stderr);
                    }
                    
                    fprintf(stderr,"\n  The unknown character is denoted by <?> in the following string :\n");
                }
                que[0]='?'; 
                for (pp=1;pp<f;pp++)  putc(' ',stderr);  
                for (pp=f;pp<f+n;pp++)  {
                    if (asr[r1[pp]]==-1) {
                        if (r1[pp]==r1[p]) {
                            que[pp]='?';fprintf(stderr,"<?>");
                        } else putc(' ',stderr);
                    } else putc(asr[r1[pp]],stderr);
                    
                    if (nyuc) {
                        fprintf(stderr,"\n  Enter a character to replace <?> with\n",r1[p]);
                        fprintf(stderr,"  or its ASCII-code in decimals  ( 01 - 255 ) or push <Enter> alone:"); 
                        nyuc=0;
                    } else fprintf(stderr,"\n  Undefined code %u at positon %d of line %d, enter new character:",r1[p],p,l); 
                    
                    gets(buf);
                    wn+=2;
                    if (buf[0]==0) {
                        if (nyrem) printf("  Code %d remaines undefined.\n",r1[p]);
                        nyrem=0;
                    } else {
                        inique();
                        if (buf[1]==0) b=buf[0];
                        else if (sscanf(buf,"%u",&b)!=1) {
                            fprintf(stderr,"bad terminal input.\n");
                            exit(1);
                        }
                        
                        printf("  All occurences of %u will be converted to '%c' (%d).\n",r1[p],b,b); asr[r1[p]]=b;
                        if (inv[b]>=0)  printf("\n       EVEN  CODE %u IS CONVERTED TO THE SAME VALUE : '%c'.\n\n", inv[b],b);
                        inv[b]=r1[p];
                    }
                }
                
                if (asr[r1[p]]) r3[p+t-f]=asr[r1[p]]; 
                else r3[p-f+t]=' ';
            }
            if (que[0]=='?') inique();
        }
    }
}


Het is niet mijn bedoeling om een debug of "support iemand anders' script" vraag te stellen. Waar ik naar op zoek ben zijn tips/links om deze code om te schrijven, wat wordt bijvoorbeeld gebruikt in plaats van gets() (geen handig googlewoord) waar GCC me voor waarschuwd?

Regeren is vooruitschuiven


  • Macros
  • Registratie: Februari 2000
  • Laatst online: 30-04 09:28

Macros

I'm watching...

De compiler waarschuwt voor gets omdat hij geen buffer overflow checkt, waardoor kwaadwillenden de code zouden kunnen hacken als het bijvoorbeeld een commandline utility was welke je zou distribueren. Dat is hier niet het geval dus kun je de waarschuwing negeren.
gets() reads a line from stdin into the buffer pointed to by s until either a terminating
newline or EOF, which it replaces with '\0'. No check for buffer overrun is performed (see
BUGS below).
De code compiled verder wel goed hier bij mij (met wat kleine schoonheids foutjes verwijderd). Maar er is geen touw aan vast te knopen wat het doen. Het is wel enorm cryptisch geprogrammeerd.

"Beauty is the ultimate defence against complexity." David Gelernter


  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 11:51
Macros schreef op donderdag 07 april 2005 @ 20:41:
De compiler waarschuwt voor gets omdat hij geen buffer overflow checkt, waardoor kwaadwillenden de code zouden kunnen hacken als het bijvoorbeeld een commandline utility was welke je zou distribueren. Dat is hier niet het geval dus kun je de waarschuwing negeren.
[...]
aha, dat scheelt al dan...
De code compiled verder wel goed hier bij mij (met wat kleine schoonheids foutjes verwijderd). Maar er is geen touw aan vast te knopen wat het doen. Het is wel enorm cryptisch geprogrammeerd.
Wat dit programmatje doen is het converteren van een bestand dat is gecodeerd in het zgn EBCDIC formaat naar een nieuwere versie die gebruik maakt van ASCII. Of het zuiver het veranderen van de codering betreft kan ik niet echt opmaken uit de code. Ik zou nog kunnen proberen of ik een andere manier kan vinden om dit te converteren en kijken of dat iets oplevert. Van de volgende stap is een windows binary beschikbaar dus dan zou ik er al ongeveer zijn.

Maar de code compileert bij jou wel gewoon? Geen "segmentation fault" bij het runnen (* T-MOB is benieuwd naar ed schoonheidsfoutjes)

Regeren is vooruitschuiven


  • Macros
  • Registratie: Februari 2000
  • Laatst online: 30-04 09:28

Macros

I'm watching...

Ik nam aan dat het een bepaald soort input nodig heeft om te draaien. Die input heb ik niet dus ik heb het niet kunnen draaien.
Als je het draait zonder argumenten segfault hij omdat hij de niet bestaande argumenten probeert uit te lezen zonder ze te controleren. Maar ja, het is toch al brak dus zoiets kon je verwachten.

Die schoonheids foutjes zijn oa. het weglaten van de return values van de functies (void) en in 1 functie de types van de parameters niet aangeven (int).

[ Voor 20% gewijzigd door Macros op 07-04-2005 21:57 ]

"Beauty is the ultimate defence against complexity." David Gelernter


  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 11:51
Macros schreef op donderdag 07 april 2005 @ 21:56:
Ik nam aan dat het een bepaald soort input nodig heeft om te draaien. Die input heb ik niet dus ik heb het niet kunnen draaien.
Als je het draait zonder argumenten segfault hij omdat hij de niet bestaande argumenten probeert uit te lezen zonder ze te controleren. Maar ja, het is toch al brak dus zoiets kon je verwachten.

Die schoonheids foutjes zijn oa. het weglaten van de return values van de functies (void) en in 1 functie de types van de parameters niet aangeven (int).
Hoe brak het ook moge zijn, er wordt wel gechecked op de input-argumenten. Uit deze code
C:
1
2
3
4
5
/* Command line  */
strcpy(command,argv[0]);
if (argc==2) strcpy(ct,"ascii");
 else if (argc==3) strcpy(ct,argv[2]);
 else  {printf("Correct syntax is: %s studyname (conversion_table)\n",command);


Maak ik althans op dat er op zijn minst een foutmelding moet worden gespuugd als het programma verkeerd wordt aangeroepen. Misschien moet ik morgen maar eens rustig naar kijken, het leesbaar maken en dan nabouwen in PHP ofzo...

Regeren is vooruitschuiven


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 02-05 01:32
Mijn god, wie schrijft deze code. :X Waarschijnlijk zijn ze er bij The Daily WTF wel blij mee. ;)

Inhoudelijk: print met GDB eens een backtrace en de waarden van zoveel mogelijk relevante variabelen op dat punt. Misschien dat je dan enig inzicht krijgt in wat er mis gaat.
Pagina: 1