DeleteLoginData fonksiyonuna bakarsak nesneyi sadece map'lerden temizliyor, delete etmiyor. Yani yazdığın else bloğu çalıştığında nesne her yerden silinip RAM'de ulaşılamaz şekilde sahipsiz kalıyor.
else kısmında DeleteLoginData(pkLD); altına bir de delete pkLD; eklersek sorun kusursuz çözülür bence zühtüde patlamaz
yinede eline sağlık paylaşım için teşekkürler
konuda demişim ki iteratoru önce logon'dan erase edin, görseldeki koda bakalım;
logondaki lookup başarısız olursa ne yapıyor?
siz yine de yazın isterseniz, sizin yöntemle zühtü patlamaz belki ama artık dağa mı kalkar indir kaldır mı yapar onu kim bilir..
ama core değişimi durumu düşünülebilir, bir warp akışına bakmak lazım.
i`m stuck here:TL;DR: YMIR dev ağabeyler duplicate login'i temizleyeceğiz derken bir mekanizma kurmuşlar ama normal çıkışa bağlamayı unutup sıvamışlar.
oyuncumuz zühtü olsun;
zühtü oyuna giriş yapıyor. arka planda ne oluyor?
QUERY_AUTH_LOGIN çalışıyor, bir CLoginData nesnesi free store'dan allocate ediliyor. bu nesneye dört farklı container'dan non-owning raw pointer ile erişiliyor amma velakin "non-owning" demek aslında doğru değil(inanın böyle demeyi çok isterdim) çünkü codebasede ownership'i taşıyan tek tip yok, dördü de fiilen "owner" gibi davranıyor, gerçi bi refcount falan var ama dökümantasyon falan olmadığı için pek anlamlandıramadım, binevi elle shared_ptr taklit edilmiş işte danglinge düşmeyelin falan ama 10 saatimi kodu anlamaya çalışarak geçirecek değilim.
"o nasıl oluyor la?" derseniz non-static data memberları inceleyebilirsiniz:
- m_map_pkLoginData // login-key -> nesne
- m_map_pkLoginDataByLogin // "zuhtu123" -> nesne
- m_map_pkLoginDataByAID // account id -> nesne
- m_map_kLogonAccount // "zuhtu123" -> nesne
yani şu..., neyse(hocam dayanamıyorum YMIR'e laf atıcam).
diyelim ki zühtü biraz takılıp çıkıyor veya alt + f4 çekiyor. şimdi arka planda ne oluyor? QUERY_LOGOUT çalışıyor, orada da işte DeleteLogonAccount("zuhtu123") çağrılıyor.
DeleteLogonAccount'un flowu şöyle:
C++:if (pkLD->IsDeleted()) // hımmmmmmmmmm delete pkLD; m_map_kLogonAccount.erase(it);
"IsDeleted() nedir lo?" m_bDeleted non-static data memberı return eden bir accessor. bunu true set eden tek yer SetDeleted mutator, o da yalnızca DeleteLoginData() içinde çağrılıyor. DeleteLoginData()'yı çağıran tek yer ise QUERY_AUTH_LOGIN, yani bu demek oluyor ki aynı hesabın tekrar login olması gerekiyor.
yani düşünelim;
zühtü DB processi hiç restart olmayan bir sunucuda bir kez login/logout tetiklese ve bir daha hiç girmese ne olur? süper olurdu aslında ama, neyse olacak olan şu: QUERY_AUTH_LOGIN bir daha tetiklenmez, bu da sırayla şunlara yol açar:
- DeleteLoginData çağrılmaz
- SetDeleted çağrılmaz
- IsDeleted() hep false return eder
- "delete pkLD;" delete-expression hiçbir zaman çalışmaz
vay be zühtü, dağları devirdin.
ek olarak zühtü'den bağımsız aynı pattern RemovePeer() içinde de tekrar ediyor:
C++:if (pkLD->IsDeleted()) { delete pkLD; } m_map_kLogonAccount.erase(it++);
bu sefer zühtü'nün suçu yok, bir game server peer'i koparsa (artık crash mi olur restart mı olur siz karar verin) o peer üzerinden bağlı tüm hesapları m_map_kLogonAccount'tan silmeye çalışlıyor ama yine aynı döngü IsDeleted normal şartlarda hep false.
yani game server bir sebepten ötürü restart attığı anda o sırada bağlı olan (kaç kişi olduğuna siz karar verin) oyuncuların CLoginData'sı free edilmiyor.
ee noldu yani derseniz olay tam olarak CWE-772(araştırın bi zahmet)
gözümden kaçmadıysa herhangi bir dangling pointer, use after free falan yok, diğer 3 containerda halen geçerli ve erişilebilir. olay nesnenin işi bitmiş ama halen serbest bırakılmamış olması. uğraştırıcı ve fark edilmesi yüksek ihtimal olsa da bir saldırı senaryosu kurulabilir. zaten normal oyuncu devride başlı başına bir dert, art niyetli birini aramanıza da gerek yok uptime'da yardımcı olur.
fix(naked pointer kullanmaya devam etmek isteyenler için):
C++:m_map_kLogonAccount.erase(it); if (pkLD->IsDeleted()) { delete pkLD; } else { DeleteLoginData(pkLD); }
burda iteratoru önce erase etmezseniz "DeleteLoginData" çağrısının hiçbir anlamı kalmaz, önce erase edin. bu oyunun codebaseinin içine biraz dalmak bile insanı akıl sağlığından eder, bu büyük ihtimalle açtığım son konu.
rica ederim, iyi forumlar.
Not: warp akışını kontrol etmedim, bir sorun bariz olarak var ama direkt olarak delete etmek farklı bir duruma yol açabilir, Metin2 mayın tarlası gibi bir oyun. uygulayıp bir sorun yaşayan olursa belirtirse analizini yapıp düzeltiriz.
Özel rica: Lütfen kullandığınız AI chate girip "ne anlatıyor la bu? şuna bir yorum yaz kallavi olsun" benzeri bir şeyin çıktısıyla yorum yapmayın, bildiğiniz konu ise teknik konuşmak istiyor iseniz doğrusunu yanlışını konuşalım yoksa ne sizin tokenler gitsin ne ben yorulayım, teşekkürler.
Linkleri görebilmek için Turkmmo Forumuna ÜYE olmanız gerekmektedir.
selam. paylaşım için teşekkürler.
hata tespiti doğru ama bu düzenleme zühtü'yü oyuna sokamıyor. ekleyip deneyip yorum yazan üye de girememiş muhtemelen bu sebepten.
zühtü karakter seçiminde "Oyuna Gir"e basıyor. istemci CNetworkStream::Connect içindeki Clear() yüzünden mevcut soketi kapatıp yenisini açıyor, yani eski desc'in destructor'ı iki LOGIN_BY_KEY'in arasında kalıyor.
AUTH_LOGIN -> LOGIN_BY_KEY (1) -> ~DESC (GD_LOGOUT) -> LOGIN_BY_KEY (2)
ortadaki adım nesneyi delete ediyor. ikinci LOGIN_BY_KEY ilk iş GetLoginData(dwLoginKey) yapıyor, nullptr, LOGIN_NOT_EXIST -> "NOID". zühtü karakter seçiminde kalıyor. bu sefer de dağın yamacında takıldı
aynı sebeple "o zaman normal çıkışta da DestroyLoginKey gönderelim" de çalışmaz, o paket de aynı destructor'dan gider.
oluru ise şöyle olur: çıkışta timestamp, birkaç saniye sonra hala m_map_kLogonAccount'ta değilse DeleteLoginData. gecikme şart, çünkü DeleteLogonAccount zaten çıkışta onu o map'ten siliyor.
bu arada birikim login başına değil hesap başına. zühtü ertesi gün tekrar girerse QUERY_AUTH_LOGIN eski kaydını bulup DeleteLoginData çağırıyor, dünkü nesnesi free oluyor. yani "bir daha hiç girmeyen her zühtü için 600bytecık"
asıl login başına birikeni: DBManager:deleteLoginData hiçbir yerden çağrılmıyor. tanım var, header'da bildirim var, çağrı yok. map'i dolduran LoginPrepare her başarılı girişte M2_NEW CLoginData + InsertLoginData yapıyor. zühtü 500 kez girip çıkarsa 500 defa. tek başına aşağı yukarı 65 kb.
bu arada doğrulamasını yapmak için test ortamı kurabilecek ortama sahip değildim bu nedenle hatalarım olabilir. claude fable 5 ultrathinking de olmadığım için bir şeyleri incelerken hata yapabiliyorum.
hata tespiti doğru ama bu düzenleme zühtü'yü oyuna sokamıyor. ekleyip deneyip yorum yazan üye de girememiş muhtemelen bu sebepten.
zühtü karakter seçiminde "Oyuna Gir"e basıyor. istemci CNetworkStream::Connect içindeki Clear() yüzünden mevcut soketi kapatıp yenisini açıyor, yani eski desc'in destructor'ı iki LOGIN_BY_KEY'in arasında kalıyor.
AUTH_LOGIN -> LOGIN_BY_KEY (1) -> ~DESC (GD_LOGOUT) -> LOGIN_BY_KEY (2)
ortadaki adım nesneyi delete ediyor. ikinci LOGIN_BY_KEY ilk iş GetLoginData(dwLoginKey) yapıyor, nullptr, LOGIN_NOT_EXIST -> "NOID". zühtü karakter seçiminde kalıyor. bu sefer de dağın yamacında takıldı

aynı sebeple "o zaman normal çıkışta da DestroyLoginKey gönderelim" de çalışmaz, o paket de aynı destructor'dan gider.
oluru ise şöyle olur: çıkışta timestamp, birkaç saniye sonra hala m_map_kLogonAccount'ta değilse DeleteLoginData. gecikme şart, çünkü DeleteLogonAccount zaten çıkışta onu o map'ten siliyor.
bu arada birikim login başına değil hesap başına. zühtü ertesi gün tekrar girerse QUERY_AUTH_LOGIN eski kaydını bulup DeleteLoginData çağırıyor, dünkü nesnesi free oluyor. yani "bir daha hiç girmeyen her zühtü için 600bytecık"
asıl login başına birikeni: DBManager:deleteLoginData hiçbir yerden çağrılmıyor. tanım var, header'da bildirim var, çağrı yok. map'i dolduran LoginPrepare her başarılı girişte M2_NEW CLoginData + InsertLoginData yapıyor. zühtü 500 kez girip çıkarsa 500 defa. tek başına aşağı yukarı 65 kb.
bu arada doğrulamasını yapmak için test ortamı kurabilecek ortama sahip değildim bu nedenle hatalarım olabilir. claude fable 5 ultrathinking de olmadığım için bir şeyleri incelerken hata yapabiliyorum.
defalarca senden sistem satın alan biri olarak zamanında aynısın değişen hiç birşey yok gene yapında naneyi görün
Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)
Benzer konular
- Cevaplar
- 5
- Görüntüleme
- 561
- Cevaplar
- 36
- Görüntüleme
- 3K
- Cevaplar
- 5
- Görüntüleme
- 680
- Cevaplar
- 17
- Görüntüleme
- 2K
