المستوى المطلوب: محترف. يفترض هذا المقال إلمامك بالتعابير النمطية (Regex) وبأساسيات تعقيد الخوارزميات. لو التعابير النمطية جديدة عليك تمامًا، اقرأه على مهل — الأمثلة تشرح الفكرة قبل التعريف العلمي.
تعبير نمطي واحد، مكتوب بحسن نية للتحقق من مدخل، يقدر يرفع استهلاك المعالج إلى 100% ويجمّد خدمتك بمدخل طوله 30 حرفًا. المشكلة اسمها التراجع الكارثي (Catastrophic Backtracking)، والثغرة الناتجة اسمها ReDoS. هنا هتعرف ليه بتحصل بالظبط، وإزاي تقيسها بنفسك، وإزاي تقفلها.
لماذا يتحوّل تعبير نمطي بريء إلى هجوم حرمان من الخدمة
المشكلة باختصار
معظم محرّكات Regex الشائعة (PCRE، وJava، وJavaScript، ومكتبة re في بايثون) تستخدم خوارزمية تراجع (backtracking). الخوارزمية دي مرنة وبتدعم مزايا زي الـ backreferences، لكن ثمنها إن زمن تنفيذها ممكن يقفز أسّيًا مع طول المدخل. الافتراض إن أي مدخل نصّي بسيط بيتعالج بسرعة — والافتراض ده غلط مع أنماط معيّنة.
المفهوم: أولًا بمثال بسيط
تخيّل موظف بيحاول يوزّع 30 كرة على صندوقين، والشرط إن ما يفضلش أي صندوق فاضي، وفي الآخر لازم تكون آخر كرة حمرا. لو كل الكرات زرقا، هو مش هيكتشف إن الشرط مستحيل من أول محاولة. هيجرّب كل توزيعة ممكنة: 29 كرة في الأول وواحدة في التاني، 28 و2، وهكذا، وكل توزيعة يعيد تقسيمها من جوّه. عدد المحاولات بينفجر، وهو بيدوّر على حل غير موجود أصلًا.
محرّك الـ Regex بيعمل نفس الحاجة بالظبط. لمّا يقابل نمط زي (a+)+$ مع نص كله a منتهي بحرف مش مطابق (زي !)، بيوزّع الحروف على الكمّيتين المتداخلتين بكل الطرق الممكنة قبل ما يستسلم.
المفهوم: الآن علميًا وبدقّة
الكمّيتان المتداخلتان (a+)+ بتخلّقان غموضًا: سلسلة من n حرف a ممكن تتقسّم على المجموعات الداخلية بعدد يتناسب مع 2^n طريقة. طالما في تطابق ناجح، المحرّك بيلاقي أول طريقة وبيقف. لكن لو المدخل فشل في آخر خطوة (بسبب $ اللي مش هيتحقق)، المحرّك مجبر يجرّب كل التقسيمات قبل ما يعلن الفشل. النتيجة تعقيد زمني أسّي O(2^n) بدل الخطي.
الرقم اللي بيصدم: عند 30 حرفًا فقط، 2^30 يساوي تقريبًا 1.07 مليار خطوة. ده بيترجم لثوانٍ من المعالجة على نواة واحدة، مقفولة 100%، من غير أي شبكة أو قاعدة بيانات في المعادلة.
قِس المشكلة بنفسك
الكود ده بيوريك الانفجار بعينك. شغّله واطبع الزمن لكل طول مدخل. الافتراض إنك على مكتبة re القياسية في بايثون (محرّك تراجع).