noisiv 1
noisiv
mavzermete 1
mavzermete
Manwe Work 1
Manwe Work
Bodyguardd 1
Bodyguardd
Vahsi Uzman 1
Vahsi Uzman
Reklam vermek için turkmmo@gmail.com

[DB] CLoginData memory leak

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
1788234008600.png

? noldu çıkarın mı bitti reis yıllar sonra ilk yorumu buraya atmışsın :d sana yanıt bile vermeyeceğim, abi dedik hiç uğruna işlerini yaptık üstüne dolandırıcılıktan ban yiyen birinin banı nasıl açılıyor da burda takılıyor o da ayrı konu zaten, neyse ya doğrudur reis kralsın.

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ı :D

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.
not olarak yazdım zaten farklı bir durum meydana gelebilir kontrol etmek, emin olmak lazım diye. warp akışı benim de aklıma geldi ne oluyor acaba diye, neyse mayın tarlası metin2 gözümden kaçmış olabilir, ownership nerde belli bile değil. çözüm yerine sorunu baz alıp araştırıp çözüm uygulayabilir isteyen, ben yine de akışa müsait anımda bakacağım.

600bytecık için ise, yani bu mantıkla UB olan bir yerde de "1 tane ubcik var yahu" diyelim, bakış açınızın hatalı olduğunu düşünüyorum.
 
Son düzenleme:
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:
  1. m_map_pkLoginData // login-key -> nesne
  2. m_map_pkLoginDataByLogin // "zuhtu123" -> nesne
  3. m_map_pkLoginDataByAID // account id -> nesne
  4. 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.
Tespit doğru; ancak uygulamanız yanlış. `GD_LOGOUT` her zaman nihai çıkış değildir. Karakter seçimi,
warp ve kanal/core geçişlerinde eski bağlantı logout gönderirken yeni bağlantı aynı login key ile tekrar `LOGIN_BY_KEY` çalıştırır.
Logout sırasında `DeleteLoginData()` çağrılması şu yan etkilere yol açabilir:

- İkinci `LOGIN_BY_KEY` isteğinin `LOGIN_NOT_EXIST/NOID` dönmesi.
- Oyuncunun karakter seçim ekranında kalması.
- Warp işleminin başarısız olması.
- Kanal/core değişiminde bağlantının kopması.
- Ağ gecikmesine bağlı aralıklı ve zor tekrarlanan login hataları.
- Bekleyen async DB sonuçlarında null pointer dereference oluşması.
- Doğrudan `delete pkLD` uygulanırsa diğer map’lerde dangling pointer ve use-after-free kalması.
- `DeleteLoginData()` sonrasında tekrar `delete` uygulanırsa double-free oluşması.

Doğru yaklaşım, logout sonrası reconnect/transfer süresi tanımak ve TTL dolduğunda hesap aktif değilse bütün indekslerden merkezi olarak çıkarıp nesneyi yalnızca bir kez silmektir.

Bunun dışında kişisel bir eleştiride bulunmak istiyorum:

Tespit değerli ve hata gerçek; fakat YMIR geliştiricilerini her bulguda küçümseyen üslup teknik içeriğin değerini düşürüyor, ve her hata bulgusunda bu egoist tavrınızı görüyorum.
Bu proje 2005 döneminin C++03 şartlarında, standart akıllı pointer’ların,
modern sanitizer’ların ve bugünkü CI/test imkânlarının bulunmadığı bir ortamda geliştirilmiş çok katmanlı bir MMO altyapısıdır. Ve dönemin en büyük teknoloji AI kullanımı onların zamanında
yoktu buna da değinmek istiyorum bir çok paylaşımınız da arkadaşlarınız "tokenim" yetmedi gibi alaycı tavırlar ile başkalarını küçümsediğini düşünerek yorum yapıyorlar
oysa kullanmayan Allahın kulu yoktur, her işlerinizi ona yaptırıp kendinizi inkar etmekte ne bileyim nasıl bir seviyedir bilemedim, neyse eleştiriye dönelim.
Yirmi yıl sonra bütün kaynak kod elinizdeyken hata bulmak, o sistemi sıfırdan kuran mühendisleri yetersiz yapmaz.
Nitekim burada da tespit doğru olmasına rağmen önerilen çözüm login-key/warp akışı incelenmeden paylaşılmış ve yeni hatalara yol açıyor. Bu durum,
legacy kodda tek fonksiyona bakarak hüküm vermenin ne kadar riskli olduğunu gösteriyor.
İyi mühendislik yalnızca hata bulmak değil; bütün yaşam döngüsünü incelemek, yan etkileri test etmek, güvenli bir çözüm üretmek ve önceki geliştiricilerin emeğine saygılı bir dille katkı sunmaktır.
Eleştiri yapılmalı, fakat teknik gerekçeyle yapılmalı; alay ve küçümseme kimseyi daha iyi yazılımcı yapmıyor.

