Bosh sahifa Wiki Double free

Double free

Double free — ayni dinamik xotira blokini uning lifetime’i tugaganidan keyin ikkinchi marta allocatorga qaytarish xatosidir. Birinchi freedan so‘ng pointer dangling bo‘ladi; ikkinchi chaqiriq allocator metadata’sini buzishi, jarayonni to‘xtatishi yoki ekspluatatsiya uchun primitive berishi mumkin. Xatti-harakat C va C++ kabi tillarda aniqlanmagan.

Kelib chiqish holatlari

Bir obyektga ikki modul o‘zini egadek munosabat qilishi keng sababdir. Xato yo‘lida cleanup bajarilib, caller ham yana free qilishi mumkin. Murakkab goto cleanup, istisno va qisman initialization bir resursni bir nechta yo‘ldan bo‘shatadi. Reference count noto‘g‘ri kamaytirilsa obyekt erta ozod bo‘ladi va keyin yana destructor chaqiriladi.

Concurrencyda ikki oqim ayni pointer holatini ko‘rib, ikkalasi ham oxirgi egaman deb free qilishi mumkin. Pointerga NULL yozish atomar ownership protokoli emas; ikkinchi oqim avvalgi qiymat nusxasini saqlagan bo‘lishi mumkin.

Allocatorga ta’siri

Allocator freed blokni free list yoki thread cache’ga qo‘shadi. Ikkinchi free bir blokni ro‘yxatga ikki marta kiritishi mumkin. Keyingi ikki allocation ayni manzilni turli obyektga beradi va ular bir-birining ma’lumotini buzadi. Zamonaviy allocatorlar duplicate entry, cookie va safe-linking bilan ayrim holatni aniqlaydi.

Himoya barcha interleaving va custom allocatorni qamramaydi. Hujumchi free list boshqaruvini manipulyatsiya qilib, keyingi allocation manziliga ta’sir qilishga urinishi mumkin. ASLR va allocator hardening xavfni kamaytiradi, lekin memory safety xatosi qoladi.

Aniqlash

AddressSanitizer allocation va birinchi free stackini saqlab, ikkinchi free’da aniq report beradi. Debug allocator freed blokni quarantine’da ushlab, qayta foydalanishni kechiktiradi. Static analyzer ownership yo‘llari va double cleanupni topishi mumkin. Fuzzing kam uchraydigan error pathni majburlaydi.

Production crashda allocator “double free or corruption” deb to‘xtashi mumkin, ammo metadata oldinroq buffer overflow bilan buzilgan bo‘lishi ham ehtimol. Faqat oxirgi free joyi emas, pointerga barcha yozuv va birinchi lifetime tugashi tekshiriladi.

Oldini olish

Har resursning bitta aniq egasi bo‘ladi. Move semantics ownershipni eski o‘zgaruvchidan yangisiga ko‘chirib, eskisini bo‘sh holatga keltiradi. Smart pointer destructorni aynan bir marta chaqiradi; shared pointer faqat boshqaruv blokini to‘g‘ri bo‘lishganda xavfsiz. Bir raw pointerdan ikki mustaqil smart pointer yaratish baribir double free keltiradi.

Cleanup idempotent API bo‘lishi mumkin, ammo allocator freening o‘zi umumiy holda idempotent emas. Wrapper handle holatini ichki nazorat qiladi va takror close’ni no-opga aylantiradi. C API ownershipni create, borrow, take kabi nom va hujjat bilan belgilaydi. Memory-safe tillar bu xatoni ko‘p holatda ownership yoki garbage collection orqali yo‘q qiladi, native extensionlar alohida sanitizatsiya bilan sinovdan o‘tadi.

Resource handlelar

Double free g‘oyasi xotiradan tashqari file descriptor, socket va GPU buffer kabi handlelarda ham uchraydi. Descriptor yopilgach operatsion tizim ayni kichik raqamni boshqa faylga berishi mumkin; eski egasi yana close qilsa yangi resursni tasodifan yopadi. Shu sababli handle ownership ko‘chirilganda eski joy invalid qiymatga atomar o‘tkaziladi. Shutdown va error callback bir vaqtda cleanup qilsa state compare-and-swap bilan faqat bitta g‘olibni tanlaydi. Idempotent yuqori darajali close ichki holatni lock bilan tekshirishi mumkin, ammo concurrent methodlar close’dan keyingi foydalanishni ham to‘xtatishi kerak.

Bog‘liq tushunchalar

Use-after-free, Heap corruption, Allocator, Ownership, AddressSanitizer, Smart pointer