dev

Modern Web Geliştirmede Regex: Motor Mimarisi ve ReDoS Koruması

Regex, metin ayrıştırma ve veri doğrulamanın en güçlü aracıdır. Ancak hatalı yazılmış bir desen, CPU kullanımını %100'e kilitleyen ReDoS açıklarına yol açabilir. NFA motor çalışma mantığını, ileri düzey gruplama tekniklerini ve performans kurallarını keşfedin.
İlgili AraçBu mimariyi tarayıcınızda canlı test edin: Regex Test Edici
Aracı Aç

1. Regex Motor Mimarisi: NFA (Non-deterministic Finite Automaton)

JavaScript, Python, PHP ve Java gibi dillerin regex motorları 'Non-deterministic Finite Automaton' (NFA) prensibiyle çalışır. NFA motorları desendeki her alternatifi sırayla dener. Eşleşme başarısız olduğunda bir önceki karar noktasına geri dönerek diğer ihtimalleri test eder; bu işleme Geriye İzleme (Backtracking) adı verilir.

Geriye izleme adımları doğru sınırlandırılmadığında, girdi metni uzadıkça denenmesi gereken kombinasyon sayısı üstel olarak artar (O(2^n)) ve tarayıcı veya backend sunucusu dakikalarca yanıt veremez hale gelir.

2. İleri Düzey Desenler: Lookahead, Lookbehind ve Non-Capturing Gruplar

Verileri doğrulamak ve ayıklamak için imleci ilerletmeden kontrol sağlayan ileri düzey regex teknikleri kullanılır:

Pozitif Lookahead (?=...) ve Negatif Lookahead (?!...): İmleci tüketmeden önündeki karakterlerin belirli bir kurala uyup uymadığını denetler. Örneğin güçlü parola doğrulama kuralları için vazgeçilmezdir.

Yakalamayan Gruplar (?:...): Parantez içindeki ifadeyi gruplar ancak yakalama belleğine (capturing group) almaz. Bu durum motorun bellek tahsisini azaltarak Regex çalışma hızını %20-30 oranında artırır.

GÜÇLÜ PAROLA VE KURUMSAL E-POSTA REGEX ÖRNEKLERİ
// 1. Güvenli Parola Doğrulama:
// En az 8 karakter, 1 büyük harf, 1 küçük harf, 1 rakam ve 1 özel karakter
const STRONG_PASSWORD_REGEX = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,64}$/;

// 2. RFC 5322 Uyumlu Sadeleştirilmiş E-posta Doğrulama:
const EMAIL_REGEX = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/;

// 3. Binlik Basamak Ayracı (Pozitif Lookahead):
function formatCurrency(number) {
  return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}

3. ReDoS (Regular Expression Denial of Service) Tehdidi

İç içe geçmiş tekrarlayıcılar (nested quantifiers) içeren desenler ReDoS saldırılarına karşı son derece savunmasızdır. Örneğin /^(a+)+$/ deseni ele alındığında, 'aaaaaaaaaaaaaaaaaaaa!' gibi sonu eşleşmeyen bir girdi gönderildiğinde motor milyonlarca permütasyonu dener ve CPU'yu %100 tüketir.

Saldırganlar bu açığı kullanarak web sunucularının tüm çekirdeklerini kilitleyebilir ve hizmet kesintisine (DDoS) yol açabilir.

ReDoS'tan Korunma KuralıAsla (a+)+ veya ([a-zA-Z]+)* gibi iç içe belirsiz tekrarlayıcılar kullanmayın. Karakter kümelerini daima ayrık (mutually exclusive) tutun ve kullanıcı girdilerine maksimum karakter uzunluğu sınırı (maxlength) koyun.

4. JavaScript'te Regex Performans Optimizasyonları

Performans açısından en sık yapılan hatalardan biri, döngü veya sık çağrılan fonksiyonlar içinde sürekli new RegExp() nesnesi üretmektir. Bu durum her çağrıda regex motorunun deseni baştan derlemesine ve çöp toplayıcının (Garbage Collector) aşırı çalışmasına neden olur:

Regex desenleri daima modül düzeyinde statik olarak tanımlanmalı veya /pattern/g biçiminde sabit bir değişken olarak saklanmalıdır.

DÖNGÜ İÇİ REGEX PERFORMANS KARŞILAŞTIRMASI
// ❌ YANLIŞ YAKLAŞIM (Her satırda baştan derlenir):
function validateLinesBad(lines) {
  return lines.filter(line => new RegExp('^[A-Z]{3}-\d{4}$').test(line));
}

// ✅ DOĞRU YAKLAŞIM (Statik olarak tek kez derlenir):
const CODE_PATTERN = /^[A-Z]{3}-\d{4}$/;
function validateLinesGood(lines) {
  return lines.filter(line => CODE_PATTERN.test(line));
}

5. Canlı Test ve Sınır Durumları (Edge Cases)

Yazılım Motoru Regex Test Aracı; bayrakları (g, i, m, s, u), eşleşme gruplarını ve yakalanan metin parçalarını anlık olarak görselleştirir. Kodunuza entegre etmeden önce boşluklar, Türkçe karakterler, yeni satır karakterleri ve sınır durumlarını bu araç üzerinde doğrulayabilirsiniz.

Sıkça Sorulan Sorular & Teknik Detaylar

Regex 'g' (global) bayrağı kullanıldığında lastIndex sorunu nedir?

Global bayraklı (/pattern/g) bir RegExp nesnesi test() ile çağrıldığında, bir sonraki arama için lastIndex değerini günceller. Aynı nesneyle tekrar test yapıldığında beklenmedik şekilde false dönebilir. Fonksiyon içi doğrulamalarda global bayrak kullanılmamalı veya lastIndex = 0 ile sıfırlanmalıdır.

Regex motorları Türkçe karakterleri (ş, ğ, ı, ü, ö, ç) nasıl ele alır?

Standart [a-z] sadece İngilizce ASCII karakterleri eşleştirir. Türkçe karakterler için ya [a-zA-ZçğıöşüÇĞİÖŞÜ] şeklinde açık karakter kümesi kullanılmalı ya da 'u' (Unicode) bayrağıyla \p{Letter} Unicode özelliği tercih edilmelidir.

Regex yerine String metotları (includes, startsWith) kullanmak daha mı hızlıdır?

Evet. Basit alt dize aramalarında String.prototype.includes() veya startsWith() regex derleme maliyeti olmadığı için Regex'ten 3-5 kat daha hızlı çalışır.

İlgili AraçRegex Test Edici aracını kullanarak bu işlemi doğrudan tarayıcınızda gerçekleştirin.
Aracı Aç