Son olarak şu söz hoşuma gitti paylaşmak istiyorum:

Az felsefe insanı ateist yapar, derin felsefe ise dine götürür. (Francis Bacon)

Paylaşım için teşekkürler.
 
Tespit doğru; ancak uygulamanız yanlış. `GD_LOGOUT` her zaman nihai çıkış değildir. Karakter seçimi,
warp ve kanal/core geçişlerinde eski bağlantı logout gönderirken yeni bağlantı aynı login key ile tekrar `LOGIN_BY_KEY` çalıştırır.
Logout sırasında `DeleteLoginData()` çağrılması şu yan etkilere yol açabilir:

- İkinci `LOGIN_BY_KEY` isteğinin `LOGIN_NOT_EXIST/NOID` dönmesi.
- Oyuncunun karakter seçim ekranında kalması.
- Warp işleminin başarısız olması.
- Kanal/core değişiminde bağlantının kopması.
- Ağ gecikmesine bağlı aralıklı ve zor tekrarlanan login hataları.
- Bekleyen async DB sonuçlarında null pointer dereference oluşması.
- Doğrudan `delete pkLD` uygulanırsa diğer map’lerde dangling pointer ve use-after-free kalması.
- `DeleteLoginData()` sonrasında tekrar `delete` uygulanırsa double-free oluşması.

Doğru yaklaşım, logout sonrası reconnect/transfer süresi tanımak ve TTL dolduğunda hesap aktif değilse bütün indekslerden merkezi olarak çıkarıp nesneyi yalnızca bir kez silmektir.

Bunun dışında kişisel bir eleştiride bulunmak istiyorum:

Tespit değerli ve hata gerçek; fakat YMIR geliştiricilerini her bulguda küçümseyen üslup teknik içeriğin değerini düşürüyor, ve her hata bulgusunda bu egoist tavrınızı görüyorum.
Bu proje 2005 döneminin C++03 şartlarında, standart akıllı pointer’ların,
modern sanitizer’ların ve bugünkü CI/test imkânlarının bulunmadığı bir ortamda geliştirilmiş çok katmanlı bir MMO altyapısıdır. Ve dönemin en büyük teknoloji AI kullanımı onların zamanında
yoktu buna da değinmek istiyorum bir çok paylaşımınız da arkadaşlarınız "tokenim" yetmedi gibi alaycı tavırlar ile başkalarını küçümsediğini düşünerek yorum yapıyorlar
oysa kullanmayan Allahın kulu yoktur, her işlerinizi ona yaptırıp kendinizi inkar etmekte ne bileyim nasıl bir seviyedir bilemedim, neyse eleştiriye dönelim.
Yirmi yıl sonra bütün kaynak kod elinizdeyken hata bulmak, o sistemi sıfırdan kuran mühendisleri yetersiz yapmaz.
Nitekim burada da tespit doğru olmasına rağmen önerilen çözüm login-key/warp akışı incelenmeden paylaşılmış ve yeni hatalara yol açıyor. Bu durum,
legacy kodda tek fonksiyona bakarak hüküm vermenin ne kadar riskli olduğunu gösteriyor.
İyi mühendislik yalnızca hata bulmak değil; bütün yaşam döngüsünü incelemek, yan etkileri test etmek, güvenli bir çözüm üretmek ve önceki geliştiricilerin emeğine saygılı bir dille katkı sunmaktır.
Eleştiri yapılmalı, fakat teknik gerekçeyle yapılmalı; alay ve küçümseme kimseyi daha iyi yazılımcı yapmıyor.

Son olarak şu söz hoşuma gitti paylaşmak istiyorum:

Az felsefe insanı ateist yapar, derin felsefe ise dine götürür. (Francis Bacon)

Paylaşım için teşekkürler.
başladık yine…

