C ja laitteistoläheinen ohjelmointi -kurssi 2010: Ensimmäinen tentti 16.12.2010

Tehtäviä oli kolme, maksimipistemäärä 8 kustakin, hyväksytyn suorituksen raja 12 pistettä.
Demoista sai hyvitystä max 6 pistettä (tehtyjen tehtävien määrä jaettuna seitsemällä, viimeinen demo laskettiin kuudeksi tehtäväksi).

Arvosana-asteikko:
pisteetarvosana
12-13p.....1
14-16p.....2
17-19p.....3
20-22p.....4
23-24p.....5

Tehtävä 1

Ensimmäisessä tehtävässä piti lisätä rpncalc-ohjelmaan vakiot pi ja e.

Ratkaisumahdollisuuksia on useita, kaikki toimivat hyväksyttiin. Yksi yleinen ja helppo tapa oli lisätä e ja pi muuttujalistaan (kuten tässä malliratkaisussa), siinä vain olisi pitänyt varmistaa, ettei vakioihin pysty sijoittamaan uutta arvoa. Erillisen vakiorakenteen teko kelpasi myös, samoin vakioiden kovakoodaus compile-funktioon (vaikka moinen rumaa onkin).

Yksi piste vähennettiin jos vakioita pystyi muuttamaan ("=e", "=pi"), mutta sekä virheilmoitus =:sta että sen ohittaminen hiljaa kelpasi.

Bugisesta koodista, joka kuitenkin kääntyy ja toimii annetulla esimerkillä, mutta särkyy joissakin muissa tilanteissa, sai 5p.

Tehtävä 2

Toisessa tehtävässä piti korjata BASIC-tulkissa oleva bugi.

Kyseessä oli yksinkertainen tyyppivirhe: liukulukuvakiot ovat oletuksena double-tyyppiä, mutta ne tulostettiin long double-formaatissa. Formaatin määräytyminen vain oli sotkuisen makron sisällä.

Yksinkertaisin ja paras ratkaisu oli lisätä bfmt-makroon basic.h:ssa testi liukuluvun koolle tähän tapaan.

Korjaukseksi kelpasi myös long doublen muuttaminen doubleksi, mutta se olisi pitänyt tehdä bfmt-makron (%Lg -> %lg) lisäksi INPUT-makrossa ja muuttujamäärittelyissä: muuten kaksi ensimmäistä esimerkkikoodia menee rikki, vaikka esim3.bas toimiikin. Tällaisesta puoliksi onnistuneesta korjauksesta sai 5p.

Pisteitä ei vähennetty vaikka oli turhaan muuttanut g:n f:ksi formaatissa.

Yhden pisteen sai hyvästä yrityksestä, jos virheellinen kohta oli selvästi löydetty (ts. oli yritetty muuttaa bfmt-makroa) mutta korjaus ei toiminut edes melkein.

Tehtävä 3

Kolmannessa tehtävässä piti löytää ja korjata bugi salasanaa kysyvästä ohjelmasta.

Ohjelman piilottelevan salaisuuden paljastaminen edellytti sen huomaamista, että alkuperäinen binääri oli suid ja siten pystyi lukemaan tiedostoa, johon muuten ei ollut pääsyä. Tätä ei kuitenkaan vaadittu, vaan maksipisteisiin riitti, että bugi oli lähdekoodista tunnistettu ja korjattu oikein.

Kyseessähän oli klassinen merkkijonon ylivuoto-ongelma:

  scanf("%s", password);
Syöttämällä ylipitkän salasanan pystyi kirjoittamaan muiden muuttujien päälle, erityisesti authenticated -muuttujan, joka oli alustettu nollaksi ennen scanf-kutsua.

Yksinkertaisin ratkaisu oli maksimipituuden lisääminen tyyliin scanf("%31s", password). Myös scanf'in korvaaminen getchar()-silmukalla tms kelpasi, jos pituustesti oli tehty oikein. Yksi piste vähennettiin, jos salasanan loppunollalle ei oltu jätetty tilaa (scanf("%32s",password)).

Muuttujan authenticated alustuksen siirtäminen scanf'in jälkeen ei sen sijaan riitä: silloin salauksen pystyy kuitenkin murtamaan sopivalla syötteellä, joka kirjoittaa encryptedpw:n päälle syötteen alkua vastaavan hash'in. (Pelkästään tästä olisi saanut 5p, mutta sen tarjoamisesta pituustarkistuksen lisäksi ei sakotettu.)

Ohjelmassa käytetyn salauksen heikkoutta ei tarvinnut huomata, lisäpisteen sen krakkaamisesta olisi voinut saada (mutta muutenkin täydet pisteet saaneille voi antaa vain moraalisen lisäpisteen).