- A hozzászóláshoz be kell jelentkezni
Hozzászólások
printf("Element: %x\n", *element);
Így lenne jó:
if (element != nullptr) {
printf("Element: %x\n", *element);
} else {
printf("Congratulations, you've found the borked index!\n");
}
- A hozzászóláshoz be kell jelentkezni
De ez nem juttat hozzá a titokhoz, ha jól értelmezem.
- A hozzászóláshoz be kell jelentkezni
Ja, most látom hogy exploitálni is kell.
Nem ez lesz a helyes irány, bár szerintem se a C, se a C++ nem tiltja, hogy a secret 0x0-ra kerüljön... de semmilyen olyan hardver+fordító páros nem jutna eszembe, ahol ez lehetséges lenne.
- A hozzászóláshoz be kell jelentkezni
A get_element_safe függvény az arr tömb egy elemére mutató pointert ad vissza, ha az index érvényes. Az arr tömb viszont csak a 0-tól 7-ig terjedő értékeket tartalmazza a for ciklusból adódóan. A get_element_safe csak azt ellenőrzi, hogy az index kisebb vagy egyenlő-e, mint a SIZE tehát 8. A >= miatt 8 is átmegy itt. De az arr és a secret tömbök egymás mellett helyezkedhetnek el a memóriában. Ha egy érvényes 0–7 közötti indexet adsz meg, akkor minden rendben van. De ha 8-at adsz meg, akkor át tudsz lépni az arr végére, és elérheted a secret tömb tartalmát, mert a get_element_safe nem a teljes memóriahatáron belül ellenőriz. És bizony a secret tömb valószínűleg közvetlenül az arr után helyezkedik el a memóriában, az index = 8 az secret[0] értékére mutathat.
- A hozzászóláshoz be kell jelentkezni
Nem jól nézed, >= 8 esetén nullptr-t ad vissza, szóval a 8-ra is.
- A hozzászóláshoz be kell jelentkezni
Igen, de hiába ad vissza nullptr-t ha ezt nem ellenőrzik, akkor egy nullptr dereferálása történik, ami szegmenshibát (segmentation fault) okoz.
(*kisebbet elírtam mert nagyobb, de utána már jól írom jelekkel. Lényeg, hogy a 8 átmegy és az pont a secret elejére mutat)
- A hozzászóláshoz be kell jelentkezni
Lényeg, hogy a 8 átmegy és az pont a secret elejére mutat
De nem megy át :) (a 8-ból is nillptr lesz). Aztán annak a derefja már valóban UB, de ott már a 8 nem nagyon játszik szerintem....
Szerk: ah, "megfelelő" optimalizálás esetén simán kidobja a check-et (az UB miatt) és "átmegy" a 7 fölötti is :)
- A hozzászóláshoz be kell jelentkezni
Most nincs kedvem bepotyogni hogy kiprobaljam hogy tenyleg bekovetkezik-e, de a pointer dereferalas printf parametereben az UB ha nullptr, vagyis az optimizer felteheti hogy nem kovetkezik be es kioptimalizalhatja az index checket a get_element_safe fv-bol. Lasd: https://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.ht…
Tehat szerintem 8-ra siman ki fogja adni a secret tomb 0. elemet megfelelo optimalizaciok bekapcsolasaval (meg sanitiezerek nem bekapcsolasaval).
I hate myself, because I'm not open-source.
- A hozzászóláshoz be kell jelentkezni
Ha ez így van, akkor gondolom 9-re secret első és így tovább elemeit is.
- A hozzászóláshoz be kell jelentkezni
Igen ez jogos megjegyzés. Nemcsak 8, hanem 9... stb is hozza a hibát.
- A hozzászóláshoz be kell jelentkezni
de a pointer dereferalas printf parametereben az UB ha nullptr, vagyis az optimizer felteheti hogy nem kovetkezik be es kioptimalizalhatja az index checket
Ajjajjajj, ez tényleg? Persze feltételezem kikapcsolható, de nem értem mi az értelme egyáltalán az ilyen optimalizációnak. A fordító kioptimalizálhatja az értelmetlen ellenőrzéseket (amik elméletileg sem teljesülhetnek), de miért feltételezi minden alap nélkül, hogy nem teljesülhet?
- A hozzászóláshoz be kell jelentkezni
Mert onnan kezdve hogy UB van, a compiler barmit is megtehet, mert a C/C++ szabvany nem mond semmit arrol hogy minek kene tortennie. Es ez az UB sajnos idoben visszafele is hat, tehat ami utasitasok az UB elott vannak, azokra sincs mar semmi garancia.
I hate myself, because I'm not open-source.
- A hozzászóláshoz be kell jelentkezni
>> de miért feltételezi minden alap nélkül, hogy nem teljesülhet?
te, mint a programozó mondod neki az elhagyott nullderef ellenőrzéssel (ti. hogy nyugi, az index mindig ok lesz)
- A hozzászóláshoz be kell jelentkezni
Ez tele van bugokkal, de a legnagyobb rohadt nagy bug, hogy mi a francért keveri a C++ kódot a C-vel??
C++-ban FILE típus? C++-ban C típusú tömb, std::vector helyett? printf meg stream-ek keverése...
Pont az ilyen gyökér keveredések miatt annyira népszerűtlen a C++.
Ezen kívül:
* nincs ellenőrizve a fájl megnyitása,
* nincs ellenőrizve a fread által olvasott elemek száma. Meg amúgy is szebb is lenne sizeof(uint32) és count=SIZE2-vel meghívni.
* nullptr-t nem kellene átadni a printf-nek. Amúgy is mi a tököm miatt ad át címként egy uint32-t (már ha nem akar beleírni).
- A hozzászóláshoz be kell jelentkezni
Amúgy is mi a tököm miatt ad át címként egy uint32-t (már ha nem akar beleírni).
Mert a pointer aritmetika csak pointerekkel működik (arr+index ezzel ad helyes eredményt).
- A hozzászóláshoz be kell jelentkezni
return arr[index];
return *(arr+index);
- A hozzászóláshoz be kell jelentkezni
Ha az arr egy sima uint32, akkor arr[index] megint értelmetlen, *(arr+index) se lesz jó.
Amúgy meg egy tömböt hogy adsz át máshogy? Max. még referenciával, nem pointerrel.
- A hozzászóláshoz be kell jelentkezni
félig laikusként a sizeof jól kezeli ezt unsigned int32 -t?
- A hozzászóláshoz be kell jelentkezni
sizeof(secret)=8*4 lesz, ha az a kérdés. Ebben pl. eltérés van a statikus tömb és a *-os definícó között.
- A hozzászóláshoz be kell jelentkezni
Én is ezen időztem, azt hittem a sizeof(...) a pointer méretét adja vissza.
- A hozzászóláshoz be kell jelentkezni
#include <stdio.h>
#include <iostream>
Ennél tovább nem szükséges olvasni, a kód úgy, ahogy van, a kukába való.
- A hozzászóláshoz be kell jelentkezni
if (index >= (SIZE + SIZE2))...
8,9... től jön a secret
...ja, hogy nem a secret a goal, hanem a bug :)
akkor if (index >= SIZE || index < 0) bár unsigned miatt mind1... passz
- A hozzászóláshoz be kell jelentkezni
nem bírtam ki, meglestem... scary 😱
- A hozzászóláshoz be kell jelentkezni
A kiírás hibás.
A main függvény lokális vermébe kerül X címre az arr, majd X - 32 címre a secret, így nyilván arról van szó, hogy a get_element_safe() függvényben kell túlcsordulást előidézni a "return arr + index" sorban, méghozzá az is biztos, hogy egy fordítóbug kihasználásával (a hiba nem szemantikai, hanem fordítóbeli).
Csakhogy, ennek megválaszolásához tudni kéne, hogy mennyi a sizeof(uintptr_t), azaz hogy 16, 32 vagy 64 bitesre fordítunk-e. Ennek ismerete nélkül nem is adható helyes válasz, tehát hibás - konrétan hiányos - a feladat kiírása.
ps: Ezen kívül a printf valóban UD-t eredményez bármilyen index >= 8 bemeneti értékre, és valóban eleve balfasz, aki így keveri a C-t és C++-t, de pláne a FILE-t a streamekkel. Gyanítom, ez triggereli a fordítóbugot az inlineolás kódgeneráló részében; és stream helyett fgets+atoi és sima C fordítóval valószínűleg eleve nem is jönne elő.
De mégegyszer, ez nem szemantikai, hanem fordítóbeli bug, tehát ismerni kéne a pontos fordítót, a célarchitektúrát, a címbusz méretét, de mivel inline-ról van szó, még a fordítónak átadott optimalizációs kapcsolók sem mindegyek!
- A hozzászóláshoz be kell jelentkezni
fgets+atoi és sima C fordítóval valószínűleg eleve nem is jönne elő.
de, előjön. (mondjuk scanf-fel próbáltam, de a lényeg, hogy C++ nélkül)
- A hozzászóláshoz be kell jelentkezni
clang és az inlineolt boundscheck esete
- A hozzászóláshoz be kell jelentkezni
Ha jól látom csak a számsorral feltöltött arr-ból olvas a megadott indexnél nem pedig a secret-ből amit ki kéne "csorgasson". A printf feletti sor.
(A SIZE2-vel kéne ellenőrizni az indexet, de mivel ugyanannyi mindkettő, most mindegy.
Szerencsétlen, hogy ugyanaz a neve a függvényparaméternek meg az egyik tömbnek.
nullptr nekem új, de c++-os dolog szóval nem kéne, meg nem kéne keverni a dolgokat. )
- A hozzászóláshoz be kell jelentkezni
Felesleges bele a C++, sima C kód is ugyanígy viselkedik.
- A hozzászóláshoz be kell jelentkezni
Ja, jóvan! Nem tudtam, hogy fejből kéne látnom, hogy szarul növeli a pointert.
- A hozzászóláshoz be kell jelentkezni