-> bu kaynak dosyalar 2014 yılında sızdırıldı hadi 10 sene geliştirme görmedi diyelim, 2005de kitap falan yok muydu? bu savunmayı neden insanlar ısrarla yapıyor anlayamıyorum
-> AI olup olmaması bir etken değil, yazılmış onlarca kitap var açıp okuyabilirlerdi
-> benim karşı olduğum yapay zeka değil yorum yazarken bile yapay zeka kullanmak, bilmediğin konu hakkında yapay zeka çıktısını argüman olarak sunmak, burda birini ezme gibi bir niyetim neden olsun bu bana ne kazandırır?
-> gariptir ki sorunu paylaşınca herkes bir anda çözüm uzmanı oldu, 1 saatte analizleri bitirip karşı argüman sundu falan neyse bugüne kadar kimsenin değinmemiş olması çok garip, maşallah diyelim umarım daha iyi yerlere gelirsiniz ben mutlu olurum
-> not olarak farklı durumların meydana gelebileceğini yazdım, doğru çözümdür diye bir şey söylemedim, bu bir analiz çözümde atladığım case olabilir metin2'yi ben geliştirmedim, core ekipten de değilim, ben bir şey söylerim başkası bak şu da var bir bak istersen der ve sonuç olarak çözüme ulaşırsınız, bazı vasıfsızların yaptığı gibi "AĞĞĞĞ HATA YAPTI AĞĞĞĞ" denmez(normal şartlarda)
-> metin2 ile ne mühendisliği, ortada mühendislik ürünü yok ki üzerine mühendislik yapasınız
-> burada kendimi “iyi yazılımcı” diye lanse etme veya gelsin biri bana “bu adam iyi” desin gibi dertlerim yok. isteyen istediğini düşünebilir biz 40 kişiyiz birbirimizi biliriz, ben bu forumdaki kötü yazılımcılardan biriydim
-> egomu tatmin etmek istesem çalıştığım şirketin kodlarımın koştuğu ürünleri nerelere satıyor diye bakardım metin2 forumu aklıma gelmez diye düşünüyorum


metin2 kompleks bir yazılım(yani karmaşık, anlaşılması, üzerinde çalışılması zor), boş vakitlerimde metin2 ile uğraşırken karşıma çıkan bir şey olursa genelde burada paylaşıyorum. son 2-3 aydır kaç tane hata analizi ve fix veya bence faydalı olabilecek konu paylaştım hiçbirine teşekkür etmeyip(birinden bir şey beklediğimden değil, kimse böyle bir şey yapmak zorunda değil örnek veriyorum) bir tanesinde gözden bir şey kaçırmışız diye bana burda “AAAA GÖZDEN KAÇIRMIŞ LAF ATINNN TAŞLAYINNN VATAN HAİNİ AAAA ZATEN EGOIST BU” yaklaşımıyla laf atanlar mı egoist ve kendini öne çıkarmaya çalışıyor yoksa bunları ben mi yapıyorum? kimseye tepeden bakacak durumda değilim, yanlış davranana yanlış davranıyorum eğlence amaçlı da şakayla karışık dalga geçerek eğleniyorum, çok da şey yapmaya gerek yok bence..
 
Son düzenleme:
başladık yine…

-> bu kaynak dosyalar 2014 yılında sızdırıldı hadi 10 sene geliştirme görmedi diyelim, 2005de kitap falan yok muydu? bu savunmayı neden insanlar ısrarla yapıyor anlayamıyorum
-> AI olup olmaması bir etken değil, yazılmış onlarca kitap var açıp okuyabilirlerdi
-> benim karşı olduğum yapay zeka değil yorum yazarken bile yapay zeka kullanmak, bilmediğin konu hakkında yapay zeka çıktısını argüman olarak sunmak, burda birini ezme gibi bir niyetim neden olsun bu bana ne kazandırır?
-> gariptir ki sorunu paylaşınca herkes bir anda çözüm uzmanı oldu, 1 saatte analizleri bitirip karşı argüman sundu falan neyse bugüne kadar kimsenin değinmemiş olması çok garip, maşallah diyelim umarım daha iyi yerlere gelirsiniz ben mutlu olurum
-> not olarak farklı durumların meydana gelebileceğini yazdım, doğru çözümdür diye bir şey söylemedim, bu bir analiz çözümde atladığım case olabilir metin2'yi ben geliştirmedim, core ekipten de değilim, ben bir şey söylerim başkası bak şu da var bir bak istersen der ve sonuç olarak çözüme ulaşırsınız, bazı vasıfsızların yaptığı gibi "AĞĞĞĞ HATA YAPTI AĞĞĞĞ" denmez(normal şartlarda)
-> metin2 ile ne mühendisliği, ortada mühendislik ürünü yok ki üzerine mühendislik yapasınız
-> burada kendimi “iyi yazılımcı” diye lanse etme veya gelsin biri bana “bu adam iyi” desin gibi dertlerim yok. isteyen istediğini düşünebilir biz 40 kişiyiz birbirimizi biliriz, ben bu forumdaki kötü yazılımcılardan biriydim
-> egomu tatmin etmek istesem çalıştığım şirketin kodlarımın koştuğu ürünleri nerelere satıyor diye bakardım metin2 forumu aklıma gelmez diye düşünüyorum


metin2 kompleks bir yazılım(yani karmaşık, anlaşılması, üzerinde çalışılması zor), boş vakitlerimde metin2 ile uğraşırken karşıma çıkan bir şey olursa genelde burada paylaşıyorum. son 2-3 aydır kaç tane hata analizi ve fix veya bence faydalı olabilecek konu paylaştım hiçbirine teşekkür etmeyip(birinden bir şey beklediğimden değil, kimse böyle bir şey yapmak zorunda değil örnek veriyorum) bir tanesinde gözden bir şey kaçırmışız diye bana burda “AAAA GÖZDEN KAÇIRMIŞ LAF ATINNN TAŞLAYINNN VATAN HAİNİ AAAA ZATEN EGOIST BU” yaklaşımıyla laf atanlar mı egoist ve kendini öne çıkarmaya çalışıyor yoksa bunları ben mi yapıyorum? kimseye tepeden bakacak durumda değilim, yanlış davranana yanlış davranıyorum eğlence amaçlı da şakayla karışık dalga geçerek eğleniyorum, çok da şey yapmaya gerek yok bence..
-> Her paylaşımında katkılı/faydalı gördüğüm zaman teşekkür etmişimdir, şuan ki konuda bile. (Bakabilirsin)

-> "gariptir ki sorunu paylaşınca herkes bir anda çözüm uzmanı oldu, 1 saatte analizleri bitirip karşı argüman sundu falan neyse bugüne kadar kimsenin değinmemiş olması çok garip, maşallah diyelim umarım daha iyi yerlere gelirsiniz ben mutlu olurum" e tabi ki, eleştirmemiz lazım, herkes eleştiriye açık olmalıdır, ister çözüm ai ile olsun ister çok yetenekli olsun yazdığı şey doğruysa, senin ilgi alanın sadece yanlışı görmek olur, yorum yapanların neyi nasıl çözdüğü değil bence.

-> 2014 yılında sızdırılan bir şey 2014 yılında yapılmış olmuyor, bu adamlar sonuç olarak 2005 yıllarında paylaştılar belki 3 sene sürdü yapım nihayetinde 2000 li yılın başlarında yaptılar ve devrim niteliğinde, yapabilen çıksın daha iyisini yapsın, 40 kişisiniz bence iyi bir hatasız metin3 yapabilirsiniz bizde oynar takdir ederiz. Kitap var diye kusursuz olacağı anlamına gelmiyor, sen tüm standartlara hakim misin, tüm kitapları bitirdin mi, her türlü UB durumlarını biliyor musun, her türlü idiom tekniğin var mı, TRIZ algoritmasıyla mı çalışıyorsun. Her şeyin profesyonel ve kusursuz mu?, Lütfen bırakın bu tavırları hoş değil, ahlaklı değil.

-> İnsan hata yapan bir varlıktır, başkasının hatası oluyorsa senin de garanti olacaktır, çokta şey yapmamak lazım.
Düşünsene, çalıştığın şirkette yürüyen kodunda 20 sene sonra başkası senin kodunu incelerken hatalarını buluyor, ve şöyle diyor,
"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."

Bence uzatmaya gerek yok sonuçta haklı bulmayacaksın, tutumunu savunuyorsun. Tekrar paylaşım için teşekkürler. Eksik stale noktalar düzeltilerek, düzenlenirse faydalı bir paylaşım.
 

Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)

Geri
Üst