سینیٹائزر ہینڈ بک: میموری، ابتدا، اور تنازعہ۔

کچھ انتہائی خطرناک بنیادی خرابیاں ان پروگراموں کی وجہ سے ہوتی ہیں جو بظاہر درست طریقے سے کام کر رہے ہیں۔

انکرپشن آپریشن درست سائفر ٹیکسٹ لوٹاتا ہے۔ تجزیہ کار غلط ان پٹ کو مسترد کرتا ہے۔ کیش بینچ مارکس کو برقرار رکھتا ہے۔ رہائی کا امیدوار تمام یونٹ اور انضمام کے ٹیسٹ پاس کرتا ہے۔

تاہم، صحیح نتیجہ کے نیچے کہیں، ریپر کو اب بھی یقین ہے کہ وہ اس ہینڈل کا مالک ہے جو پہلے سے بھیجا گیا تھا۔ کسی بھی آؤٹ پٹ فیلڈ کو شروع کیے بغیر کامیابی کا راستہ واپس آ جاتا ہے۔ فائنلائزر فی الحال ایک ایسی چیز کو آزاد کرنے کا انتظار کر رہا ہے جس کی زندگی کو دوسرے رن ٹائم کے ذریعے کنٹرول کیا جاتا ہے۔ دو تھریڈز ایک ہی حالت کو تبدیل کرتے ہیں، لیکن شیڈیولر نے انٹرلیونگ کا انتخاب نہیں کیا ہے، جو تنازعہ کی نشاندہی کرتا ہے۔

متوقع پیداوار ضروری طور پر اس کو ظاہر نہیں کرے گی۔

پہلی قابل مشاہدہ ناکامی مختص کرنے والے کے آزاد کردہ علاقے کو دوبارہ استعمال کرنے کے کئی گھنٹے بعد ہو سکتی ہے، کچرا جمع کرنے کے چکر کی وجہ سے پہنچنے کی صلاحیت میں تبدیلی آتی ہے، باہر نکلنے کا راستہ بالآخر ایک لیک شدہ مختص کا سبب بنتا ہے، یا پروڈکشن ٹریفک ایک ہم آہنگی کا نمونہ تیار کرتا ہے جو ٹیسٹ سویٹ میں نہیں کیا گیا تھا۔ تب تک، کریش اسٹیک اکثر بگ مصنف کی بجائے بگ کے شکار سے تعلق رکھتا ہے۔

یہ وہی ہے جو کریوس ڈس انفیکٹینٹس کو بند کرنے کے لیے بنایا جاتا ہے۔ یہ کریشوں کو ڈیبگ کرنا آسان بنانے کے علاوہ بھی بہت کچھ کرتا ہے۔ وہ ان مفروضوں کو رن ٹائم سیمنٹکس دیتے ہیں کہ باقاعدہ ٹیسٹ عام طور پر مضمر چھوڑ دیتے ہیں۔ یہ پتہ اب بھی رسائی کے لیے درست ہے، اس مختص کا اب بھی ایک قانونی مالک ہے، اس قدر کی ابتدا اس سے پہلے کی گئی تھی کہ اس نے عمل درآمد کو متاثر کیا، یا اس مشترکہ میموری تک رسائی کو مطابقت پذیری کے مطابق ترتیب دیا گیا ہے جس کا رن ٹائم مشاہدہ کر سکتا ہے۔

Address Sanitizer (ASan)، LeakSanitizer (LSan)، Memory Sanitizer (MSan)، اور Thread Sanitizer (TSan) ایک ہی ڈیبگنگ موڈ کے چار تغیرات نہیں ہیں۔ وہ پھانسی کی مختلف خصوصیات کا مشاہدہ کرتے ہیں۔

ASan ایڈریس ایبلٹی اور لائف ٹائم کو ٹریک کرتا ہے۔ LSan پوچھتا ہے کہ ٹیر ڈاؤن پر کون سی مختصات فعال رہتی ہیں، اور کیا کنکشن کے باقی امکانات معقول ہیں۔ MSan ابتدائی ماخذ کی پیروی کرتا ہے۔ TSan کنورنٹ رسائی کی اجازت دینے کے لیے پہلے سے ہونے والے تعلقات کو دوبارہ تشکیل دیتا ہے۔

کمپائلر کے جھنڈے کو قبول کرنے کے بعد مشکل حصہ شروع ہوتا ہے۔

سینیٹائزر کی تعمیرات صرف اس صورت میں کارآمد ہیں جب آپ حقیقت میں سمجھتے ہیں کہ آپ کیا دیکھ رہے ہیں۔ کون سے ماڈیول آلات بنائے گئے ہیں؟ رن ٹائم پر کون سا ایلوکیٹر یا سنکرونائزیشن آپریشن نظر نہیں آتا؟ کیا مفید فریموں کی شناخت کے لیے رپورٹ کو کافی اچھی طرح سے نشان زد کیا جا سکتا ہے؟ کیا آپ کے کام کے بوجھ کو چھوٹی گاڑی کی ملکیت کی منتقلی، ناکامی کے راستے، یا دھاگے کے انٹرلیونگ کا سامنا کرنا پڑا ہے؟

اور ایک بار جب لین قابل اعتماد ثبوت پیش کرتا ہے، تو اس کا تعلق کہاں سے ہے؟ ہر پل کی درخواست پر، سست شیڈول ملازمتوں پر، یا ابتدائی مشاہدے کے موڈ میں جب آپ بیس لائن کو سمجھتے ہیں؟

یہ سوالات خاص طور پر منظم/مقامی حدود پر تیز ہو جاتے ہیں۔ Dart, Java, Python, Swift, C#، یا Rust wrappers APIs فراہم کر سکتے ہیں جو پہلے سے طے شدہ حوالہ شمار، مختص کرنے والے جوڑوں، ادھار شدہ پوائنٹرز، نقل و حمل پر کامیابی کے قواعد، کال بیکس، اسٹیڈیم اور فائنلائزرز کی بنیاد پر محفوظ دکھائی دیتے ہیں۔ زبان کی حدود ان اصولوں کو نہیں ہٹاتی ہیں۔ دو رن ٹائمز پر تعینات کرنا جن کی ملکیت اور زندگی بھر کے بارے میں بہت مختلف خیالات ہوسکتے ہیں۔

اس ہینڈ بک میں بہت سی مثالیں اس قسم کی حد تک واپس آتی ہیں۔ یعنی وہ کوڈ جو باہر سے تو سادہ نظر آتا ہے لیکن اندر سے زندگی کے بنیادی اصولوں کو برقرار رکھنا چاہیے۔

google/webcrypto.dart یہ ایک دہرائی جانے والی مثال ہوگی۔ یہ ڈارٹ ایف ایف آئی، بورنگ ایس ایس ایل ہینڈلز، فائنلائزرز، اسکوپنگ کلین اپ، ہکس کی تعمیر، اور ملکیت کی منتقلی کو نسبتاً کمپیکٹ سسٹم میں یکجا کرتا ہے۔ یہ ایک بہت ہی عام انجینئرنگ رکاوٹ کی ایک کم چمکدار، لیکن مفید مثال ہے۔ بعض اوقات، آپ کی مطلوبہ سینیٹائزر سیٹنگز کو آس پاس کے ٹول چین کے ذریعے بلاک کر دیا جاتا ہے، اور آپ کو فیصلہ کرنا ہوتا ہے کہ اس دوران آپ کو رن ٹائم کے کون سے مفید ثبوت مل سکتے ہیں۔

یہ مسئلہ ڈارٹ یا کرپٹوگرافی تک محدود نہیں ہے۔ حقیقی دنیا کے نظام شاذ و نادر ہی مکمل طور پر قابل انحصاری گراف، ایک کوآپریٹو رن ٹائم، مکمل علامت نگاری، اور لامحدود CI وقت ایک ساتھ فراہم کرتے ہیں۔ عملی سوال عموماً تنگ ہوتا ہے۔ اس تعمیر کے لئے فی الحال کیا قابل مشاہدہ ہے، کیا قابل مشاہدہ نہیں ہے، اور کام کا بوجھ کیا ہے جو دستیاب شواہد کو معنی خیز بناتا ہے؟

یہ اس کتابچہ کی دلیل ہے: سینیٹائزر رن ٹائم معاہدوں کو قابل عمل بناتے ہیں۔. ملکیت ایک بار بار چلنے والا حصہ ہے، خاص طور پر ایف ایف آئی کی حدود میں، لیکن اسی طرح ابتدا اور ہم آہنگی بھی ہے۔ فزرز، تناؤ کے ٹیسٹ، ناکامی کے انجیکشن، اور ہم آہنگی کی تحقیقات پھانسیاں پیدا کرتی ہیں جو اس معاہدے کو چیلنج کرتی ہیں۔ سینیٹائزر رن ٹائم خلاف ورزیوں کو ظاہر کرتا ہے۔ CI اس بات کا تعین کرتا ہے کہ آیا یہ نتائج پائیدار ریگریشن پروٹیکشن بن جاتے ہیں یا ایک بار ڈیبگنگ ایونٹس کے طور پر رہتے ہیں۔

اگلے ابواب میں، ہم اس ماڈل سے شیڈو میموری، لیک ریچ ایبلٹی، انیشیلائزیشن ٹریکنگ، ریس کا پتہ لگانے، FFI کی ملکیت، کام کا بوجھ ڈیزائن، رپورٹ کی درجہ بندی، اور ریلیز پالیسی کی طرف بڑھتے ہیں۔ مقصد صرف جراثیم کش ادویات کا استعمال نہیں ہے۔ یہ اس بات کو سمجھنے کے بارے میں ہے کہ کلین رن اصل میں آپ کو کیا بتاتا ہے، رپورٹ آپ کو آپ کے کوڈ میں موجود مفروضوں کے بارے میں کیا بتاتی ہے، اور ٹول کی نظر سے باہر کیا رہ جاتا ہے۔

انڈیکس

شرائط

یہ ہینڈ بک بنیادی کوڈ ڈیبگنگ اور کنکرنٹ پروگرامنگ کا بنیادی علم فرض کرتی ہے۔ C یا C++ بنیادی اصولوں کو دوبارہ متعارف کرانے کے بجائے، یہ پوائنٹرز، ایلوکیشن، تھریڈ سنکرونائزیشن، بلڈ سسٹمز اور CI پر بنتا ہے۔

یہاں توجہ متحرک عملدرآمد کے ثبوت پر ہے – سینیٹائزر کا رن ٹائم کیا مشاہدہ کرسکتا ہے، ان رپورٹس کا کیا مطلب ہے، اور کس طرح ملکیت، ابتدا، اور ہم آہنگی کے مفروضے کام کے بوجھ اور ارد گرد کی پائپ لائن کو تشکیل دیتے ہیں۔

یہاں وہ ہے جس سے آپ کو پہلے ہی واقف ہونا چاہئے:

  • مقامی اسٹیک ٹریس کو پڑھیں اور کالر، کالی، ایلوکیشن اور صفائی کے راستوں کے درمیان چھلانگ لگائیں۔

  • بنیادی ملکیت کے تصورات جیسے کہ ادھار اور ملکیتی اشارے، ملکیت کی منتقلی، حوالہ شماری، اور تعییناتی صفائی۔

  • ایک عملی سطح پر ہیپ اور اسٹیک ایلوکیشن، بشمول ایلوکیٹر کے جوڑے اور آبجیکٹ لائف ٹائم کیوں اہم ہیں۔

  • ہم آہنگی کے بنیادی اصول جیسے mutexes، atomicity، دھاگے کی تخلیق، اور یہ خیال کہ دھاگوں کے درمیان ترتیب کو فرض کرنے کے بجائے قائم کیا جانا چاہیے۔

  • کمانڈ لائن سے ٹیسٹ بنائیں اور چلائیں اور مقامی ڈیبگ بلڈز اور سی آئی بلڈز کے درمیان فرق کو سمجھیں۔

اور یہاں مثالوں کے ساتھ کیا پیروی کرنا ہے:

  • تک رسائی کے ساتھ تازہ ترین کلینگ/LLVM ٹول چین: clang, clang++اور llvm-symbolizer.

  • زیادہ تر کمپائلر پر مبنی مثالوں کے لیے لینکس یا میکوس ماحول۔ لینکس مثالوں کے مکمل سیٹ اور ویلگرینڈ لین کے لیے سب سے زیادہ عملی ماحول ہے۔

  • تیار کردہ بائنری کو کیسے چلائیں اور لاگز اور کریش آرٹفیکٹس کو کیسے محفوظ کریں۔

  • اختیاری طور پر پورے عمل اور FFI فال بیک کی مثال دیکھنے کے لیے Valgrind تک رسائی حاصل کریں۔

  • اختیاری ڈارٹ ٹولنگ webcrypto.dart کیس اسٹڈی۔ ملکیت کے تجزیہ پر عمل کرنے کے لیے آپ کو کسی بھی ڈارٹ تجربے کی ضرورت نہیں ہے۔

  • اور، کم رسمی طور پر، آپ کے پاس فائل کو چھونے والے آخری شخص پر الزام لگانے سے پہلے اسٹیک ٹریس کو پڑھنے کے لیے کافی صبر ہے۔ 🙂

ہم ایک طویل کمپائلر یا ماحولیاتی سیٹ اپ واک تھرو سے نہیں گزریں گے۔ کمانڈز فرض کرتے ہیں کہ آپ کے پاس متعلقہ کمپائلر اور رن ٹائم پیکجز انسٹال ہیں اور انسٹرومینٹیشن، رپورٹس، ورک بوجھ اور پالیسیوں پر فوکس کرتے ہیں۔

مزید برآں، یہ جنرل میموری مینجمنٹ، تھریڈنگ، فزنگ، یا کمپائلر کنفیگریشن کو دوبارہ نہیں سکھاتا ہے۔ صرف وہی حصے جو ہمارے جراثیم کش نتائج کی تشریح کرنے کے طریقے کو بدلتے ہیں تفصیل سے تیار کیے جاتے ہیں۔

درست نتائج اور درست عملدرآمد کے درمیان فرق

شیڈو میموری، لیک روٹس، اوریجن ٹریکنگ، یا پہلے سے ہونے والے گراف میں جانے سے پہلے، دو خصوصیات کو الگ کرنا مددگار ہے جنہیں آسانی سے جوڑا جا سکتا ہے۔ فنکشنل درستگی اور عملدرآمد کی تاثیر.

روایتی ٹیسٹ فنکشنل سوالات پوچھتے ہیں۔ اس ان پٹ کو دیکھتے ہوئے، کیا نظام نے متوقع قیمت واپس کی، متوقع حالت کو تبدیل کیا، یا متوقع ضمنی اثر پیدا کیا؟

سینیٹائزر کچھ اور پوچھتا ہے۔ کیا وہ رن جس نے ان نتائج کو درست کیا؟

یہ سوالات متضاد ہیں لیکن ایک جیسے نہیں ہیں۔ بنیادی کلید کو لیک کرتے وقت فنکشن صحیح سادہ متن واپس کر سکتا ہے۔ تجزیہ کار غیر شروع شدہ آؤٹ پٹ کی لمبائی کو پڑھتے ہوئے غلط ان پٹ کو مسترد کر سکتا ہے جو مسترد ہونے کے عمل میں ہے۔ ریپر مہینوں تک صحیح طریقے سے کام کر سکتا ہے جبکہ یہ مانتے ہوئے کہ دو مختلف اشیاء دونوں ایک ہی بنیادی ہینڈل کے مالک ہیں۔ ایک لاک لیس کیش تمام تعییناتی امتحانات کو پاس کر سکتا ہے اور پھر بھی یہ تنازعہ رکھتا ہے کہ شیڈیولر نے ابھی تک بے نقاب نہیں کیا ہے۔

یہ امتیاز جراثیم کشی کے کام کا نقطہ آغاز ہے۔

خاکہ دکھاتا ہے کہ کیوں پاس ہونے والا امتحان ہمیشہ درست عمل نہیں ہوتا۔ سینیٹائزر چھپے ہوئے رن ٹائم معاہدوں کی نشاندہی کرتا ہے جو عام آؤٹ پٹ پر مبنی ٹیسٹوں سے چھوٹ سکتے ہیں۔

کیڑے اکثر وہاں سے نکلتے ہیں جہاں حادثہ ہوا تھا۔

میموری کیڑے شاذ و نادر ہی پہلی جگہ ناکام ہوتے ہیں۔

آپ کی پہلی غلطی چھوٹی ہو سکتی ہے۔ حوالہ جاتی اضافہ غائب، ملکیت کی منتقلی کے بعد بھی پوائنٹر دستیاب ہیں، غلط دائرہ کار سے کلین اپ کال بیکس ہٹا دیے گئے، کامیابی کے ایک راستے پر خارجی پیرامیٹرز اچھوت چھوڑے گئے، یا فائنلائزر بہت دیر سے الگ ہوئے۔

نظر آنے والی خرابیاں بہت بعد میں، دوسرے اجزاء میں، دوسرے تھریڈز میں، یا شٹ ڈاؤن کے دوران ہو سکتی ہیں۔ تب تک، کریش سائٹ پر موجود اسٹیک اکثر اس کوڈ کی بجائے بگ کی وجہ سے پیدا ہونے والے کوڈ کی وضاحت کرتا ہے۔

سینیٹائزر مددگار ہے کیونکہ یہ رن ٹائم کی حالت کو برقرار رکھتا ہے جو عام طور پر نہیں ہوتا ہے۔ ASan ٹریک کرتا ہے کہ آیا میموری قابل شناخت ہے اور یہ کسی چیز کی زندگی بھر میں کیسے تبدیل ہوتی ہے۔ MSan ابتدائی حالت کا پرچار کرتا ہے۔ TSan میموری تک رسائی اور ہم آہنگی کے تعلقات کو ریکارڈ کرتا ہے۔ Lsan چیک کرتا ہے کہ جب کوئی عمل ختم ہوجاتا ہے تو کیا قابل رسائی رہ جاتا ہے۔

اضافی ریاستیں حادثے کے حتمی مقام سے زیادہ فراہم کرتی ہیں۔ ٹول پر منحصر ہے، رپورٹ یہ ظاہر کر سکتی ہے کہ اشیاء کہاں مختص اور ڈی ایلوکیٹ کی جاتی ہیں، کہاں غیر شروع شدہ اقدار ہوتی ہیں، یا جہاں تھریڈز کے درمیان رسائی کی ریس ہوتی ہے۔ رپورٹ کو اب بھی تشریح کی ضرورت ہے، لیکن یہ پروگرام غلط حالت میں کیسے پہنچا اس کی تشکیل نو شروع کرنے کے لیے کافی تاریخ فراہم کرتی ہے۔

درست آؤٹ پٹ غلط عمل کو چھپا سکتا ہے۔

ایک بنیادی API پر غور کریں جو کال کرنے والے کے ذریعہ فراہم کردہ بفر پر 32 بائٹ ڈائجسٹ لکھتا ہے۔

bool digest(const uint8_t* input, size_t input_len, uint8_t* output, size_t* output_len);

معقول معاہدہ یہ ہے کہ صحیح واپسی کا مطلب یہ ہے کہ آؤٹ پٹ اور *output_len دونوں کو شروع کیا گیا ہے۔ اب کہتے ہیں کہ ایک کامیابی کا راستہ ڈائجسٹ لکھتا ہے، لیکن اس کی لمبائی طے کرنا بھول جاتا ہے۔

یونٹ ٹیسٹ جو صرف 32 ڈائجسٹ بائٹس کو چیک کرتے ہیں اب بھی پاس ہو سکتے ہیں۔ کال کرنے والا ایک غیر شروع شدہ اسٹیک سلاٹ سے 32 پڑھ سکتا ہے جو بگ کے چھپنے کے لیے کافی ہوتا ہے۔

MSan "کیا اقدار درست نظر آتی ہیں؟” سے زیادہ مفید سوالات پوچھتا ہے۔ اشارہ کرتا ہے کہ آیا پروگرام اس قدر کو استعمال کرنے سے پہلے اس قدر کی شروعات کی ایک جائز تاریخ تھی۔

زندگی بھر، کیڑے ایک ہی شکل رکھتے ہیں۔ فرض کریں کہ ریپر مقامی ہینڈل کو کسی دوسرے مالک کو منتقل کرتا ہے، لیکن فائنلائزر کو منسلک چھوڑ دیتا ہے۔ ٹرانسمیشن کے وقت ضروری طور پر کچھ بھی ناکام نہیں ہوتا ہے۔ فائنلائزر کے چلنے سے پہلے عام ٹیسٹ مکمل ہو سکتے ہیں۔

تاہم، GC کے دباؤ کے تحت، پرانا ریپر بالآخر ہینڈل کو چھوڑ سکتا ہے جبکہ نیا مالک اب بھی ہینڈل کے زندہ رہنے کی توقع رکھتا ہے۔ پھر اگلی ڈیفالٹ رسائی استعمال کے بعد مفت ہوسکتی ہے۔

فنکشنل ٹیسٹنگ غلط نہیں ہے۔ وہ صرف ایک مختلف سوال کا جواب دے رہے تھے۔ انہوں نے آپریشن کے نتائج کی توثیق کی، لیکن ملکیت کی غلطیوں کو بے نقاب کرنے کے لیے درکار آبجیکٹ لائف ٹائم یا GC ٹائمنگ نہیں چلائی۔

جراثیم کش ادویات کو ابھی بھی کام کے بوجھ کی کوریج کی ضرورت ہے۔

سینیٹائزر صرف ان خلاف ورزیوں کی اطلاع دے سکتے ہیں جو عمل درآمد کے دوران دیکھی گئی ہوں۔

ASan پرانے اشارے نہیں پکڑ سکتا جن کا کوئی بھی حوالہ نہیں دیتا۔ TSan تنازعہ کی اطلاع نہیں دے سکتا اگر متضاد رسائی کبھی اوورلیپ نہ ہو۔ LSan ان راستوں میں رساو کو ظاہر نہیں کر سکتا جن میں کام کا بوجھ کبھی داخل نہیں ہوتا ہے۔ اگر برانچ پر کوئی ان پٹ نہیں آتا ہے جو رائٹ کو چھوڑ رہی ہے، تو MSan ابتدائی بگ کو ظاہر نہیں کر سکتا۔

یہ وہ جگہ ہے جہاں دھندلا پن، تناؤ کی جانچ، ناکامی کا انجکشن، اور کنکرنسی پروبس اہم ہو جاتے ہیں۔ یہ جراثیم کش ادویات کا متبادل نہیں ہے۔ اس سے دلچسپ پھانسیوں کے امکانات بڑھ جاتے ہیں۔

کوریج گائیڈڈ فزنگ غیر معمولی ان پٹ راستوں کو تلاش کرتی ہے۔ زندگی کے چکر کا تناؤ کسی چیز کو تخلیق کرنے، برقرار رکھنے، منتقل کرنے، ناکام کرنے، بند کرنے، حتمی شکل دینے اور ختم کرنے کا دہرایا جانے والا عمل ہے۔ ناکامی انجیکشن کلین اپ اور رول بیک کوڈ پر مجبور کرتا ہے جو خوش راہ ٹیسٹ شاذ و نادر ہی آتے ہیں۔ کنکرنسی پروبس تکلیف دہ دھاگے کے نظام الاوقات بناتی ہیں جو کہ قابل مشاہدہ ہونے کے لیے کثرت سے واقع ہوتی ہیں۔ کارپس ری پلے پہلے دریافت شدہ غلطیوں کو خاموشی سے واپس آنے سے روکتا ہے۔

سینیٹائزر کا کام نتیجے میں آنے والی غلط حالت کو جھنڈا لگانا اور مثالی طور پر اس کی تاریخ کو کافی حد تک بیان کرنا ہے تاکہ اسے ڈیبگ کیا جا سکے۔

یہی وجہ ہے کہ سیکڑوں ہزاروں مختصر تخلیق/استعمال/قریبی سائیکل ہمیں زندگی بھر کی درستگی کے بارے میں ایک بینچ مارک سے زیادہ بتا سکتے ہیں جو ایک طویل عرصے تک رہنے والی چیز کے ذریعے گیگا بائٹس پر کارروائی کرتا ہے۔ بینچ مارک اپنا زیادہ تر وقت مستحکم حالت میں گزارتے ہیں۔ لائف سائیکل ورک بوجھ ٹرانزیشن سے گزرتے ہوئے وقت گزارتا ہے جہاں ملکیت کی غلطیاں سامنے آتی ہیں۔

متحرک تجزیہ ہمہ گیر نہیں ہے۔

صاف جراثیم کش ادویات کا استعمال مفید ثبوت ہے۔ یہ اس بات کا ثبوت نہیں ہے کہ آپ کا کوڈ محفوظ ہے۔

یہ ہمیں بتاتا ہے کہ اس تعمیر اور اس کام کے بوجھ کے لیے، پروگرام کے وہ حصے جو سینیٹائزر کو نظر آ رہے ہیں، کسی معاہدے کی خلاف ورزی نہیں کی ہے جس کی جانچ کرنا ٹول جانتا ہے۔

دائرہ کار اس سے کم ہو سکتا ہے جو پہلے نظر آتا ہے۔

ہو سکتا ہے کہ کچھ ماڈیولز آلات نہ بنائے جائیں۔ حسب ضرورت مختص کرنے والے دلچسپی کی منطقی آبجیکٹ حدود کو چھپا سکتے ہیں۔ کوڈ کے اندر ہم آہنگی ہوسکتی ہے جس کا TSan مشاہدہ نہیں کرسکتا ہے۔ علامتیں غائب ہو سکتی ہیں یا آپٹیمائزیشن اسٹیک کو دوبارہ بنانا مشکل بنا سکتی ہے۔ رن ٹائم میموری کو ان طریقوں سے منظم کر سکتا ہے جو سینیٹائزر کے ماڈل پر واضح طور پر نقشہ نہ بنائیں۔ دباؤ جان بوجھ کر کچھ نتائج کو دیکھنے سے ہٹا دیتا ہے۔

اور بگ کے چھوٹ جانے کے لیے ان مسائل میں سے کسی کا بھی موجود ہونا ضروری نہیں ہے۔ مکمل طور پر انسٹرومینٹڈ بائنری آپ کو ان راستوں کے بارے میں کچھ نہیں بتاتی ہے جو آپ کے کام کا بوجھ کبھی انجام نہیں دیتا ہے۔

لہذا، صاف دوڑ کے بعد، پوچھنے کے لیے مفید سوالات شامل ہیں:

کیا اب ہم محفوظ ہیں؟

کہ:

اس دوڑ نے اصل میں کیا مشاہدہ کیا، اور اس کے نقطہ نظر کے میدان سے باہر کیا رہ گیا؟

یہ اعتماد کی ایک مناسب سطح ہے جسے متحرک تجزیہ پر لاگو کیا جا سکتا ہے۔ گرین سینیٹائزر لین باقی پروگرام کے لیے ایک سرٹیفکیٹ نہیں ہے، بلکہ مشاہدہ پر عمل درآمد کا مضبوط رن ٹائم ثبوت ہے۔

سینیٹائزر ایک قابل نفاذ عنوان کے معاہدے کے طور پر۔

سینیٹائزر کا عمومی تعارف بگ کلاسز کی فہرست ہے۔ ASan استعمال کے بعد مفت اور حد سے باہر رسائی کی تلاش کرتا ہے، LSan لیک کی تلاش کرتا ہے، MSan غیر شروع شدہ میموری کے استعمال کو تلاش کرتا ہے، اور TSan ڈیٹا کی دوڑ کو تلاش کرتا ہے۔

اگرچہ یہ وضاحت درست ہے، لیکن اصل رپورٹ کو دیکھتے وقت یہ خاص طور پر مددگار نہیں ہے۔

ایک بہتر نمونہ یہ پوچھنا ہوگا کہ پروگرام نے کیا مفروضے بنائے ہیں کہ جراثیم کش دوا کو غلط ثابت کر سکتا ہے۔ بہت زیادہ ملکیت والے کوڈ میں، اس کا مطلب اکثر یہ پوچھنا ہوتا ہے کہ وسائل کو کس کو استعمال کرنے کی اجازت ہے، اسے عوامی بنانے کا ذمہ دار کون ہے، اور کیا وہ جوابات راستے میں بدل گئے ہیں۔

MSan اور TSan کے لیے، ایک ہی خیال ملکیت سے آگے ابتدا اور ہم آہنگی تک پھیلا ہوا ہے۔ اس کے درست ہونے کے لیے کیا سچ ہونا چاہیے، اور کیا مشاہدہ شدہ پھانسی نے حقیقت میں اس کو قائم کیا؟

ASan کے معاہدے کی تفصیلات درج ذیل ہیں: پتہ کی اہلیت اور زندگی بھر. پروگرام اس طرح برتاؤ کرتا ہے جیسے میموری کا علاقہ اب بھی قابل رسائی ہے۔ ASan کافی رن ٹائم حالت کو برقرار رکھتا ہے تاکہ یہ بتا سکے کہ آیا یہ سچ ہے۔ اگر کسی زون کو جاری کیا جاتا ہے، قرنطینہ کیا جاتا ہے، یا ایک نازک زون کے طور پر زہر دیا جاتا ہے، تو رسائی اس کی زندگی بھر کے رن ٹائم منظر کی خلاف ورزی کرتی ہے۔

Lsan ملکیت کے دوسرے سرے کو دیکھتا ہے۔ یہ پوچھنے کے بجائے کہ آیا کسی چیز تک اس کی زندگی بھر ختم ہونے کے بعد اس تک رسائی حاصل کی گئی ہے، یہ پوچھتا ہے کہ اس کی مختص زندگی کا وقت کیوں ختم ہو گیا ہے۔ کسی عمل کو ختم کرتے وقت، یہ معلوم جڑوں سے قابل رسائی مختص کو ٹریک کرتا ہے۔ میموری جو قابل رسائی ملکیت کے راستے کے بغیر مختص رہتی ہے اسے لیک ہونے کی اطلاع دی جاتی ہے۔ تو میں Lsan کے بارے میں اس طرح سوچتا ہوں: ٹرمینل ملکیت اکاؤنٹنگ نہ صرف ایک "رساو جراثیم کش”

MSan دوسرے معاہدوں کو ٹریک کرتا ہے۔ ماخذ کو دوبارہ ترتیب دیں۔. ایڈریس ایبل میموری کا مطلب ضروری نہیں کہ درست ڈیٹا ہو۔ غیر شروع شدہ بائٹس خاموش برانچ کنڈیشنز، پوائنٹرز، سائزز، پیرامیٹرز، یا ریٹرن ویلیوز نہیں ہونے چاہئیں۔ MSan عمل درآمد کے ذریعے اس ریاست کا پرچار کرتا ہے اور رپورٹ کرتا ہے جب پروگرام آخر میں غیر شروع شدہ حالت کو معنی خیز سمجھتا ہے۔

تسان کے ساتھ معاملہ کرتا ہے۔ مطابقت پذیری کی نمائش. دونوں تھریڈز ایک ہی حالت تک رسائی حاصل کر سکتے ہیں، لیکن اگر یہ تنازعات تک رسائی حاصل کرتے ہیں، تو ایک ترتیب دینے والا رشتہ ہونا چاہیے جو اسے قانونی بناتا ہے۔ TSan قابل مشاہدہ مطابقت پذیری کی تشکیل نو کرتا ہے اور رسائی کی اطلاع دیتا ہے جو غیر ترتیب شدہ رہتے ہیں۔ یہ فرق اہم ہے۔ ایک پروگرام مطابقت پذیری فراہم کرنے کے لیے حسب ضرورت رن ٹائم، کال بیک پروٹوکول، یا بیرونی لائبریری پر بھروسہ کر سکتا ہے، لیکن تسان کو ایسا کوئی فائدہ نظر نہیں آتا ہے۔

یہ ماڈل خاص طور پر مقامی APIs کے ارد گرد بنائے گئے ہیں کیونکہ مقامی کوڈ ملکیت کے فیصلوں کو براہ راست ظاہر کرتا ہے۔

بورنگ ایس ایس ایل ایک مفید مثال ہے، حالانکہ پیٹرن صرف خفیہ کاری تک محدود نہیں ہے۔ API کے قوانین درج ذیل آپریشنز کے درمیان فرق کرتے ہیں: get0, get1, set0اور set1 اس کی وجہ یہ ہے کہ ایک ہی پوائنٹر کی قسم کو واپس کرنے یا قبول کرنے سے ملکیت کے لیے ایک جیسے مضمرات نہیں ہوتے۔

کوئی راستہ نہیں get0-میں نے انداز کا نتیجہ ادھار لیا۔ کوئی راستہ نہیں get1طرز کے نتیجے میں ملکیتی حوالہ جات شامل ہیں۔ کوئی راستہ نہیں set0-طریقہ کام ملکیت منتقل کرتا ہے جبکہ set1 کال کرنے والے کے موجودہ حوالہ کو منتقل کیے بغیر اسے برقرار رکھتا ہے۔ حوالہ شماری اشیاء درج ذیل کارروائیوں کو بے نقاب کرتی ہیں: *_up_refمختص کردہ اشیاء میں اسی ریلیز کا فنکشن ہوتا ہے۔

نام کچھ حقیقی درستگی کا کام کر رہا ہے۔ اگر ریپر ان تمام معاملات کو "کچھ مقامی پوائنٹر” پر چپٹا کرتا ہے، تو یہ ان معلومات کو رد کر دیتا ہے جسے API جان بوجھ کر محفوظ کرنے کی کوشش کر رہا تھا۔

اس طرح ریپر ادھار ہینڈل کو جاری کرتا ہے۔ یا، ملکیت کی منتقلی کے بعد بھی ہینڈل کا استعمال جاری رکھیں۔ یا ریفرنس کو خفیہ رکھیں۔ پوائنٹر کی قدر خود تبدیل نہیں ہوئی ہے۔ جو چیز تبدیل ہوئی وہ پروگرام کے استعمال یا تباہ کرنے کا حق تھا جس کی طرف اشارہ کیا گیا تھا۔

فائنل کرنے والے اسی مسئلے کو کم واضح کرتے ہیں۔ ایک فائنلائزر عام طور پر منسلک ہوتا ہے جب کہ ریپر بنیادی وسائل کا مالک ہوتا ہے۔ اگر ملکیت کو بعد میں کسی دوسرے آبجیکٹ میں منتقل کر دیا جاتا ہے لیکن فائنلائزر منسلک رہتا ہے، تو دونوں آبجیکٹ میں اب ایک ہی وسیلہ کی صفائی کا راستہ ہو سکتا ہے۔ کوئی فوری ناکامی نہیں ہے۔ حتمی نتیجہ اس بات پر منحصر ہے کہ صفائی کا راستہ پہلے کیا جاتا ہے۔ یعنی، ایک ایسی زندگی جو دوہری ریلیز، باسی رسائی، یا غلطیوں کی وجہ سے ارادے سے زیادہ لمبی رہتی ہے۔

MSan دیگر حدود میں اسی قسم کی تضادات کو ظاہر کرتا ہے۔ فرض کریں کہ فنکشن کامیابی کی اطلاع دیتا ہے اور کال کرنے والا کامیابی کی تشریح اس طرح کرتا ہے کہ "تمام آؤٹ پٹس شروع کر دیے گئے ہیں۔” اگر ایک کامیاب برانچ بیرونی پیرامیٹرز کو اکیلا چھوڑ دیتی ہے، تو کال کرنے والا اور کالی مختلف معاہدوں کے تحت کام کریں گے، بغیر ضروری طور پر مشکوک میموری تک رسائی کے۔

جب ہم وقت سازی تجریدی حدود کو عبور کرتی ہے تو TSan رپورٹس ایک جیسی ہوتی ہیں۔ آپ کا کوڈ صرف اس صورت میں درست ہو سکتا ہے جب کچھ تالے، ایٹم آپریشنز، کال بیک پروٹوکول، یا رن ٹائم ایونٹس آرڈرنگ قائم کریں۔ اگر وہ ترتیب موجود نہیں ہے (یا کسی ایسی جگہ پر موجود ہے جسے آلات کے ذریعے انجام دینے والے نہیں دیکھ سکتے ہیں)، رپورٹ آپ کو بتاتی ہے کہ مطابقت پذیری کی کہانی رن ٹائم کے نقطہ نظر سے نامکمل ہے۔

لہذا، جراثیم کش رپورٹیں اکثر زیادہ مفید ہوتی ہیں جب مقامی گمراہی کے بجائے اجزاء کے درمیان تضادات کے طور پر پڑھی جاتی ہیں۔ پروگرام کا ایک حصہ کہتا ہے کہ آبجیکٹ زندہ ہے، اور دوسرا حصہ پہلے ہی اس چیز کو آزاد کر چکا ہے۔ ایک فریق کہتا ہے کہ نتیجہ شروع ہو چکا ہے لیکن دوسری طرف کا کہنا ہے کہ کوئی نتیجہ نہیں لکھا گیا۔ ایک تھریڈ نے فرض کیا ہے کہ دوسرے تھریڈ نے اپنی حالت کو محفوظ طریقے سے پوسٹ کر دیا ہے، لیکن مشاہدہ کردہ ہم آہنگی کا گراف ظاہر کرتا ہے کہ ایسا نہیں ہوا ہے۔

بہت سارے FFI والے کوڈ کے لیے، ملکیت وہ جگہ ہے جہاں یہ تضادات سب سے تیزی سے جمع ہو جاتے ہیں۔

مندرجہ ذیل ملکیت کے بہاؤ کا خاکہ FFI- ہیوی سسٹمز کے لیے ایک مفید ذہنی ماڈل ہے۔

FFI- ہیوی سسٹم کے لیے اونرشپ فلو ڈایاگرام جس میں دکھایا گیا ہے کہ کس طرح مقامی ہینڈلز مختص کرنے والوں، منظم ریپرز، فائنلائزرز، اسکوپس، ایریناز، اور مقامی لائبریریوں کے درمیان منتقل ہوتے ہیں، اور غلطیوں کے نتیجے میں ڈبل فریز، لیک، یا مفت کے بعد فائنلائزر کے استعمال کی خرابیاں کیسے پیدا ہو سکتی ہیں۔

خاکہ دکھاتا ہے کہ کیوں FFI ملکیت کو ریاست میں واضح تبدیلی کی ضرورت ہے۔ ہینڈلز کو غلط طریقے سے ادھار لینے، منتقل کرنے، حتمی شکل دینے یا اسکوپ کرنے کا نتیجہ لیک، ڈبل فریز، یا باسی فائنلائزرز کی صفائی کا سبب بن سکتا ہے۔

یہی پیٹرن بورنگ ایس ایس ایل سے آگے ظاہر ہوتا ہے۔ مقامی APIs معمول کے مطابق منفرد ملکیتی اشیاء، حوالہ شمار شدہ اشیاء، مستعار خیالات، منتقل شدہ ہینڈلز، میدان کی ملکیت والی میموری، اور عارضی وسائل کے درمیان فرق کرتے ہیں جنہیں راستے میں آپریشن ناکام ہونے کی صورت میں آزاد کرنا ضروری ہے۔

اصطلاحات مختلف ہیں، لیکن سوال یہ ہے کہ:

اس وقت وسائل کا مالک کون ہے؟ کیا یہ حوالہ مستعار یا محفوظ شدہ ہے؟ کن آپریشنوں سے ان کی زندگی ختم ہو جاتی ہے؟ کیا ملکیت صرف کامیاب ہونے پر ہی بدلتی ہے؟ اگر صفائی میں تاخیر ہوتی ہے تو اس کے ہوتے ہوئے تاخیر کا ذمہ دار کون ہے؟

یہ فرق جراثیم کشی کی پیداوار کا اندازہ لگانا آسان بناتے ہیں۔ اگر ملکیت کی منتقلی واضح ہے تو، ASan کے بعد کے استعمال کو ایک مخصوص منتقلی کا پتہ لگایا جا سکتا ہے جس نے پرانے مالک کو پیچھے چھوڑ دیا۔ Lsan رپورٹس ان حوالوں سے منسلک ہو سکتی ہیں جو مماثل ریلیز تک نہیں پہنچی ہیں۔ اگر منتقلی مضمر ہے، تو سینیٹائزر اب بھی کیڑے تلاش کر سکتا ہے، لیکن رپورٹ کو ملکیتی ماڈلز کے لیے ریورس انجینئرڈ ہونا چاہیے جن کا کوڈ میں واضح طور پر اظہار نہیں کیا گیا ہے۔

یہاں تک کہ اگر MSan اور TSan کے درمیان معاہدہ تنگ معنوں میں ملکیت کا معاہدہ نہیں ہے تو بھی وہی اصول لاگو ہوتے ہیں۔ APIs کو ابتدائی پوسٹ کی شرائط کو واضح کرنا چاہیے۔ کنکرنسی کوڈ کو واضح طور پر مطابقت پذیری کے تعلقات بنانا چاہیے۔ یہ اصول غیر تحریری مفروضوں پر جتنا کم انحصار کریں گے، یہ سمجھنا اتنا ہی آسان ہو گا کہ جراثیم کش ادویات دراصل کس چیز کو غلط ثابت کرتی ہیں۔

اس کا مطلب ہے کہ یہ ٹولز معاہدوں کو قابل عمل بنانے میں کارآمد ہیں۔ وہ پروگراموں کی ملکیت، ابتدا، یا ہم آہنگی کے لیے اصول وضع نہیں کرتے ہیں۔ وہ قوانین پہلے سے موجود ہیں۔ سینیٹائزر ان میں سے کچھ کو رن ٹائم سٹیٹ فراہم کرتا ہے، عملدرآمد کا مشاہدہ کرتا ہے، اور آپ کو بتاتا ہے کہ پروگرام کب برتاؤ کرتا ہے جیسے کہ اصول درست تھے، یہاں تک کہ جب شواہد دوسری صورت میں تجویز کرتے ہوں۔

چار جراثیم کش ادویات کا گہرائی سے تجزیہ

چار بڑے سینیٹائزرز کا نحو اس سے کم مختلف ہے جتنا آپ ان کے نفاذ سے بتا سکتے ہیں۔

سامان رن ٹائم سوال عام لاگت اہم حدود
آسن کیا زندگی کے اس موڑ پر اس میموری تک رسائی حاصل کرنا قانونی تھا؟ تقریباً 2x سست روی اور میموری اوور ہیڈ ناقابل مشاہدہ رسائی یا منطقی آبجیکٹ کی حدود کی اطلاع نہیں دی جا سکتی۔
ماؤنٹ ایل اس عمل کے اختتام پر بلاجواز مختص کیا ہیں؟ دوڑتے وقت کم۔ زیادہ تر کام بے ترکیبی کے دوران ہوتا ہے۔ قدامت پسند رسائی مطلوبہ ملکیت کی طرح نہیں ہے۔
MS۔ کیا غیر شروع شدہ ریاست نے پھانسی کو متاثر کیا؟ تقریباً 3 گنا سست۔ مزید اصل سے باخبر رہنے کا اضافہ کیا جائے گا۔ وسیع پیمانے پر سازوسامان انحصاری گراف درکار ہیں۔
تسان کیا متضاد رسائی رن ٹائم پر نظر آنے والی مطابقت پذیری کے مطابق ترتیب دی گئی ہے؟ نمایاں میموری اوور ہیڈ کی وجہ سے تقریباً 5-15x سست روی پوشیدہ مطابقت پذیری اور غیر سازگار کوڈ نتائج کو پیچیدہ بناتا ہے۔
والگرینڈ میمچیک مکمل عمل بائنری انسٹرومینٹیشن کے ذریعے کس بری رسائی یا لیک رویے کا مشاہدہ کیا جا سکتا ہے؟ بہت سست مرکزی یا متبادل لین کے لیے بڑی مستقل میٹرکس کے مقابلے میں بہتر ہے۔

اخراجات صرف منصوبہ بندی کے تخمینی اعداد و شمار ہیں۔ کام کے بوجھ کی شکل، مختص کرنے والے کا رویہ، انحصار کا سائز، پلیٹ فارم، اور رن ٹائم فن تعمیر اس کو نمایاں طور پر تبدیل کر سکتا ہے۔

ایڈریس سینیٹائزر (آسن): ایڈریس ایبلٹی اور لائف ٹائم

ایڈریس سینیٹائزر اکثر میموری کی خرابی کو تلاش کرنے کے ایک تیز طریقہ کے طور پر متعارف کرایا جاتا ہے، لیکن اس کا ماڈل زیادہ مخصوص ہے۔ ASan ٹریک کرتا ہے کہ آیا کوئی پروگرام اس تک رسائی کے وقت میموری کے دیئے گئے علاقے کو ایڈریس کر سکتا ہے۔

کمپائلر انسٹرومینٹیشن کو لوڈ اور اسٹور کیا جاتا ہے تاکہ اسے رن ٹائم کے ذریعہ برقرار رکھے گئے شیڈو میٹا ڈیٹا کے خلاف چیک کیا جاسکے۔ ڈھیر کی چیز ایک زہریلے ریڈ زون سے گھری ہوئی ہے۔ آزاد میموری بھی آلودہ ہے، اور حال ہی میں آزاد کردہ مختص کو عام طور پر دوبارہ استعمال کرنے سے پہلے تنہائی میں رکھا جاتا ہے۔

اسٹیک انسٹرومینٹیشن اسی خیال کو مقامی زندگیوں پر لاگو کرتا ہے۔ ASan اس طرح اسکوپ کے بعد کے استعمال اور واپسی کے بعد کے استعمال کو پکڑ سکتا ہے اگر متعلقہ سپورٹ فعال ہو۔

یہی وجہ ہے کہ ASan قدرتی طور پر زندگی بھر کے کیڑوں کا نقشہ بناتا ہے۔ ایک ریپر تصادم سے بہت پہلے ملکیت کی غلطیاں کر سکتا ہے۔ غلطیاں صرف ASan میں ظاہر ہوتی ہیں جب وہ بالآخر میموری تک مخصوص رسائی میں بدل جاتی ہیں جنہیں رن ٹائم غلط یا حد سے باہر سمجھتا ہے۔

ASan جس کیڑے کو پکڑ سکتا ہے وہ وسیع ہے، جس میں ہیپ، اسٹیک، اور عالمی دائرہ سے باہر رسائی، استعمال کے بعد مفت، استعمال کے بعد دائرہ کار، استعمال کے بعد واپسی، ڈبل مفت، غلط مفت، اور معاون پلیٹ فارمز پر، سینیٹائزر کے رن ٹائم کے ذریعے لیک کا پتہ لگانا۔

ڈیبگنگ بلڈز کے لیے، کمپائلر فلیگ کو زیادہ سے زیادہ اصلاح پر مفید رپورٹس کی حمایت کرنی چاہیے۔ اصل معیار یہ ہیں:

clang++ -O1 -g -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=address -o my_tests sanitizer_tests.cc

ASAN_SYMBOLIZER_PATH="$(command -v llvm-symbolizer)"
ASAN_OPTIONS="detect_leaks=1:check_initialization_order=1" 
./my_tests

یہ تعمیر ڈیبگ انفارمیشن اور فریم پوائنٹرز کو محفوظ رکھتی ہے اور بہن بھائی کال آپٹیمائزیشن سے گریز کرتی ہے، اسٹیک سے مفید کال کرنے والوں کے غائب ہونے کے امکانات کو کم کرتی ہے۔ llvm-symbolizer رن ٹائم کال کے ذریعے دستیاب ہے، لیک کا پتہ لگانے اور پلیٹ فارم کے ذریعے تعاون یافتہ ابتدائی آرڈر کی جانچ پڑتال کرتا ہے۔

اس عین مطابق جھنڈے کی کوئی خاص قدر نہیں ہے جو آپ کے بلڈ سسٹم کے مطابق نہیں ہے۔ نقطہ بائنریز تیار کرنا ہے جو ناکامیوں کی وضاحت کرسکتے ہیں۔ سینیٹائزر لین جو رن ٹائم کا کچھ فیصد بچاتی ہیں لیکن ایک اسٹیک بناتی ہیں جسے کوئی بھی دوبارہ ترتیب نہیں دے سکتا، یہ ایک بری بات ہے۔

ASan بذریعہ ڈیفالٹ پہلی دریافت شدہ غلطی پر بھی رک جاتا ہے۔ تحقیقات کے دوران اس طرح کا رویہ محفوظ رکھنے کے قابل ہے۔

اگر کوئی پروگرام غلط میموری کی حالت میں داخل ہوتا ہے، اگر بعد میں غلطیاں ہوتی ہیں تو یہ کم قابل اعتماد ہو جاتا ہے۔ ایک باسی تحریر پڑوسی آبجیکٹ کو خراب کر سکتی ہے، جس کی وجہ سے برانچ تبدیل ہو سکتی ہے، جو کسی غیر متعلقہ جگہ تک دوسری غلط رسائی کا سبب بن سکتی ہے۔ جاری رکھنے کے نتیجے میں مزید رپورٹس مل سکتی ہیں، لیکن ضروری نہیں کہ زیادہ آزاد کیڑے ہوں۔

پہلی رپورٹ اکثر وہ بہترین ثبوت ہوتی ہے جو آپ حاصل کر سکتے ہیں کیونکہ مختص، لائف ٹائم ٹرانزیشن، اور غلط رسائی ابھی بھی اصل غلطی کے نسبتاً قریب ہے۔

آسن طاقتور ہے، لیکن اس کے نتائج کی اب بھی حدود ہیں۔ مکمل طور پر جامد لنکنگ عام طور پر تعاون یافتہ ماڈل نہیں ہے۔ 64 بٹ سسٹمز پر، ASan شیڈو میپنگ کے لیے ایک بڑی ورچوئل ایڈریس رینج محفوظ رکھتا ہے۔ جزوی سازوسامان کمزور کرتا ہے جسے آپ رن ٹائم پر دیکھ سکتے ہیں۔ کسٹم کنٹینرز اور مختص کرنے والے منطقی آبجیکٹ کی حدود کو چھپا سکتے ہیں۔ کمپیکٹ شیڈو اسکیم میں جزوی طور پر حد سے باہر غیر منسلک رسائی کے لیے ایک معروف ایج کیس بھی ہے۔

ان میں سے کوئی بھی حد آسن کو کمزور نہیں کرتی۔ یہ صرف اس بات کی وضاحت کرتا ہے کہ آسن چلانے کا کیا مطلب ہے۔ اس کا مطلب ہے کہ اس کام کے بوجھ کے ذریعے جاری کردہ رسائی انسٹرومینٹڈ رن ٹائم کے ذریعہ قابل مشاہدہ ایڈریس ایبلٹی حدود کو عبور نہیں کرتی ہے۔

آسن شیڈو میموری کیسے کام کرتی ہے۔

ASan ہر مختص کے لیے بھاری میٹا ڈیٹا آبجیکٹ کو برقرار رکھنے کے بجائے کمپیکٹ شیڈو نمائیندگی کا استعمال کر کے نمایاں رفتار حاصل کرتا ہے۔

ایک عام میپنگ میں، ایک شیڈو بائٹ ایپلی کیشن میموری کے 8 بائٹس کی نمائندگی کرتا ہے۔ 0 کی شیڈو ویلیو کا مطلب ہے کہ تمام آٹھ متعلقہ بائٹس قابل شناخت ہیں۔ قدریں 1 سے 7 تک جزوی طور پر قابل شناخت پونچھ کی نمائندگی کر سکتی ہیں، درست معروف بائٹس کی تعداد کو انکوڈنگ کرتے ہوئے۔ 0 کے علاوہ کسی بھی قدر کو ریڈ زونز، فریڈ میموری، یا غلط اسٹیک لائف ٹائم کے لیے زہر مارکر کے طور پر استعمال کیا جاتا ہے۔

فلو چارٹ ASan شیڈو میموری کی وضاحت کرتا ہے: ایپلیکیشن میموری کا ایک 8-بائٹ بلاک ایک شیڈو بائٹ پر نقش ہوتا ہے۔ یہاں، 0 کا مطلب ہے کہ تمام بائٹس قابل شناخت ہیں، اقدار 1 سے 7 کا مطلب ہے کہ بہت سے معروف بائٹس قابل شناخت ہیں، اور پوائزن مارکر ریڈ زون، فریڈ میموری، یا غلط اسٹیک لائف کی نشاندہی کرتے ہیں۔

خاکہ دکھاتا ہے کہ کس طرح ASan ایپلیکیشن میموری کو شیڈو میموری میں نقشہ بناتا ہے، جس سے آپ جلدی سے اس بات کا تعین کر سکتے ہیں کہ آیا کوئی لوڈ یا اسٹور درست، جزوی طور پر درست، یا گندی میموری سے ٹکراتا ہے۔

انسٹرومینٹڈ لوڈ یا اسٹور سے پہلے، کمپائلر کے ذریعے تیار کردہ کوڈ ایپلیکیشن کے پتے کو ان کے شیڈو بائٹس میں نقش کرتا ہے اور تصدیق کرتا ہے کہ درخواست کردہ رسائی درست ہے۔

ایک عام ہیپ ایلوکیشن کے لیے، ایلوکیٹر آبجیکٹ کے گرد ایک زہر آلود ریڈ زون رکھتا ہے۔ جب کسی چیز کو آزاد کیا جاتا ہے، تو اس کی یادداشت بھی زہر آلود ہو جاتی ہے اور اسے فوری طور پر دوبارہ استعمال کے لیے واپس نہیں کیا جاتا، بلکہ اسے عموماً کچھ عرصے کے لیے تنہائی میں رکھا جاتا ہے۔

یہ تاخیر اہم ہے۔ اس کے بغیر، باسی پوائنٹر تیزی سے ایک ہی پتے پر نئی، درست اشیاء کا حوالہ دینا شروع کر سکتے ہیں۔ کسی علاقے کو زہر آلود رکھنے سے پچھلے پوائنٹرز کو استعمال کے بعد مفت میں ناکام ہونے کے لیے مزید وقت ملتا ہے۔

اسٹیک انسٹرومینٹیشن مقامی متغیرات کے لیے وہی عمومی طریقہ کار استعمال کرتی ہے۔ دائرہ کار ختم ہونے پر علاقے داغدار ہو سکتے ہیں، اور فنکشن کے اسٹیک لائف ٹائم خلاف ورزیوں کو پکڑنے کے لیے واپس آنے کے بعد اضافی آلات داغدار حالت کو محفوظ رکھ سکتے ہیں جو اس بات پر منحصر ہے کہ آیا پچھلے فریموں کو دوبارہ استعمال کیا گیا ہے۔

شیڈو ماڈل ASan کی رفتار اور اس کے کچھ اندھے دھبوں دونوں کے لیے ذمہ دار ہے۔

ASan بہت مفید ہے جب کوئی غلط رسائی کمپائلر اور رن ٹائم کے ذریعہ معلوم حد کو عبور کرتی ہے۔ یہ کم مفید ہے اگر رسائی مکمل طور پر بغیر انسٹرومینٹڈ کوڈ کے اندر ہوتی ہے، اگر ان لائن اسمبلی کمپائلر کے ذریعے تیار کردہ چیک کو نظرانداز کرتی ہے، یا اگر مختص کرنے والا متعدد منطقی اشیاء کو ایک بڑے ایڈریس ایبل ایریا کے طور پر پیش کرتا ہے۔

اہم اختلافات بھی ہیں: منطقی ملکیت کی خرابی۔ اور خلاف ورزی کا ازالہ کرنا. ASan نہیں جانتا کہ API کا کہنا ہے کہ ایک پوائنٹر بھیجا گیا تھا۔ یادداشت بالآخر زہر آلود ہوگئی اور مجھے بعد میں معلوم ہوا کہ کسی نے اسے چھوا تھا۔ اگر ملکیت کا ماڈل غلط ہے لیکن عمل درآمد کے دوران کوئی غیر قانونی رسائی نہیں ہوتی ہے، تو ASan کے پاس رپورٹ کرنے کے لیے کچھ نہیں ہے۔

پہلی رپورٹ کو وجہ بیان کے طور پر پڑھیں۔

عام طور پر، ASan رپورٹس کو سمجھنا آسان ہوتا ہے اگر آپ اوپر والے فریم کو بگ نہیں سمجھتے ہیں۔

ہیپ کے بعد کے عام استعمال کے لیے، کم از کم تین پوائنٹس ہیں جو دوبارہ ترتیب دینے کے قابل ہیں:

  • غلط میموری تک آخری رسائی

  • اسائنمنٹ جو کسی چیز کو تخلیق کرتا ہے۔

  • زندگی کا اختتام ڈیل لوکیشن

رپورٹ پر منحصر ہے، آپ کو شیڈو میموری سیاق و سباق اور تھریڈ بنانے کی تاریخ بھی مل سکتی ہے۔

یہ ڈھیر ایک ہی چیز کے بارے میں مختلف عقائد کو بیان کرتے ہیں۔

ایلوکیشن اسٹیک آپ کو بتاتا ہے کہ اس کی زندگی کہاں سے شروع ہوئی۔ مفت اسٹیک آپ کو بتاتا ہے کہ پروگرام کے ایک حصے نے کہاں فیصلہ کیا ہے کہ اس کی زندگی ختم ہوگئی ہے۔ موجودہ رسائی آپ کو بتاتی ہے کہ آپ کے خیال میں کون اس چیز کو استعمال کرسکتا ہے۔

مثال کے طور پر:

allocate native object
    -> hand pointer to wrapper
    -> transfer ownership elsewhere
    -> old cleanup path still runs
    -> new owner dereferences pointer
    -> ASan reports use-after-free

تعبیر وہ جگہ ہے جہاں ASan کو مسئلہ ملتا ہے۔ ٹوٹی ہوئی منتقلی پہلے ہوئی تھی۔

عملی ترمیم میں، یہ فرق اہم ہے۔ شکار کی رسائی میں ایک کالعدم چیک شامل کرنا باسی ملکیت کی حالت کو برقرار رکھتے ہوئے ایک تصادم کو دبا سکتا ہے۔ بہتر مرمت عام طور پر اس مقام پر ہوتی ہے جہاں ایک مالک نے مالک ہونا بند کر دیا لیکن پروگرام اس تبدیلی کو دکھانے میں ناکام رہا۔

اپنی مرضی کے مطابق مختص کرنے والے اور انٹرسیپٹرز

ASan اس وقت بہترین کام کرتا ہے جب اس کی ایلوکیشن باؤنڈری ویو ان حدود سے میل کھاتا ہے جن کی ایپلی کیشن کو پرواہ ہے۔

یہ بہت سادہ اور عام سے مختلف ہے۔ malloc, free, newاور delete. یہ میدانوں، سلیبس، پولز، مقامی مختص کرنے والوں، جے آئی ٹی کے ڈھیروں، بیچ کنفیگریشنز، اور لائبریری کے مخصوص مختص کرنے والوں کے ساتھ زیادہ پیچیدہ ہو جاتا ہے۔

ایک پول پر غور کریں جہاں سسٹم 1MiB سپورٹ ایریا کی درخواست کرتا ہے اور پھر اسے سیکڑوں 64 بائٹ آبجیکٹ میں تقسیم کرتا ہے۔ سسٹم مختص کرنے والے کے نقطہ نظر سے، یہ ایک حقیقی وقت مختص ہوسکتا ہے۔ جب تک پول ASan کے ساتھ تعاون نہیں کرتا، ایک 64-بائٹ آبجیکٹ سے دوسرے پر اوور رائٹ مکمل طور پر ایڈریس ایبل بیکنگ میموری کے اندر رہ سکتا ہے۔

پروگرام نے ایک منطقی آبجیکٹ کی حد عبور کی۔ آسن کے پاس پکڑنے کے لیے متعلقہ زہر کی حد نہیں ہوسکتی ہے۔

سینیٹائزر سے آگاہ ایلوکیٹر عام طور پر اسے کئی طریقوں میں سے ایک طریقے سے ہینڈل کرتے ہیں: آپ ایک ٹیسٹنگ موڈ فراہم کر سکتے ہیں جو واضح طور پر غیر استعمال شدہ سلاٹس یا وائٹ اسپیس کو کرپٹ کرتا ہے، سینیٹائزر API کے ذریعے کنٹینر کی حدود کی تشریح کرتا ہے، یا ASan کو آزادانہ طور پر دیکھنے کے لیے سسٹم مختص کرنے والے کو انفرادی طور پر مختص کرتا ہے۔

کام کا بوجھ ڈیزائن بھی مدد کر سکتا ہے. جارحانہ سلاٹ کا دوبارہ استعمال اس امکان کو بڑھاتا ہے کہ باسی حوالہ جات زندگی بھر کی بدلی ہوئی حالت سے متصادم ہوں گے۔ تخلیق کاؤنٹر مختص کرنے والے کی سطح پر باسی ہینڈلز کو بے نقاب کر سکتے ہیں۔ بار بار ایلوکیشن/ڈی ایلوکیشن/ری ایلوکیشن سیکوینسز زندگی بھر کی جانچ کے لیے مستحکم ریاست کے کام کے بوجھ سے زیادہ مفید ہوتے ہیں جو ایک ہی اشیاء کو کئی منٹ تک متحرک رکھتے ہیں۔

اہم حصہ یہ ہے کہ مختص کرنے والے کی مرئیت خودکار نہیں ہے۔

مختص کرنے والا جان بوجھ کر درخواست سے آبجیکٹ کی حدود کو چھپاتا ہے۔ -fsanitize=address تعمیر کے اوپری حصے میں، آپ بعد میں اس حد کو دوبارہ ترتیب نہیں دے سکتے۔ مختص کرنے والے کو اسے ASan کے سامنے لانا چاہیے یا ایسی ترتیب کا استعمال کرنا چاہیے جو جانچ کے ماحول میں باؤنڈری کا مشاہدہ کرنے کی اجازت دیتی ہے۔

انٹرسیپٹرز مشترکہ لائبریری کی حدود میں ایک جیسا کردار ادا کرتے ہیں۔ یہ سینیٹائزر کے رن ٹائم کو یہ سمجھنے کی اجازت دیتا ہے کہ لائبریری کوڈ کے اندر کیا کارروائیاں ہو سکتی ہیں۔ تاہم، انٹرسیپٹرز مکمل آلات کی جگہ نہیں لے سکتے۔ یہ آسن کے افق کو وسعت دیتا ہے۔ مبہم کوڈ کو شفاف نہیں بناتا ہے۔

دبانا بحالی کی حکمت عملی نہیں ہے۔

بعض اوقات تحمل کی ضرورت ہوتی ہے۔

تیسری پارٹی کی لائبریریوں سے رپورٹیں تیار کی جا سکتی ہیں جنہیں باکس سے باہر نہیں کیا جا سکتا۔ پلیٹ فارم کے اجزاء میں پہلے سے ہی اپ اسٹریم فکسز ہو سکتے ہیں جو تعاون یافتہ ماحول تک نہیں پہنچے ہیں۔ ایسے معاملات ہو سکتے ہیں جہاں سینیٹائزر کا رن ٹائم اور انحصارات اتنے زیادہ تعامل کرتے ہیں کہ عارضی استثناء کے بغیر لین کا استعمال جاری نہیں رہ سکتا۔

ایسے حالات میں اپنے مخصوص مسئلے کو دبانے کی کوشش کریں نہ کہ اپنے اردگرد سے۔

وسیع پیمانے پر دبانا خطرناک ہے کیونکہ یہ سبز فنگسائڈ کے طریقوں کے اثرات کو تبدیل کرتا ہے۔ پوری لائبریریوں، نام کی جگہوں، یا کال پاتھز کو ملانا دبانے کی اصل وجہ کو بھول جانے کے مہینوں بعد نئے، غیر متعلقہ رجعت کو چھپا سکتا ہے۔

آپ کے مالک کوڈ کے لیے، دبانا غیر معمولی ہونا چاہیے۔ اگر کوئی رپورٹ حقیقی اور قابل عمل ہے، تو اسے چھپانا کیونکہ اس میں ترمیم کرنا تکلیف دہ ہے اس وجہ کو شکست دیتا ہے کہ آپ ASan چلا رہے ہیں۔

اگر ڈیٹرنس ضروری ہے تو یہ سمجھنے کے لیے کافی معلومات رکھیں کہ یہ کیوں موجود ہے۔ سب سے تنگ مستحکم مماثلت دستیاب ہے، بنیادی مسئلہ، کون سے اجزاء اسے حل کرتے ہیں، اور استثنیٰ کو کب دوبارہ دیکھا جائے گا۔

لین کو نئی غلطیوں کے لیے حساس رکھیں اور تمام مستثنیات کو تنگ، دستاویزی وقفوں میں ہینڈل کریں جو موجودہ تعمیر میں دیکھے جا سکتے ہیں۔

لیک سینیٹائزر (LSan): ٹرمینل ملکیت

لیکس کی ناکامی کی ایک مختلف شکل ہے استعمال کے بعد فری یا بفر اوور فلو سے۔ کسی بھی چیز سے اختلاف کرنے کی ضرورت نہیں ہے۔ ٹاسک صحیح نتیجہ واپس کر سکتا ہے، تمام ٹیسٹ پاس کر سکتا ہے، اور یہ عمل عام طور پر ختم ہو سکتا ہے اور اس کے بعد بھی مختص رقم باقی رہ گئی ہے۔

اس دوڑ کے ساتھ کہیں، ملکیت کبھی ختم نہیں ہوئی۔

LeakSanitizer زندگی کے چکر میں اس مقام کے ارد گرد بنایا گیا ہے۔ ASan پروگرام کے چلنے کے دوران رسائی کی نگرانی کرتا ہے۔ LSan زیادہ تر دلچسپ کام کرتا ہے جب کوئی عمل ختم ہو جاتا ہے، جب یہ معائنہ کر سکتا ہے کہ ہیپ ایلوکیشنز کیا ہیں اور وہ لائیو روٹ سے کیسے جڑے ہوئے ہیں۔

اس وجہ سے لیک کا پتہ لگانا خاص طور پر ایسے کوڈ کے لیے مفید ہے جو فوری نتائج پر اثر انداز نہیں ہوتا ہے اور صفائی کے غائب ہونے کا خدشہ رکھتا ہے (FFI ریپرز، جزوی ساخت کی ناکامیاں، سڑنے والے راستے، کیچز، حوالہ شمار شدہ اشیاء، نظام جو جزوی طور پر حتمی شکل پر انحصار کرتے ہیں)۔

بجنا LSan کو ASan کی تعمیر کے حصے کے طور پر یا آزادانہ طور پر چلا سکتا ہے: -fsanitize=leak. چونکہ زیادہ تر مہنگے آپریشن تمام باقاعدہ میموری تک رسائی کے بجائے لیک چیکنگ کے دوران ہوتے ہیں، اس لیے پروگرام باڈی کے لیے رن ٹائم اوور ہیڈ عام طور پر چھوٹا ہوتا ہے۔

ایک مفید ذہنی ماڈل ٹرمینل اونرشپ اکاؤنٹنگ ہے۔ تمام مختصات کو آزاد کیا جانا چاہیے یا عمل کے ختم ہونے تک قابل رسائی رہنے کی معقول وجہ ہونی چاہیے۔ Lsan دوسری قسم کو رن ٹائم حالت سے دوبارہ تشکیل دیتا ہے جس کا معائنہ کیا جا سکتا ہے۔

یہ فرق اہم ہے کیونکہ ملکیت کے بہت سے کیڑے غلط رسائی میں ترجمہ نہیں کرتے ہیں۔ ایک برقرار رکھا ہوا حوالہ ہمیشہ کے لیے زندہ رہ سکتا ہے۔ آپ غلطی کے راستے میں ایک کلین اپ کال بھول سکتے ہیں۔ گلوبلز یا کیچز نادانستہ طور پر آبجیکٹ گراف کو زندہ رکھ سکتے ہیں۔ ایپلیکیشن کام کرتی رہتی ہے، لیکن ملکیت کا راستہ کبھی بند نہیں ہوتا۔

اگر آپ کے پاس پہلے سے ہی کام کرنے والی ASan کنفیگریشن ہے تو، رساو کا پتہ لگانے کو فعال کرنا عام طور پر سب سے زیادہ عملی نقطہ آغاز ہوتا ہے۔ اسٹینڈ ایلون LSan دستیاب ہے اور جب مکمل ASan آلات مطلوبہ یا انٹیگریٹ کرنا مشکل نہ ہو تو مفید ہو سکتا ہے۔ تاہم، تاریخی طور پر اس کا ASan انضمام کے راستے سے کم تجربہ کیا گیا ہے۔

پہلے سے طے شدہ ASan سپورٹ لیک پاتھ مندرجہ ذیل ہے:

clang -O1 -g -fsanitize=address -fno-omit-frame-pointer 
  -o leak_suite leak_suite.c

ASAN_SYMBOLIZER_PATH="$(command -v llvm-symbolizer)" 
ASAN_OPTIONS="detect_leaks=1" 
LSAN_OPTIONS="exitcode=23:suppressions=lsan.supp" 
./leak_suite

اگر آپ صرف لیک کوریج چاہتے ہیں:

clang -O1 -g -fsanitize=leak -o leak_suite leak_suite.c
LSAN_OPTIONS="exitcode=23:suppressions=lsan.supp" ./leak_suite

واضح ایگزٹ کوڈز CI میں کارآمد ہیں کیونکہ وہ لیک رپورٹس کو عام آپریشن کی ناکامیوں میں بدل دیتے ہیں۔ دبانا معلوم بیرونی نتائج کو اس کوڈ کو ڈوبنے سے روکتا ہے جس کی آپ پیمائش کرنے کی کوشش کر رہے ہیں۔ تاہم، آپ کو وہی اخراجات اٹھانا ہوں گے جو اس ہینڈ بک میں کہیں اور بیان کیے گئے ہیں۔ کوئی بھی دباو کچھ حد تک مرئیت کو ہٹا دیتا ہے۔

جب نتائج کی واضح تشریح کی جاتی ہے تو رساو کے راستے زیادہ قیمتی ہو جاتے ہیں۔ اگر کوئی ٹیسٹ وسائل مختص کرتا ہے، اپنی زندگی کو استعمال کرتا ہے، اس کے پاس موجود ہر چیز کو جاری کرتا ہے، اور باہر نکل جاتا ہے، تو پھاڑ پھاڑ پر غیر متوقع طور پر مختص کرنا ملکیت کا کافی سیدھا اشارہ ہے۔ یہ عمل جتنا بڑا اور شور مچائے گا، اس کی تشریح میں اتنی ہی زیادہ احتیاط کی ضرورت ہے۔

رسائی ارادے کی طرح نہیں ہے۔

Lsan قدامت پسند ہے کیونکہ اسے ملکیت کے منصوبوں کا براہ راست علم نہیں ہے۔ باہر نکلنے پر، یہ روٹ جیسے علاقوں جیسے تھریڈ اسٹیک، رجسٹر، گلوبل اور تھریڈ لوکل اسٹوریج کی جانچ کرتا ہے، اور پھر ان اقدار کی پیروی کرتا ہے جو ہیپ ایلوکیشن میں پوائنٹر کی طرح نظر آتی ہیں۔ اگر اس گراف کے ذریعے کوئی مختص ابھی بھی قابل رسائی ہے، تو LSan مختص کو برقرار رکھ سکتا ہے چاہے ایپلیکیشن اسے منطقی طور پر ڈی ایلوکیٹ کرنے کی کوشش کرے۔

فلو چارٹ یہ دکھا رہا ہے کہ کس طرح Lsan اسٹیک، رجسٹرز، گلوبل، اور تھریڈ-لوکل اسٹوریج سے جڑیں اکٹھا کرکے، پوائنٹر جیسی اقدار کو ٹریک کرکے، اور براہ راست اور بالواسطہ ناقابل رسائی رساو سے قابل رسائی مختص کو الگ کرکے عمل سے باہر نکلنے پر لیکس کی جانچ کرتا ہے۔

خاکہ دکھاتا ہے کہ کس طرح LSan ختم ہونے پر قابل رسائی کو ٹریک کرتا ہے۔ ایک ناقابل رسائی مختص کے نتیجے میں ایک لیک رپورٹ ہو گی، لیکن قابل رسائی میموری اب بھی منطقی طور پر غلط ہو سکتی ہے اگر پروگرام اسے پہلے آزاد کرنے کی کوشش کرتا ہے۔

یہ لیک کا پتہ لگانے اور عام زندگی بھر کی ڈیبگنگ کے درمیان سب سے اہم فرق ہے۔

فرض کریں کہ کسی شے کو آزاد کرنے کے دوران آزاد کر دیا جانا چاہیے تھا، لیکن اس شے کا ایک باسی اشارہ عالمی ڈھانچے میں رہتا ہے۔ پروگرام کے نقطہ نظر سے، صفائی ٹوٹ گئی ہے. Lsan کے نقطہ نظر سے، مختص اب بھی قابل رسائی ہے۔

مخالف کیس کی تشخیص کرنا آسان ہے۔ اگر کسی مختص کے پاس روٹ تک واپس جانے کا راستہ نہیں ہے جسے LSan پہچانتا ہے، تو یہ اسے لیک ہونے کی اطلاع دے سکتا ہے اور اس ایلوکیشن اسٹیک کی نشاندہی کرسکتا ہے جس نے اسے بنایا ہے۔

براہ راست اور بالواسطہ لیکس ایک ساتھ پڑھنے کے قابل ہیں۔ ایک پیرنٹ آبجیکٹ کے لیے ریلیز غائب ہونا پورے گراف کو ناقابل رسائی بنا سکتا ہے۔ اس کے پیرنٹ میں ترمیم کرکے، بہت سے نیچے کی طرف لیک ہونے والے ریکارڈز کو ایک ساتھ ہٹایا جا سکتا ہے۔ ہر بالواسطہ مختص کو آزادانہ طور پر ٹریک کرنا وقت کا ضیاع ہے اگر وہ سب ایک ہی کھوئے ہوئے مالک میں شریک ہوں۔

رسائی جان بوجھ کر بھی ہو سکتی ہے۔ کچھ رن ٹائمز پروسیس لائف ٹائم کیشے کو برقرار رکھتے ہیں۔ ایک لائبریری ایک بار عالمی حالت کو شروع کر سکتی ہے اور اسے کبھی نہیں پھاڑ سکتی ہے کیونکہ عمل ختم ہونے سے صفحہ بہرحال دوبارہ حاصل ہو جائے گا۔ ٹیسٹ فریم ورک اور منظم رن ٹائمز شٹ ڈاؤن کے دوران مختص کو ظاہر کر سکتے ہیں جن کا زیر تفتیش اجزاء سے بہت کم تعلق ہے۔

یہی وجہ ہے کہ مکمل ایپلیکیشن لیک رپورٹس کی تشریح کرنا فوکسڈ رپورٹس سے زیادہ مشکل ہے۔

لائبریریوں یا FFI ریپرز کے لیے، ایک چھوٹا مددگار عمل بہت زیادہ فائدہ مند ہو سکتا ہے۔

initialize runtime
    -> create native resources
    -> exercise success and failure paths
    -> release explicit owners
    -> allow deferred cleanup where relevant
    -> exit

زندگی کا دور جتنا چھوٹا ہوگا، اس مفید سوال کا جواب دینا اتنا ہی آسان ہوگا: ‘اس مقام پر کون سی مختصات موجود رہیں؟’

فائنلائزر پر مبنی کوڈ یہاں خصوصی توجہ کا مستحق ہے۔ کسی منظم آبجیکٹ سے جڑنے میں ناکامی کا مطلب یہ نہیں ہے کہ جب عمل لیک کی جانچ شروع کرتا ہے تو آبجیکٹ کے بنیادی وسائل پہلے ہی مکمل ہو چکے ہیں۔ اگر آپ کے ٹیسٹ فائنل کلین اپ پر منحصر ہوتے ہیں، تو آپ کے استعمال کو رن ٹائم کے ٹرمینیشن رویے کو مدنظر رکھنا چاہیے بجائے اس کے کہ عمل کے خاتمے کا علاج ڈیٹرمنسٹک ڈسٹرکٹر کال کے ساتھ کیا جائے۔

یہی مسئلہ غیر مطابقت پذیر کلین اپ، ورکر تھریڈز اور بیک گراؤنڈ کیشے کے ساتھ ظاہر ہوتا ہے۔ لیک ٹیسٹ جو عام ٹیر ڈاون مکمل ہونے سے پہلے ختم ہو جاتے ہیں وہ میموری کی اطلاع دے سکتے ہیں کہ اصل ایپلیکیشن کچھ دیر بعد ریلیز ہوئی ہوگی۔

یہ LSan کو نظر انداز کرنے کی وجہ کے بجائے کام کے بوجھ کا مسئلہ ہے۔ ٹیسٹ کو درحقیقت اس ریاست تک پہنچنا چاہیے جس کے لیے اس کا مقصد ملکیت کی پیمائش کرنا ہے۔

آہستہ آہستہ رساو کا راستہ آن لائن لائیں۔

ایک قائم شدہ کوڈبیس میں لیک کا پتہ لگانے سے اکثر بدصورت پہلی رپورٹس تیار ہوتی ہیں۔

کچھ دریافتیں آپ کے اپنے کوڈ کی اصل لیک ہوں گی۔ دوسرے انحصار، رن ٹائم ایگزٹ رویے، لائف ٹائم کیچز پر کارروائی، ٹیسٹنگ ٹولز کے ذریعے نامکمل صفائی، یا مختص کرنے سے پیدا ہو سکتے ہیں جن تک رسائی کے لیے مزید تفتیش کی ضرورت ہوتی ہے۔

سب کو فوری طور پر مسدود کرنے کی کوشش کرنے سے عام طور پر دو میں سے ایک نتیجہ نکلے گا: اس کا مطلب ہے کہ ایک وسیع دبانے والا ڈھیر یا CI لین جسے ہر کوئی دوبارہ کرنا اور نظر انداز کرنا سیکھتا ہے۔

اپنی رپورٹس کو دوبارہ تیار کرنے کے قابل بنا کر شروع کریں۔

ملکیتی کوڈ کا براہ راست تعییناتی رساو عام طور پر سیدھا ہوتا ہے۔ اسے ٹھیک کریں اور تولید کو برقرار رکھیں۔ رن ٹائم یا انحصار کے نتائج کے لیے، یہ طے کریں کہ آیا وہ مستحکم ہیں، درحقیقت باہر نکلنے پر منسلک کیے جا سکتے ہیں، اور کیا ایک چھوٹا عمل انہیں جانچ کے تحت کوڈ سے الگ کر سکتا ہے۔

صرف ایسے کیسز کو دبائیں جہاں کافی شواہد موجود ہوں اور میچوں کو محدود کریں۔

اپنی ناکامی کی پالیسی کو سخت کریں کیونکہ آپ کی بنیادی لائن واضح ہو جاتی ہے۔ گہری جانچ میں، نئے براہ راست لیک کو تیزی سے روکا جا سکتا ہے۔ ایک منظم رن ٹائم یا بڑے میزبان عمل کے نتائج کو ایک ہی پروسیسنگ حاصل کرنے سے پہلے مزید خصوصیات کی ضرورت پڑ سکتی ہے۔

یہی وجہ ہے کہ یہ لیک ہو رہا ہے۔ شدت اور لیک نتیجہ یہ ایک الگ فیصلہ رہنا چاہیے۔ عمل کے آغاز کے دوران ایک بار لیک ہونے والی 4 بائٹ مختص کا معمولی آپریشنل اثر ہو سکتا ہے، لیکن یہ پھر بھی آپ کو بتاتا ہے کہ ملکیت کا ایک راستہ صحیح طریقے سے ختم نہیں ہوا ہے۔ ریلیز کو مسدود کرنا یا نہیں اس کا انحصار پالیسی پر ہے۔ ملکیت کا حساب کتاب غلط ہے یا نہیں یہ الگ بات ہے۔

مفید رساو کا راستہ بالآخر اس مقام پر پہنچ جاتا ہے جہاں نئی ​​رپورٹ حیران کن ہے۔ جب ایسا ہوتا ہے، LSan وقفہ وقفہ سے صفائی کے آپریشنز کرنا بند کر دیتا ہے اور ملکیتی راستوں کے لیے ریگریشن ڈیٹیکٹر بن جاتا ہے جن کی پہلے کوئی قابل عمل جانچ نہیں ہوتی تھی۔

Memory Sanitizer (MSan): ابتداء کا ذریعہ

ASan میموری کا استعمال کرتے ہوئے کوڈ کیپچر کرتا ہے جسے اب چھوا نہیں جا سکتا۔ MSan ایک اور غلطی پکڑتا ہے: یعنی، میموری بالکل قابل توجہ ہے، لیکن آپ جو قدر پڑھ رہے ہیں وہ قانونی طور پر سیٹ نہیں ہے۔

یہ فرق اہم ہے کیونکہ غیر شروع شدہ ڈیٹا کو فوری طور پر کریش ہونے کی ضرورت نہیں ہے۔ یہ لمبائی، جھنڈا، پوائنٹر آفسیٹ، برانچ کنڈیشن، یا آؤٹ پٹ کسی اور پرت پر واپس آ سکتا ہے۔ ایک پروگرام کسی آپریشن تک پہنچنے سے پہلے اس قدر کے ارد گرد گزر سکتا ہے جسے MSan قابل مشاہدہ سمجھتا ہے۔

یہ MSan کو خاص طور پر API کی حدود میں تضادات تلاش کرنے کے لیے مفید بناتا ہے۔

کال کرنے والا کامیاب واپسی دیکھتا ہے اور فرض کرتا ہے کہ API کی طرف سے وعدہ کیا گیا کوئی بھی آؤٹ پٹ استعمال کرنے کے لیے تیار ہے۔ کالی کی ایک شاخ ہے جو اپنی کوئی بھی آؤٹ پٹ لکھے بغیر کامیابی لوٹاتی ہے۔ کوڈ کے دونوں ٹکڑے الگ الگ دیکھے جانے پر معقول معلوم ہو سکتے ہیں۔ مسئلہ صرف اس وقت ظاہر ہوتا ہے جب کال کرنے والا ایسی حالت استعمال کرتا ہے جس کے لیے اس نے درست ابتدائی ریکارڈ حاصل نہیں کیا ہو۔

موزیلا کا NSS شمارہ 1767590 ایک مفید مثال ہے۔ آؤٹ پٹ پوائنٹر کو ایک کامیاب کال کے بعد ابتدائی طور پر سمجھا جاتا تھا، حالانکہ کالی کے ذریعے ایک راستہ اسے لکھے بغیر کامیابی واپس کرسکتا ہے۔ MSan نے بالآخر غیر شروع شدہ اقدار کی اطلاع دی، لیکن زیادہ دلچسپ خامی API معاہدہ تھا۔ "کامیابی” کا مفہوم داعی کے لیے نفاذ سے زیادہ مضبوط تھا۔

یہ ایک بار بار چلنے والا MSan پیٹرن ہے۔ رپورٹیں استعمال کی سائٹ پر ظاہر ہوتی ہیں، لیکن کیڑے اکثر پہلے شروع ہو جاتے ہیں جب کچھ راستے کال کرنے والے کی توقع کے مطابق حالت قائم کرنے میں ناکام ہو جاتے ہیں۔

ڈیفالٹ MSan تعمیر ہے:

clang++ -O1 -g -fno-omit-frame-pointer 
  -fsanitize=memory -fsanitize-memory-track-origins=2 
  -o msan_suite msan_suite.cc

MSAN_SYMBOLIZER_PATH="$(command -v llvm-symbolizer)" 
./msan_suite

-fsanitize=memory آلہ سازی کو چالو کریں۔ -fsanitize-memory-track-origins=2 MSan سے اس بارے میں اضافی معلومات کو برقرار رکھنے کے لیے کہیں کہ نشہ کہاں سے آیا اور یہ میموری کے ذریعے کیسے منتقل ہوا۔

اصل کا سراغ لگانا مہنگا ہے۔ سادہ MSan پہلے سے ہی اہم رن ٹائم اور میموری اوور ہیڈ کا شکار ہے، اور سورس ٹریکنگ اور بھی اوور ہیڈ کا اضافہ کرتی ہے۔ لیکن مشکل کیڑوں کے لیے، زیادہ معلومات حاصل کرنے کے لیے اکثر ادائیگی کرنا قابل قدر ہے۔

ماخذ کی معلومات کے بغیر، رپورٹ آپ کو بتا سکتی ہے کہ غیر شروع شدہ لمبائی ڈیکوڈر کے اندر ایک نقطہ تک پہنچ گئی ہے۔ اصل کو فعال کرنے سے آپ ان اقدار کو متعدد اسٹورز کے ذریعے کال کرنے والے کی طرف سے مختص کردہ آؤٹ پٹ ڈھانچے میں ٹریس کرنے کی اجازت دیتا ہے، اور پھر اس بات کو یقینی بناتا ہے کہ بحالی کے ایک راستے نے کسی ممبر کو شروع نہیں کیا ہے۔

یہ جاننے میں فرق ہے کہ بری حالت کہاں ظاہر ہوتی ہے اور یہ جاننا کہ یہ کہاں عمل میں آتی ہے۔

MSan خاص طور پر پارسرز، کوڈیکس، بائنری فارمیٹس، کرپٹوگرافک میسج ہینڈلنگ، سیریلائزیشن، IPC، ڈیٹا بیس پیجز، اور APIs کے ساتھ آؤٹ پٹ پیرامیٹرز کے ساتھ اچھی طرح کام کرتا ہے۔ یہ نظام معمول کے مطابق اشیاء کو بتدریج تخلیق کرتے ہیں اور جزوی طور پر آبادی والی ریاستوں کو متعدد تہوں میں منتقل کرتے ہیں۔ اس سے پہلے کہ باقاعدہ جانچ میں کوئی عجیب چیز نظر آنا شروع ہو جائے، ابتدا کی غلطیاں حیران کن فاصلے کو برداشت کر سکتی ہیں۔

MSan واقعی کیا تبلیغ کرتا ہے۔

غیر شروع شدہ میموری کو "رینڈم بائٹس” کہنا ایک مفید شارٹ ہینڈ ہے، لیکن اس میں وہ طریقہ کار یاد نہیں آتا جو MSan کو دلچسپ بناتا ہے۔

MSan ایک شیڈو حالت کو برقرار رکھتا ہے جو شروع ہونے والی قدر کے بٹس کو بیان کرتا ہے۔ کاپی اس ریاست کا پرچار کرتی ہے۔ ریاضی اور دیگر عمل اس کو نتیجہ تک پہنچاتے ہیں۔ جیسے جیسے اقدار پروگرام کے ذریعے منتقل ہوتی ہیں، ابتدائی ریکارڈ ان کے ساتھ چلتا ہے۔

فلو چارٹ دکھا رہا ہے کہ کس طرح MSan کاپی یا ریاضی کے ذریعے غیر شروع شدہ حالت کو ٹریک کرتا ہے، یا تو غیر شروع شدہ مختص کے طور پر یا اسٹیک سلاٹ میں داغدار سائے کی حالتوں کے طور پر، جب تک کہ حساس استعمال جیسے برانچز، پوائنٹرز/انڈیکس، پیرامیٹرز، یا ریٹرن ویلیوز MSan رپورٹ کو متحرک نہ کریں۔

خاکہ دکھاتا ہے کہ کس طرح MSan کسی پروگرام کے ذریعے غیر شروع شدہ حالت کی پیروی کرتا ہے اور صرف اس وقت رپورٹ کرتا ہے جب اقدار کو اس طرح استعمال کیا جاتا ہے جس سے عملدرآمد کو متاثر ہوتا ہے۔

اس طرح، نشہ کی حالت ان میں سے کسی کی اطلاع ہونے سے پہلے بہت سے بظاہر بے ضرر کاموں سے بچ سکتی ہے۔

مثال کے طور پر:

stack object allocated
    -> one field left unwritten
    -> structure copied
    -> field copied into a size variable
    -> size used in a conditional
    -> MSan reports uninitialized use

ایک شاخ وہ ہوتی ہے جہاں ایک ایسی ریاست جو محض غلط ہو وہ معنوی طور پر اہم ہو جاتی ہے۔ اگر آپ صرف اس برانچ میں ترمیم کرتے ہیں، تو آپ پچھلے راستے سے محروم ہوجائیں گے جس نے جزوی طور پر ابتدائی آبجیکٹ بنایا تھا۔

اسی طرح فنکشن کی حدود پر لاگو ہوتا ہے۔ اگر کوئی قدر کال کرنے والے کو واپس کر دی جاتی ہے یا کوڈ کو پاس کر دیا جاتا ہے جس کے لیے ابتداء کی ضرورت ہوتی ہے، MSan منتقلی کی اطلاع دے سکتا ہے حالانکہ بنیادی میموری ایڈریس ہمیشہ درست ہوتا ہے۔

یہی وجہ ہے کہ MSan رپورٹس ASan رپورٹس سے بہت مختلف محسوس ہوتی ہیں۔ ASan کے ساتھ، آپ عام طور پر کسی پتے کی زندگی بھر کی تشکیل نو کرتے ہیں۔ MSan آپ کو اقدار کی تاریخ کو دوبارہ تشکیل دینے کی اجازت دیتا ہے۔

اوریجن ٹریکنگ اس ریکارڈ میں ایک اور پرت کا اضافہ کرتی ہے۔ اعلی ٹریس لیول پر، MSan اس بارے میں معلومات کو برقرار رکھ سکتا ہے کہ آلودہ میموری کہاں سے پیدا ہوئی اور اسے بعد میں کہاں ذخیرہ کیا گیا۔ یہ شور مچانے والا اور مہنگا ہو سکتا ہے، لیکن یہ بہت مفید ہے جب قابل مشاہدہ استعمال تجرید کی کئی پرتیں غائب ابتداء سے دور ہو۔

MSan کو انحصار گراف کے ذریعے مرئیت کی ضرورت ہے۔

اگر پھانسی کے اہم حصوں کو استعمال میں نہیں لایا جاتا ہے، تو MSan پر بھروسہ کرنا زیادہ مشکل ہو جاتا ہے۔

ہم کہتے ہیں کہ ایک غیر سازگار لائبریری بفر کو لکھتی ہے۔ ایپلیکیشن کے نقطہ نظر سے، بائٹ بالکل درست ہو سکتا ہے، لیکن MSan نے اس تحریر کا مشاہدہ نہیں کیا جس نے اسے شروع کیا۔ جب انسٹرومینٹڈ کوڈ بعد میں بفر کو استعمال کرتا ہے، تو شیڈو اسٹیٹ پھر بھی کہہ سکتی ہے کہ بائٹ کرپٹ ہے۔

مخالف مسئلہ بھی موجود ہے۔ آلودہ ڈیٹا کو بغیر آلات کے کوڈ میں منتقل کیا جا سکتا ہے اور MSan کو اس کا مقصد جانے بغیر وہاں استعمال کیا جا سکتا ہے۔

انٹرسیپٹرز لائبریری کی مشترکہ حدود میں مدد کرتے ہیں لیکن صوابدیدی مبہم کوڈ کو ظاہر نہیں کرتے ہیں۔ اگر ابتدائی حالت ان انحصارات کو پاس کرتی ہے جسے MSan سمجھ نہیں پاتا، تو نتیجے میں آنے والی رپورٹ ناقابل اعتبار ہو گی۔

اعلیٰ معیار کی MSan کوریج کے لیے عام طور پر ایپلی کیشنز اور لائبریریوں کی تعمیر نو کی ضرورت ہوتی ہے جن کے ذریعے نازک حالت کے بہاؤ ہم آہنگ آلات کے ساتھ گزرتے ہیں۔ آپ کے ماحول پر منحصر ہے، یہ C/C++ رن ٹائم اور دیگر نچلی سطح کے انحصار تک بڑھ سکتا ہے۔

یہی وجہ ہے کہ MSan ایک عام سینیٹائزر میٹرکس میں صرف ایک اور چیک باکس کے بجائے اپنا تعمیراتی ماحول بن جاتا ہے۔

زیادہ تر ماخذ پر مبنی انحصار والے پروجیکٹس اپنے ماحول کو بہت مکمل بنا سکتے ہیں۔ ایسے پروجیکٹس جو پہلے سے تعمیر شدہ مقامی لائبریریوں، ان لائن اسمبلیوں، ملکیتی رن ٹائمز، یا ناقابل تعمیر نظام کے اجزاء پر بہت زیادہ انحصار کرتے ہیں ان کے لیے صاف نتائج حاصل کرنے میں سخت دقت ہوتی ہے۔

وہ آپریٹنگ اخراجات حقیقی ہیں۔ MSan کے ذریعہ پائے جانے والے بگ کلاسوں کے لئے بھی یہی ہے۔ کوڈ کے لیے جو حملہ آور کے زیر کنٹرول ان پٹ کو پارس کرتا ہے یا جزوی طور پر تعمیر شدہ آؤٹ پٹ پر بہت زیادہ انحصار کرتا ہے، لین سرمایہ کاری کے قابل ہو سکتی ہیں چاہے ان میں سسٹم کے صرف احتیاط سے منتخب کردہ حصے ہوں۔

واضح طور پر کامیابی کے بعد کی شرائط کی وضاحت کریں۔

MSan کو APIs تلاش کرنے کی عادت ہے جن کی واپسی کی قدریں عمل درآمد کی اصل ضمانت سے زیادہ بتاتی ہیں۔

خصوصیات پر غور کریں جیسے:

bool decode(const uint8_t* input, size_t input_len,
            uint8_t* output, size_t* output_len);

کال کرنے والا فطری طور پر پوسٹ کنڈیشن کے طور پر سچ پڑھتا ہے۔ آؤٹ پٹ میں درست نتائج ہوں گے اور *output_len آپ کو بتائے گا کہ ان میں سے کتنے درست ہیں۔

اگر کچھ کامیاب شاخیں آؤٹ پٹ لکھتی ہیں، لیکن آپ *output_len کو اکیلا چھوڑ دیتے ہیں، تو آپ کے نفاذ نے ایک ایسی حالت پیدا کردی ہے جس میں API بات چیت نہیں کر رہا ہے۔

ڈھانچے کے ساتھ بھی یہی مسئلہ ظاہر ہوتا ہے۔

result.status = OK
result.data   = initialized
result.length = never written

کچھ نہیں status == OK کال کرنے والے کو خبردار کرتا ہے کہ فیلڈ کا معائنہ کرنا محفوظ نہیں ہے۔

کچھ ڈیزائن اس ابہام سے بچتے ہیں۔ کنٹرول فلو برانچز سے پہلے آؤٹ پٹ کو ایک درست ڈیفالٹ ویلیو پر شروع کیا جا سکتا ہے۔ ایک فنکشن ایک سے زیادہ آزاد پوائنٹرز کے ذریعے اسے بنانے کے بجائے مکمل طور پر تشکیل شدہ نتیجہ آبجیکٹ کو واپس کر سکتا ہے۔ APIs جو حقیقت میں مکمل، جزوی اور ناکام نتائج کو سپورٹ کرتے ہیں وہ کسی ایک کامیابی کوڈ کو اوور لوڈ کرنے کے بجائے واضح طور پر اس حالت کی نشاندہی کر سکتے ہیں۔ جزوی مواد والے بفرز اختیاری طور پر لکھے ہوئے سائیڈ چینلز پر انحصار کیے بغیر نتیجہ کے حصے کے طور پر ایک درست لمبائی واپس کر سکتے ہیں۔

کون سا ڈیزائن مناسب ہے اس کا انحصار آپ کے API پر ہے۔ ایک اہم خاصیت یہ ہے کہ کال کرنے والے کو معلوم ہونا چاہیے کہ انٹرفیس اور واپسی کی حالت کے ذریعے کون سی اقدار دستیاب ہیں۔

اگر MSan گمشدہ ابتداء کا پتہ لگاتا ہے، تو یہ اضافہ کرتا ہے: memset(..., 0, ...) بعض صورتوں میں یہ درست حل ہو سکتا ہے۔ دوسرے معاملات میں، آپ کو صرف اتنا کرنا ہے کہ API معاہدے کو مبہم رکھتے ہوئے غیر متعینہ حالت کو قابل فہم ڈیفالٹ ویلیو سے تبدیل کرنا ہے۔

مزید مفید سوالات کے جوابات دینے کے لیے یہ رپورٹ کافی لمبی کھودنے کے قابل ہے۔ کون سا راستہ کال کرنے والے کو یہ یقین کرنے کی اجازت دیتا ہے کہ یہ قدر تیار ہے جب یہ نہیں ہے؟

Thread Sanitizer (TSan): مطابقت پذیری کی نمائش

ThreadSanitizer عملدرآمد کے کچھ حصوں کا مشاہدہ کرتا ہے کہ باقاعدہ ٹیسٹ توثیق کرنے میں خاص طور پر خراب ہیں: مختلف تھریڈز کے ذریعے رسائی کے درمیان ترتیب۔

چونکہ شیڈیولر مسلسل بے نائین انٹرلیونگ کا انتخاب کرتا ہے، اس لیے ایک پروگرام حقیقی دنیا کے ڈیٹا مقابلے میں ہزاروں بار کامیابی سے چل سکتا ہے۔ چونکہ تسان آلات میموری تک رسائی اور مطابقت پذیری کی کارروائیوں کو فراہم کرتا ہے، اس لیے یہ متضاد رسائی کی شناخت کرنے کے لیے کافی حد تک عملدرآمد کو دوبارہ تشکیل دے سکتا ہے جو کہ درست ترتیب کے تعلق کے بغیر ہوتی ہیں۔

یہ مرئیت ایک اہم قیمت پر آتی ہے۔ TSan عام طور پر پروگراموں کو تقریباً 5 سے 15 گنا سست کر دیتا ہے اور باقاعدہ میموری کی مقدار سے کئی گنا زیادہ استعمال کر سکتا ہے۔ اس کے لیے وسیع کمپائلر انسٹرومینٹیشن کی بھی ضرورت ہے۔ بلڈ مشین اضافی تبدیلیاں کر سکتی ہے، جیسے کہ رن ٹائم کے وقت ضرورت کے مطابق پوزیشن سے آزاد ایگزیکیوٹیبل تیار کرنا۔

ان حدود کی وجہ سے، TSan عام طور پر باقاعدہ ٹیسٹ بائنریز میں قدرتی اضافہ ہونے کی بجائے اپنی ساخت میں موجود ہے۔

جنرل سیٹ اپ آسان ہے۔

clang++ -O1 -g -fsanitize=thread 
-o tsan_suite tsan_suite.cc

TSAN_OPTIONS="halt_on_error=1:history_size=7" 
./tsan_suite

کمپائلر جھنڈے ریسوں کا پتہ لگانے کے لیے آپ کے پروگرام کا آلہ بناتا ہے۔ Halt_on_error=1 پہلی اطلاع دی گئی ریس کو چلانے میں ناکام ہو جائے گا، جبکہ ایک بڑی تاریخ رپورٹ میں سابقہ ​​رسائی کے بارے میں مزید سیاق و سباق فراہم کر سکتی ہے۔

دوسرے سینیٹائزرز کی طرح، کارآمد علامتیں آلات کی تعمیر سے زیادہ سے زیادہ کارکردگی حاصل کرنے سے زیادہ اہم ہیں۔ TSan رپورٹس میں اکثر دو اسٹیک، ایک سے زیادہ تھریڈز، اور ان کے ارد گرد مطابقت پذیری کے واقعات شامل ہوتے ہیں۔ ضرورت سے زیادہ جارحانہ تعمیر کی وجہ سے کالر یا تھریڈ اسپوننگ اسٹیک کو کھو دینا پہلے سے ہی مشکل ریس کو دوبارہ تعمیر کرنا زیادہ مشکل بنا سکتا ہے۔

ایک بڑا آپریشنل مسئلہ باقی عمل میں مرئیت ہے۔

مشترکہ میموری تک رسائی کو محفوظ بنانے کے لیے TSan کو مطابقت پذیری کا مشاہدہ کرنا چاہیے۔ یہ اس وقت اچھی طرح سے کام کرتا ہے جب لاکنگ، ایٹمیسیٹی، کنڈیشن ویری ایبلز، تھریڈ تخلیق، اور دیگر مطابقت پذیری پرائمیٹوز کوڈ سے گزرتے ہیں جسے رن ٹائم سمجھتا ہے۔ اگر آرڈرنگ کا کوئی حصہ پہلے سے تعمیر شدہ لائبریری، کسٹم شیڈیولر کوڈ، اسمبلی، مقامی کال بیک، یا بغیر آلات کے رن ٹائم مشین کے اندر ہوتا ہے تو قابل اعتمادی کم ہو جاتی ہے۔

کوئی بھی رپورٹ جو ان حدود میں سے کسی ایک کے قریب آتی ہے اسے سیاق و سباق کی ضرورت ہوتی ہے اس سے پہلے کہ کوئی اسے غلط مثبت کا لیبل لگا سکے۔

موزیلا کا بگزیلا شمارہ 1688716 ایک مفید مثال ہے۔ رپورٹ میں گرافیکل کوڈ شامل تھا جہاں متعلقہ عمل درآمد کا کچھ حصہ بغیر آلات کے کوڈ سے گزرا تھا۔ بحث کو اس امکان پر غور کرنا تھا کہ سنکرونائزیشن تسان کے نقطہ نظر سے باہر موجود ہے۔

یہ آپ کے اپنے مکمل انسٹرومینٹڈ کوڈ میں دو غیر مطابقت پذیر رسائی سے بہت مختلف صورتحال ہے۔

دوسری طرف کا اندھا دھبہ بھی اہم ہے۔ اگر متضاد رسائی بذات خود غیر سازوسامان والے کوڈ کے اندر ہوتی ہے، تو TSan تنازعہ کو بالکل نہیں دیکھے گا۔ لہذا، جزوی آلات کا استعمال حدوں پر مبہم رپورٹس اور مبہم ماڈیولز کے اندر حقیقی غلط منفی پیدا کر سکتا ہے۔

سنجیدہ TSan لین کے لیے، یہ جاننا اچھا ہے کہ پہلی رپورٹ آنے سے پہلے اس عمل کے کن حصوں کو تیار کیا جا رہا ہے۔

TSan کام کے بوجھ میں ASan کے مقابلے میں خاص طور پر جانچ کے تحت اثاثوں کے لیے ڈیزائن کیے گئے اہم فوائد بھی پیش کرتا ہے۔ موجودہ یونٹوں کا ایک خاندان ایک ہی تھریڈ شیڈول کو مستقل طور پر تیار کرتے ہوئے صحیح فنکشن کو انجام دے سکتا ہے۔ ریس کا پتہ لگانے کے لیے تکرار، جھگڑا اور اوورلیپ کی ضرورت ہوتی ہے۔

یہ اس جگہ پر اثر انداز ہوتا ہے جہاں لین گرتی ہے۔ مختصر TSan اسموک ٹیسٹ اب بھی پل کی درخواستوں کے لیے کارآمد ثابت ہو سکتے ہیں، لیکن مہنگے، ہم وقتی کام کا بوجھ اکثر طے شدہ رنز، دوبارہ ہدف بنانے، یا پری لانچ ٹیسٹنگ کے لیے زیادہ موزوں ہوتے ہیں۔ بعد میں ہینڈ بک میں CI سیکشن ان تجارتی معاہدوں کی مزید تفصیل سے وضاحت کرتا ہے۔

ہوتا ہے-پہلے ایک ذہنی ماڈل ہے جو کام کرتا ہے۔

TSan کو صرف "دو دھاگوں نے ایک ہی متغیر کو چھوا” نہیں پایا۔

ہم میموری تک رسائی اور مطابقت پذیری کے واقعات کو ریکارڈ کرتے ہیں اور پھر پوچھتے ہیں کہ آیا متضاد رسائی کو ان کے پہلے ہونے والے تعلقات کے مطابق ترتیب دیا گیا ہے۔ اگر دو تھریڈز ایک ہی میموری تک رسائی حاصل کرتے ہیں، تو کم از کم ایک رسائی لکھتی ہے، اور کوئی قابل مشاہدہ مطابقت پذیری اس عمل کا حکم نہیں دیتی ہے، TSan ڈیٹا ریس کی ایک شکل رکھتا ہے۔

ترتیب کا خاکہ مصنف اور قاری کے دھاگوں کے درمیان ہم آہنگی دکھا رہا ہے۔ ایک ریلیز/انلاک/سگنل کے بعد حاصل/لاک/انتظار بغیر کسی ڈیٹا کی دوڑ کے آرڈرڈ رسائی پیدا کرتا ہے، جب کہ قابل مشاہدہ آؤٹ آف آرڈر لکھنا اور پڑھنا آؤٹ آف آرڈر رسائی کے تنازعات ہیں جن کی TSan رپورٹ کر سکتا ہے۔

خاکہ دکھاتا ہے کہ کس طرح مطابقت پذیری ترتیب دیتا ہے جسے TSan کو چیک کرنا چاہیے۔ قابل مشاہدہ ترتیب کے بغیر، TSan رپورٹس تھریڈز کے درمیان رسائی کے تنازعات کا باعث بن سکتی ہیں۔

ایک mutex ایک ترتیب بناتا ہے جسے TSan سمجھتا ہے۔ ایک دھاگے کو کھول کر اور پھر دوسرے دھاگے کو مقفل کر کے، آپ اپنی ضرورت کے کنارے کو قائم کر سکتے ہیں۔ درست حاصل/ریلیز ایٹم بھی ایسا ہی کر سکتا ہے۔ دھاگے کی تخلیق اور جوڑ، حالت کے متغیرات، اور دیگر تسلیم شدہ مطابقت پذیری پرائمیٹوز بھی پیشگی گراف میں حصہ ڈالتے ہیں۔

مثال کے طور پر، ایک سادہ پوسٹنگ پیٹرن پر غور کریں:

writer:
    initialize object
    -> release/store ready flag

reader:
    acquire/load ready flag
    -> read object

اگر free/acquire جوڑوں کو درست طریقے سے لاگو کیا جاتا ہے اور TSan کو نظر آتا ہے، تو یہ ممکن ہے کہ تحریروں کو سیدھ میں لایا جائے جو کہ قاری کے استعمال کرنے سے پہلے کسی چیز کو شروع کرے۔

اگر آپ اس پروٹوکول کو ایک سادہ غیر مطابقت پذیر بولین سے تبدیل کرتے ہیں، تو آپ کا پروگرام اب بھی کچھ مخصوص سسٹمز پر کام کرتا دکھائی دے سکتا ہے۔ TSan کے پاس اب ترتیب دینے والے کناروں سے منسلک رسائی نہیں ہے۔

اپنی مرضی کے مطابق مطابقت پذیری کے ساتھ ایک ہی مسئلہ ظاہر ہوتا ہے. اسمبل شدہ سیلف لاکنگ ڈیوائسز ہارڈ ویئر کی سطح پر مکمل طور پر درست اور جراثیم کش ادویات کے لیے پوشیدہ ہوسکتی ہیں۔ TSan کے نقطہ نظر سے، دونوں اطراف کی رسائی غیر ترتیب سے ظاہر ہوسکتی ہے کیونکہ ان کو جوڑنے والے واقعات ماڈل میں داخل نہیں ہوئے ہیں۔

اسی لیے TSan رپورٹس میں دو ڈیبگنگ ڈائریکشنز ہوتی ہیں: بعض اوقات ہم آہنگی اصل میں غائب ہوتی ہے۔ بعض اوقات ہم آہنگی موجود ہوتی ہے لیکن TSan اس کا مشاہدہ نہیں کرسکتا۔ اگرچہ رپورٹ خود متضاد رسائی فراہم کرتی ہے، لیکن آلات کی حدود کو سمجھنے سے آپ کو یہ جاننے میں مدد مل سکتی ہے کہ آپ کس چیز سے نمٹ رہے ہیں۔

ہمیں ‘مثبت ریس’ کے بارے میں شکوک و شبہات کا شکار ہونا چاہیے۔

"معمولی نسل” ایک خطرناک جملہ ہے کیونکہ یہ عام طور پر متعین مطابقت پذیری کے قواعد کے بجائے مشاہدہ شدہ رویے کو بیان کرتا ہے۔

فیلڈ بے ضرر لگ سکتا ہے کیونکہ اب تک دکھائی گئی تمام اقدار قابل قبول ہیں۔ کچھ مسائل ابھی باقی ہیں۔

C اور C++ میں، حقیقی دنیا کے ڈیٹا کی دوڑیں عام طور پر آپ کے پروگرام کو رویے کے غیر متعینہ علاقے میں رکھتی ہیں۔ مرتب کرنے والے ترجمے وقت کے مفروضوں تک محدود نہیں ہیں جو کوڈ کو جانچ کے دوران محفوظ ظاہر کرتے ہیں۔

مسابقتی شعبے بھی بڑے انویریئنٹس میں حصہ لے سکتے ہیں۔ ہم آہنگی سے باہر کے جھنڈے بے ضرر لگ سکتے ہیں، لیکن اس کے مطابق دیگر فیلڈز میں تبدیلی کی توقع ہے۔ دوسری اپ ڈیٹس کے بغیر ایک اپ ڈیٹ کو دیکھنے سے یہ ظاہر ہو سکتا ہے کہ پروگرامر کا ارادہ نہیں تھا۔

دیکھ بھال دلیل کو مزید کمزور کرتی ہے۔ وہ اقدار جو واقعی اہم نہیں تھیں جب ریس متعارف کروائی گئی تھی وہ بعد میں زندگی بھر کے فیصلے، کال بیک پروٹوکول، یا سیکیورٹی چیک کا حصہ بن سکتی ہیں، لیکن پہلے کی غیر مطابقت پذیر رسائی برقرار ہے۔

بعض اوقات TSan رپورٹس انسٹرومینٹیشن گیپس یا سنکرونائزیشن سے آتی ہیں جو رن ٹائم پر نظر نہیں آتیں۔ یہ وہ لوگ ہیں جو سرحد پر جانچ کے مستحق ہیں۔

اگر دونوں متضاد رسائییں آپ کے اپنے انسٹرومینٹیشن کوڈ میں ہیں، اور ان کو پورا کرنے کے لیے کوئی ترتیب دینے کا طریقہ کار نہیں ہے، تو "اچھے” کے لیے "میں نے اسے پہلے کبھی ٹوٹتے نہیں دیکھا” سے زیادہ مضبوط بیان کی ضرورت ہے۔

اکثر حتمی وصولی آسان ہے. مناسب میموری ترتیب کے ساتھ ایٹمکس کا استعمال کریں، موجودہ mutex کے پیچھے حالت رکھیں، یا آبجیکٹ کو دوبارہ ڈیزائن کریں تاکہ متضاد رسائی اب ساتھ ساتھ نہ ہو۔

زیادہ مشکل حصہ اس بات کی نشاندہی کرنا ہے کہ کوڈ کے غائب ہونے کی حقیقت کو سامنے لانے سے پہلے کوڈ کا انحصار کس ترتیب پر تھا۔

ریس شیڈولنگ کو آسان بنانا

TSan صرف ان ریسوں کی اطلاع دیتا ہے جو مشاہدہ شدہ رنز کے دوران ہوئی تھیں۔

اگر کام کا بوجھ کوئی متعلقہ ڈپلیکیشن نہیں بناتا تو کنکرنٹ کوڈ کی ایک ملین لائنیں صاف طور پر گزر سکتی ہیں۔ اس کے برعکس، فوکسڈ ٹیسٹنگ جو بار بار ایک لائف سائیکل باؤنڈری کو ٹکراتی ہے، سیکنڈوں کے معاملے میں تنازعہ کو بے نقاب کر سکتی ہے۔

ایک مفید ہم آہنگی کی تحقیقات جان بوجھ کر دلچسپی کے شیڈول کے امکان کو بڑھاتی ہے۔

اگر آپ کو محفوظ رہنے کی ضرورت ہے جب دو کام تقریباً ایک ہی وقت میں شروع ہوں تو ایک بیریئر پر تھریڈ شروع کریں۔ اگر کال بیک کی تکمیل اور آبجیکٹ کی تباہی کے درمیان کوئی دوڑ ہو سکتی ہے تو ہم اس تبدیلی کو ہزاروں بار دہراتے ہیں۔ اگر آپ کی رجسٹری ہم آہنگی تلاش کرنے اور صاف کرنے کی حمایت کرتی ہے، تو آپ متعدد کارکنوں کے لیے دونوں کاموں کو برباد کر دیں گے۔

صرف ٹیسٹ کی پیداوار تنگ حدود میں مفید ہو سکتی ہے۔

thread A:
    read state
    -> yield
    -> update shared object

thread B:
    close object
    -> release shared state

پیداوار کیڑے پیدا نہیں کرتے ہیں۔ یہ پہلے سے ہی ایک قانونی شیڈیولر فراہم کرتا ہے جس میں زیادہ جگہ کی مداخلت ہوتی ہے۔

اسی طرح کی تکنیک کال بیکس کو رجسٹر کرنے اور منسوخ کرنے، سائیکل کو منسلک/ڈیٹچ کرنے، آپریشن مکمل ہونے کے دوران ختم کرنے، اور واضح صفائی اور پس منظر کی رہائی کے درمیان دوڑ پر لاگو ہوتی ہے۔

رینڈمائزیشن ایک بڑے شیڈول کی جگہ کو تلاش کرنے میں مدد کر سکتی ہے، لیکن یہ عمل کے بیج اور ترتیب کو ریکارڈ کرتی ہے۔ TSan رپورٹس جو راتوں رات ایک بار آتی ہیں اور مقامی طور پر دوبارہ پیش نہیں کی جا سکتیں ان رپورٹس کے مقابلے میں زیادہ مہنگی ہوتی ہیں جو کام کے بوجھ کو دوبارہ پیش کر سکتی ہیں۔

کام کا بوجھ اس طرز عمل کے ساتھ وفادار ہونا چاہیے جو ایک حقیقی نظام پیدا کر سکتا ہے۔ مصنوعی جھگڑے کارآمد ہیں، لیکن ناممکن چیز زندگی بھر نہیں ہیں۔ جانچ کو ایپلی کیشنز کے لیے موجودہ ریسوں کو شیڈول کرنے میں آسانی پیدا کرنی چاہیے، بجائے اس کے کہ ہم آہنگی کے ایسے ماڈل ایجاد کیے جائیں جنہیں وہ کبھی استعمال نہیں کریں گے۔

لہذا ایک اچھا TSan کام کا بوجھ اپنا وقت منتقلی پر صرف کرتا ہے: شائع اور استعمال، رجسٹر اور غیر رجسٹر، شروع اور بند، بند اور مکمل، برقرار رکھنا اور جاری کرنا، وغیرہ۔ یہ وہ جگہ ہے جہاں دو تھریڈز اس بات پر متفق نہیں ہوتے ہیں کہ اس وقت کس ریاست کو چھونے کے لیے محفوظ ہے۔

جراثیم کش مرکبات کے بارے میں جانیں اور ان میں کیا شامل نہیں ہے۔

کوئی مفید "ہر چیز کو فعال کریں” سینیٹائزر کی تعمیر نہیں ہے۔

ٹولز مختلف رن ٹائم میٹا ڈیٹا کو برقرار رکھتے ہیں، مختلف آلات کے تقاضے عائد کرتے ہیں، اور اکثر بہت مختلف کام کے بوجھ کی ضرورت ہوتی ہے۔ کچھ مجموعے قدرتی طور پر ایک ہی بائنری میں فٹ ہوتے ہیں۔ دوسروں کو ان کے اپنے انحصار گراف اور CI بجٹ کے ساتھ الگ الگ تعمیرات کے طور پر سنبھالا جانا چاہئے۔

ان حدود کو سمجھنا ضروری ہے کیونکہ بڑے پیمانے پر جراثیم کش میٹرکس اب بھی کمزور ثبوت فراہم کر سکتے ہیں اگر امتزاج کا انتخاب ناقص ہے یا عمل کے اہم حصے مبہم ہیں۔

ایک ایسا امتزاج جو ایک ساتھ اچھی طرح چلتا ہے۔

ASan اور Un DefinedBehaviorSanitizer عام طور پر ایک ساتھ فعال ہوتے ہیں۔ یہ چیک عملدرآمد کے مختلف حصوں کا احاطہ کرتے ہیں اور بہت سی کلینگ بلڈز میں اچھی طرح سے ایک ساتھ رہتے ہیں۔

clang++ -O1 -g -fno-omit-frame-pointer 
  -fsanitize=address,undefined 
  -fno-sanitize-recover=all 
  app.cc -o app_sanitized

ASan ایڈریس ایبلٹی اور زندگی بھر کو مدنظر رکھتا ہے۔ UBSan زبان کی سطح پر غیر متعینہ رویے کو پکڑتا ہے، بشمول غلط حرکتیں، غلط طریقے سے رسائی، غلط شماری اقدار، اور فعال شدہ عدد اوور فلو چیکنگ۔

اگرچہ UBSan اس ہینڈ بک کا بنیادی موضوع نہیں ہے، لیکن اس کا تعلق اس بحث میں ہے کیونکہ اختتامی یادداشت کی خرابیاں ان جگہوں سے پیدا ہو سکتی ہیں جنہیں ASan ماڈل نہیں کرتا ہے۔

سائز کے غلط حسابات کے نتیجے میں کم سائز مختص ہو سکتے ہیں۔ ایک بری کاسٹ ایک ناممکن قسم کی حالت کے ذریعے پھانسی بھیج سکتی ہے۔ کسی پروگرام کے داغدار ASan کی حد کو عبور کرنے سے پہلے غلط طریقے سے رسائی یا ریاضی کے زیادہ بہاؤ مفروضوں کو توڑ سکتے ہیں۔ ان صورتوں میں، UBSan کی دریافت نتیجے میں ہونے والے ASan حادثے کے مقابلے میں اصل غلطی کے قریب ہو سکتی ہے۔

بحالی کی پالیسیاں جان بوجھ کر منتخب کرنے کے قابل ہیں۔ UBSan کا استعمال جاری رکھنے سے ایک ہی رن کے دوران متعدد زمروں کو بے نقاب کیا جا سکتا ہے، جو وسیع تلاش کے دوران مفید ہے۔ پہلے نتیجہ میں ناکامی عملدرآمد کو ابتدائی طور پر معلوم غلط حالت کے قریب رکھتی ہے، جس کا رجعت لین سے اندازہ لگانا اکثر آسان ہوتا ہے۔

رساو کا پتہ لگانا بھی عام طور پر ASan کی تعمیرات کا اشتراک کرتا ہے۔ معاون پلیٹ فارمز پر، LSan ASan رن ٹائم کے ذریعے چل سکتا ہے اور جب عمل ختم ہو جاتا ہے تو قابل رسائی تجزیہ کر سکتا ہے۔ یہ عمل درآمد کے دوران رسائی کی خلاف ورزی کی کوریج اور ایک ہی بائنری میں ریلیز پر لیک کیلکولیشن دونوں فراہم کرتا ہے۔

اسٹینڈ ایلون LSan تب بھی مفید ہے جب ASan کے باقی آلات کے بغیر لیک ٹیسٹنگ کی ضرورت ہو۔ انتخاب زیادہ تر آپریشنز کے بارے میں ہے۔ جب بھروسہ مند ASan تعمیرات پہلے سے موجود ہیں، لیک سپورٹ کو فعال کرنا عام طور پر انفرادی تعمیراتی ترتیبوں کی تعداد کو کم رکھتا ہے۔

TSan اور MSan کو الگ الگ تعمیرات کی ضرورت ہوتی ہے۔

TSan کا تعلق ASan سے مختلف بائنری سے ہے۔

دونوں ٹولز میموری تک بہت زیادہ رسائی حاصل کرتے ہیں اور بہت مختلف مقاصد کے لیے رن ٹائم حالت کو برقرار رکھتے ہیں۔ TSan کو رسائی کی تاریخ اور مطابقت پذیری میٹا ڈیٹا کی ضرورت ہے، جبکہ ASan کو شیڈو ایڈریس ایبل حالت اور مختص کرنے والے انضمام کی ضرورت ہے۔ عملی طور پر، ان کو ایک ہی سینیٹائزر آپریشن کی مختلف حالتوں کے بجائے الگ مشاہدے کے ماحول کے طور پر سمجھا جانا چاہیے۔

یہ علیحدگی بہرحال مفید ہے کیونکہ کام کا بوجھ مختلف ہونا چاہیے۔

ASan لین پارسر ٹیسٹنگ، لائف سائیکل تناؤ، اور ایرر پاتھ کوریج میں غیر معمولی قدر فراہم کرتی ہیں۔ TSan لین کو ہم آہنگی کی ضرورت ہوتی ہے۔ اس کا مطلب ہے کہ آپ کو کام کی نقل، بار بار تھریڈ سوئچنگ، کال بیک تنازعہ، کام کے فعال ہونے کے دوران ختم کرنے، اور دلچسپ شیڈولنگ کے لیے کافی تکرار کی ضرورت ہے۔

کارکردگی کے بجٹ بھی مختلف ہیں۔ کام کا بوجھ جو ASan پر بالکل مناسب ہے TSan پر بہت مہنگا ہو سکتا ہے۔

MSan کو ایک اور وجہ سے اپنا ماحول درکار ہے۔ ابتدائی ذرائع پر صرف اس صورت میں بھروسہ کیا جا سکتا ہے جب اس ریاست کو پاس کرنے والا کوڈ کافی طریقے سے تیار کیا گیا ہو۔

شامل کرنا -fsanitize=memory اہم بنیادی انحصار کو مبہم چھوڑنے سے ابتدا کی تاریخ ٹوٹ سکتی ہے جس کی پیروی کرنے کی MSan کوشش کر رہا ہے۔ سنجیدہ MSan سیٹ اپ ایک اضافی کمپائلر فلیگ کے ساتھ ایک عام ایپلی کیشن کی تعمیر کے بجائے ایک انسٹرومینٹڈ انحصار گراف کی طرح نظر آتے ہیں۔

یہ بلڈ میٹرکس کو غیر متناسب بناتا ہے، جو ٹھیک ہے۔

ایک پروجیکٹ زیادہ تر تبدیلیوں کے لیے ASan+UBSan چلا سکتا ہے، اسی بائنری کے حصے کے طور پر لیک کا پتہ لگا سکتا ہے، چھوٹے، انتہائی ہم آہنگی والے کام کے بوجھ کے لیے TSan چلا سکتا ہے، اور MSan کو صرف ایسے ماحول میں چلا سکتا ہے جو متعلقہ انحصار کو درست طریقے سے دوبارہ بنا سکے۔ ایک مفید سوال یہ نہیں ہے کہ آیا تمام ٹولز ایک ہی CI مرحلے پر ظاہر ہوتے ہیں، بلکہ یہ ہے کہ ہر لین قابل اعتماد طریقے سے کیا دیکھ سکتی ہے۔

ہارڈ ویئر سپورٹ اور پروڈکشن سائیڈ چیک

سافٹ ویئر ASan زندگی بھر اور حدود کی غلطیوں کا مشاہدہ کرنے کا صرف ایک طریقہ ہے۔

ہارڈ ویئر کی مدد سے ایڈریس سنیٹائزر اور آرم میموری ٹیگنگ ایکسٹینشنز ٹیگ شدہ میموری اور پوائنٹرز کا استعمال کرتے ہیں تاکہ استعمال میں موجود پوائنٹر اور اس کا حوالہ دینے والے مختص کے درمیان تضادات کا پتہ لگایا جا سکے۔ سپورٹ شدہ 64 بٹ آرم سسٹم ایسے ماحول میں میموری کے معائنے کو عملی بناتے ہیں جہاں روایتی آسن کے اوور ہیڈ کو برداشت کرنا مشکل ہوتا ہے۔

نقصانات سافٹ ویئر ASan سے مختلف ہیں۔

ٹیگ کی جگہ محدود ہے، لہذا غلط پوائنٹرز درست ٹیگز سے ٹکرا سکتے ہیں اور پتہ لگانے سے بچ سکتے ہیں۔ پلیٹ فارم سپورٹ اس بات کا تعین کرتا ہے کہ آپ اسکین کہاں چلا سکتے ہیں۔ اسٹیک، عالمی، اور مختص کرنے والے کے رویے کی درست ہینڈلنگ بھی روایتی ASan سے مختلف ہے۔

یہ میکانزم جو کچھ خریدتے ہیں وہ پھانسیوں تک رسائی ہے جو باقاعدہ سینیٹائزر CI کبھی نہیں دیکھ پائیں گے: طویل عرصے سے کام کا بوجھ، ڈیوائس کے لیے مخصوص رویہ، حقیقت پسندانہ مختص کرنے والے دباؤ، اور کچھ معاملات میں، پیداوار یا قریب پروڈکشن ٹریفک۔

محفوظ مختص کرنے والے، سخت مختص کرنے والے، نمونے کی یادداشت کا معائنہ، کریش ٹیلی میٹری، اور کینری کی تعیناتیاں اسی وسیع حکمت عملی میں فٹ ہیں۔ ہر ایک مکمل طور پر آلات والے ٹیسٹ ماحول سے باہر قابل قبول قیمت پر مختلف رن ٹائم رویے کا مشاہدہ کرتا ہے۔

اگر ممکن ہو تو، ان کے نتائج کو ایک تعییناتی ٹیسٹ سیٹ اپ میں واپس کیا جانا چاہیے۔ ASan میں زندگی کے چکر کو دوبارہ پیدا کرنے کے قابل ہونا نمونے کے بعد کی پیداوار کے استعمال کو بہت زیادہ قیمتی بنا دیتا ہے۔ طویل عرصے سے چلنے والے میموری کی ترقی کے پیٹرن کا نتیجہ شدید Lsan کام کے بوجھ سے ہوسکتا ہے۔ ہم آہنگی کی غلطیاں صرف بوجھ کے تحت دیکھی گئی ہیں TSan تناؤ کا معاملہ ہو سکتا ہے۔

پروڈکشن سائیڈ انسپکشن مشاہدے کے عمل کو بڑھاتا ہے۔ کمپائلر سینیٹائزر کی تعمیرات وہیں رہتی ہیں جہاں یہ غلطیاں عام طور پر دوبارہ پیدا کی جا سکتی ہیں، جس میں زیادہ ٹولز اور سخت کنٹرول ہوتے ہیں۔

گرین سینیٹائزر میٹرکس واقعی ہمیں کیا بتاتا ہے۔

جراثیم کش میٹرکس "کیا یہ صحیح پروگرام ہے؟” سے زیادہ تنگ سوالوں کے جواب دیتا ہے۔

یہ آپ کو بتاتا ہے کہ عمل درآمد کے دوران کیا ہوا جس کا انسٹرومینٹڈ رن ٹائم مشاہدہ کرنے کے قابل تھا۔

یہ بڑی حد تک دعوے کے دائرہ کار سے باہر ہے۔

جب کہ تمام جراثیم کش ادویات خاموش رہتی ہیں، کاروباری منطق ناقص ہو سکتی ہے۔ منظوری نامکمل ہو سکتی ہے۔ خفیہ کاری پروٹوکول کا غلط استعمال کیا جا سکتا ہے۔ ٹائمنگ اور دوسرے سائیڈ چینلز مکمل طور پر میموری سے محفوظ کوڈ میں موجود ہو سکتے ہیں۔ لاک فری الگورتھم بغیر کسی تنازعہ کے بھی مطلوبہ خطوط کی ضمانت دینے میں ناکام ہو سکتے ہیں۔

یہاں تک کہ میموری کی حفاظت اور ہم آہنگی کے اندر، کام کے بوجھ کی کوریج ایک سخت حد بنی ہوئی ہے۔ جو کوڈ نہیں چلتا ہے وہ متحرک رپورٹس نہیں بنا سکتا۔

میٹرولوجی ایک اور حد بناتی ہے۔ ASan مختص کرنے والے کے اندر پوشیدہ آبجیکٹ کی حدود کو نافذ نہیں کر سکتا جسے وہ سمجھ نہیں پاتا۔ MSan مبہم کوڈ میں ابتدائی تاریخ کھو دیتا ہے۔ TSan ان ہم آہنگی کو دوبارہ ترتیب نہیں دے سکتا جو رن ٹائم پر نظر نہیں آتے ہیں۔ غیر آلات والے تھرڈ پارٹی ماڈیول میں ایسے کیڑے شامل ہو سکتے ہیں جو محیطی سینیٹائزر آپریشنز کے لیے نظر نہیں آتے۔

دبائو دلیل کو مزید تنگ کرتا ہے۔ گرین رن کا مطلب ہے کوئی رن ٹائم نہیں ملا۔ غیر منقطع میں خلاف ورزیوں کی اطلاع دینے کا طریقہ جانتا تھا۔ لہذا، ہر دباو "صاف” کے معنی بدل دیتا ہے۔

کامیابی سے عمل درآمد سے منسلک دعووں کو درست طریقے سے بیان کرنا مددگار ہے۔

اس تعمیر کے لیے، اس کام کے بوجھ کے انسٹرومینٹ ایگزیکیوشن نے اس سینیٹائزر کے ذریعے قابل مشاہدہ رن ٹائم خصوصیات کی خلاف ورزی نہیں کی۔

یہ شائستہ لگ سکتا ہے، لیکن یہ ایک مفید انجینئرنگ بیان ہے۔ یہ آپ کو بالکل بتاتا ہے کہ باقی کام کہاں پڑتے ہیں۔

اگر آپ کا کام کا بوجھ کمزور ہے تو اپنے کام کا بوجھ بہتر کریں۔ اگر آپ کا انحصار مبہم ہے تو، اگر ممکن ہو تو اپنے انحصار کے گراف کو مزید بنائیں۔ اگر ایک ایرر کلاس ASan کے ماڈل سے باہر آتی ہے، تو اسے دیکھنے کے لیے ٹولز شامل کریں۔ اگر باقی غیر یقینی صورتحال رن ٹائم کوریج کے بجائے API ڈیزائن سے پیدا ہوتی ہے، جامد تجزیہ، کوڈ کا جائزہ، مضبوط ملکیت کی اقسام، یا انٹرفیس کی تبدیلیاں دیگر سینیٹائزر آپریشنز کے مقابلے میں بہتر فائدہ فراہم کر سکتی ہیں۔

ایک اچھا سینیٹائزر سیٹ اپ معروف شواہد میں خلا کو پُر کرنے سے بڑھتا ہے، نہ کہ کمپائلر جھنڈوں کو جمع کرنے سے۔

رن ٹائم باؤنڈریز کے پار FFI کی ملکیت

FFI بگز بار بار ہوتے ہیں کیونکہ انہیں زندگی بھر کے دو ماڈلز کو مختلف حدود کے ساتھ ملانے کی ضرورت ہوتی ہے۔ منیجڈ سائیڈ کوڑا کرکٹ اکٹھا کرنے اور فائنل کرنے والوں کا استعمال کر سکتی ہے، جبکہ مقامی طرف واضح مفت، حوالہ شماری، اسٹیڈیم، یا ملکیت کی منتقلی APIs کا استعمال کر سکتا ہے۔

ناکامی خلاصہ میں شاذ و نادر ہی "FFI” ہوتی ہے۔ اکثر دونوں فریق اس بات پر متفق نہیں ہوتے ہیں کہ کسی بھی لمحے وسائل کا مالک کون ہے۔

بار بار آنے والی ناکامیوں میں سے ایک ہے۔ اسٹیٹس کی منتقلی کے بغیر ملکیت منتقل کریں۔. ریپر ایک بنیادی ہینڈل بناتا یا وصول کرتا ہے اور ملکیت کسی دوسرے کو دیتا ہے، لیکن پھر بھی اس ہینڈل کو بطور دستیاب ظاہر کرتا ہے۔ اس بات کا کوئی اشارہ نہیں ہے کہ پوائنٹر کی ملکیت خود منتقل ہو گئی ہے۔ جب تک کہ ریپر کی حالت کو منتقلی کے حصے کے طور پر تبدیل نہیں کیا جاتا ہے، پچھلا مالک اب بھی ریپر کو آزاد کر سکتا ہے، کلین اپ منسلک کر سکتا ہے، یا بعد میں اسے استعمال کر سکتا ہے۔

یہ وہ جگہ ہے جہاں APIs جو قرض لینے، برقرار رکھنے اور ملکیت کی منتقلی کے درمیان فرق کرتے ہیں۔ بورنگ ایس ایس ایل ایک خاص مثال ہے۔ get0, get1, set0اور set1 یہ آپ کو بتاتا ہے کہ آیا حوالہ مستعار، ملکیت، اپنایا، یا برقرار رکھا گیا ہے۔ ایک ریپر جو ان تمام معاملات کو ایک ہی پوائنٹر کی نمائندگی میں کم کرتا ہے وہ معلومات کو کھو دیتا ہے جو مقامی API کے ذریعہ جان بوجھ کر سامنے آتی ہے۔ اس طرح ادھار لیے گئے ہینڈلز جاری کیے جاتے ہیں، منتقل کیے گئے ہینڈلز دوبارہ استعمال کیے جاتے ہیں، اور ملکیتی حوالہ جات خاموشی سے لیک ہو جاتے ہیں۔

ایک اور عام ناکامی ہے۔ رہائی کے طریقہ کار کا نقصان. یہ جاننا کافی نہیں ہے کہ آپ الاٹمنٹ کے مالک ہیں۔ آپ کو یہ بھی جاننے کی ضرورت ہے کہ اس مختص کو کیسے آزاد کیا جانا چاہئے۔ مقامی لائبریریاں مخصوص مفت فنکشنز کے ساتھ مختص کو یکجا کر سکتی ہیں، حوالہ شمار شدہ اشیاء کو واپس کر سکتی ہیں جن میں کمی کی کارروائیوں کی ضرورت ہوتی ہے، یا کال کرنے والے کے بجائے ایرینا کی ملکیت والی میموری واپس کر سکتے ہیں۔

بورنگ ایس ایس ایل پھر ایک سادہ سی مثال فراہم کرتا ہے۔ OPENSSL_malloc کے ذریعے ریلیز ہونے والا ہے۔ OPENSSL_free. اگر ریپر اس میموری کو کسی دوسرے مختص کرنے والے کی میموری کے ساتھ قابل تبادلہ سمجھتا ہے، تو غلطی اس وقت تک نظر نہیں آئے گی جب تک کہ اسے الگ نہ کیا جائے، یا جب تک کہ ASan، Valgrind، یا کوئی اور میموری چیکر اس ریلیز تک نہ پہنچ جائے جو مماثل نہیں ہے۔

وسیع تر اصول یہ ہے کہ مالک ریپر کو نہ صرف وسائل کا پتہ بلکہ وسائل کی تباہی کے الفاظ کو بھی محفوظ رکھنا چاہیے۔

تیسری ناکامی اس سے آتی ہے: فنشنگ کو تباہی سمجھنا. حتمی شکل دینے والے بالآخر بنیادی وسائل کو جاری کر سکتے ہیں، لیکن وہ تعییناتی زندگی فراہم نہیں کرتے ہیں۔ وقت کا انحصار رن ٹائم کی رسائی اور کوڑا کرکٹ جمع کرنے پر ہوتا ہے، نہ کہ اس لغوی نقطہ پر جس پر پروگرام کو اعتراض کی ضرورت بند ہو جاتی ہے۔

یہ امتیاز اہم ہے جب بھی بنیادی وسائل کی اپنی ایک بامعنی زندگی ہو۔ فائل ڈسکرپٹرز، بیس ہینڈلز، انکرپشن سیاق و سباق، GPU آبجیکٹ، ڈیٹا بیس ہینڈلز، اور اسی طرح کے وسائل کو اکثر واضح ریلیز سیمنٹکس کی ضرورت ہوتی ہے۔ ٹرمینیٹر فال بیک کے طور پر مفید ہے، لیکن اسے خاموشی سے دوسرا، خود مختار مالک نہیں بننا چاہیے۔

ٹرانسمیشن خاص طور پر خطرناک ہے. اگر کوئی منظم آبجیکٹ اپنا بنیادی ہینڈل دوسرے مالک کو دے دیتا ہے، لیکن اس کا حتمی کنندہ منسلک رہتا ہے، تو دونوں فریق اب یقین کر سکتے ہیں کہ وہ صفائی کے ذمہ دار ہیں۔ اس اقدام کے حصے کے طور پر ریپر کو اپنی ریاست کو باطل کرنا چاہیے۔ اس کا مطلب ہے کہ آپ کو فائنلائزر کو الگ کرنا ہوگا، ہینڈل کو صاف کرنا ہوگا، یا بصورت دیگر بعد کے استعمال کو فوری طور پر ناکام کرنا ہوگا۔

ناکامی کے راستے ایک اور قسم کا بگ پیدا کرتے ہیں۔ آپ کا کوڈ کامیاب راستے پر بالکل درست ہو سکتا ہے، لیکن اگر آپریشن درمیان میں ناکام ہو جاتا ہے، تب بھی آپ کے پاس ملکیت کی کوئی مستقل کہانی نہیں ہے۔

فرض کریں کہ ایک فنکشن تین عارضی آبجیکٹ مختص کرتا ہے اور ان میں سے ایک کو صرف اس صورت میں منتقل کرتا ہے جب حاصل کامیاب ہو۔ ناکامی کے راستے کو کسی بھی چیز کو جاری کرنا چاہئے جو نہیں بھیجا گیا تھا۔ کامیابی کے راستے کو اس چیز کو آزاد کیے بغیر باقی عارضی کو آزاد کرنا چاہیے جس کی ملکیت منتقل کی گئی ہے۔ یہ ایک الگ سوال ہے۔ کیا صفائی ہر ایگزٹ پر چلتی ہے، اور جب یہ چلتی ہے، کون سی چیزیں اب بھی اس صفائی کے راستے کا حصہ ہیں؟

یہ صفائی کی حد ہے، RAII گارڈ، defer-اسٹائل میکانزم اور اسی طرح کے پیٹرن کارآمد ہیں۔ کلین اپ کو ڈیفالٹ کے طور پر سیٹ کرنا اور پھر اس صفائی کی ذمہ داری سے آبجیکٹ کو واضح طور پر ہٹانے کے لیے ملکیت کی کامیاب منتقلی کی ضرورت ہے۔ اس امتیاز کے بغیر، ناکامی پر ایک ہی کوڈ لیک ہو سکتا ہے اور کامیابی پر ڈبل فری۔

ایک چھوٹی سی C++ مثال ظاہر کرتی ہے کہ جب واضح طور پر اظہار کیا جائے تو وہ حالت کیسی دکھتی ہے۔ بورنگ ایس ایس ایل یہاں ایک ٹھوس API فراہم کرتا ہے، لیکن پیٹرن بنیادی، حوالہ شمار شدہ ہینڈلز پر لاگو ہوتا ہے۔

#include 
#include 
#include  

struct PKeyDeleter { 
    void operator()(EVP_PKEY* p)
    const noexcept { EVP_PKEY_free(p); } 
};

using UniquePKey = std::unique_ptr; 

class KeySlot { 
    public: 
        // The slot owns exactly one reference. 
        explicit KeySlot(UniquePKey key) : key_(std::move(key)) {} 

        // Borrow without changing ownership. 
        EVP_PKEY* borrow() const noexcept { 
            return key_.get();
        } 

        // Transfer ownership out. The slot becomes empty.
        UniquePKey take() {
            return std::move(key_); 
        } 
        
        // Create another owning reference for shared use.
        UniquePKey clone_ref() const {
            if (!key_) { 
                throw std::logic_error("empty slot"); 
            }

            if (EVP_PKEY_up_ref(key_.get()) != 1) { 
                throw std::runtime_error("EVP_PKEY_up_ref failed"); 
            } 
            return UniquePKey(key_.get()); 
        } 
        bool empty() const noexcept {
            return key_ == nullptr;
        }

    private: UniquePKey key_; 
};

مفید حصہ یہ ہے کہ ملکیت کے مختلف کام اب ایک جیسے نظر نہیں آتے۔ borrow() دوسرا مالک بنائے بغیر ہینڈل کو بے نقاب کرتا ہے۔ take() مالک کا حوالہ منتقل کریں اور ماخذ کو خالی چھوڑ دیں۔ clone_ref() واضح طور پر ایک اور ملکیتی حوالہ تخلیق کرتا ہے۔

ایک قسم کا نظام زندگی بھر کی تمام خرابیوں کو نہیں روک سکتا، لیکن یہ غلطی سے ملکیت کی منتقلی کو زیادہ مشکل بنا سکتا ہے۔ یہ ASan اور LSan کو جانچنے کے لیے کلینر ماڈل فراہم کرتا ہے۔ ایک باسی رسائی یا لیک ہونے والا حوالہ ناقابل شناخت خام پوائنٹرز کے سمندر کے بجائے کسی مخصوص ٹوٹی ہوئی منتقلی کی طرف اشارہ کرتا ہے۔

منظم FFI کوڈ کو اکثر اسی حالت کو زیادہ واضح طور پر انکوڈ کرنے کی ضرورت ہوتی ہے کیونکہ زبان کی عام آبجیکٹ لائف ٹائم خود بخود بنیادی آبجیکٹ کی زندگی بھر کی وضاحت نہیں کرتا ہے۔ ریپر اب بھی امتیاز کو نشان زد کر سکتا ہے۔

import 'dart:ffi' as ffi;

final class NativeHandle extends ffi.Opaque {}

final class OwnedNativeHandle {
    OwnedNativeHandle(this._ptr, this._free, this._finalizer)
        : _token = Object() {
            _finalizer.attach(this, _ptr.cast(), detach: _token);
    }

    ffi.Pointer? _ptr;
    final void Function(ffi.Pointer) _free;
    final ffi.NativeFinalizer _finalizer;
    final Object _token;

    bool get isMoved => _ptr == null;

    ffi.Pointer borrow() {
        final ptr = _ptr;
        
        if (ptr == null) {
            throw StateError('Native handle is no longer owned here');
        }

        return ptr;
    }

    ffi.Pointer move() {
        final ptr = borrow();
        
        _finalizer.detach(_token);
        _ptr = null;

        return ptr;
    }

    void close() {
        final ptr = _ptr;
        
        if (ptr == null) return;

        _finalizer.detach(_token);
        _ptr = null;
        _free(ptr);
    }
}

یہاں، move() یہ صرف ایک پوائنٹر واپس کرنے سے زیادہ ہے. ریپر کی حالت کو تبدیل کرتا ہے۔ ملکیت چھوڑنے کے بعد، پچھلا مالک ہینڈل کو دوبارہ کرائے پر نہیں لے سکتا اور ٹرمینیٹر کے پاس اسے چھوڑنے کا اختیار نہیں رہتا۔ close() یہ انہی اصولوں کی پیروی کرتا ہے اور ایک سے زیادہ مرتبہ کال کرنا محفوظ ہے کیونکہ ڈیفالٹ ریلیز ہونے سے پہلے ملکیت کی حالت بدل جاتی ہے۔

درست نمائندگی کا انحصار زبان اور رن ٹائم پر ہوتا ہے۔ کچھ سسٹم nullable ہینڈلز کا استعمال کرتے ہیں، کچھ وقف شدہ حرکت کی حالت کا استعمال کرتے ہیں، کچھ پوائنٹر کو مالک آبجیکٹ کے پیچھے چھپاتے ہیں، اور دیگر لکیری یا affine اقسام کا استعمال کرتے ہیں۔ اہم بات یہ ہے کہ منتقلی پچھلے مالک کی حالت کو اس طرح تبدیل کرتی ہے جس کا باقی پروگرام مشاہدہ کر سکتا ہے۔

عارضی قبضے کو بھی اسی علاج کی ضرورت ہوتی ہے۔ لغوی صفائی کی گنجائشیں "غیر بھیجی ہوئی ریلیز” کو واضح کر سکتی ہیں۔

final class Scope {
    final Map

دائرہ کار ہر چیز کا مالک ہوتا ہے جب تک کہ وہ دو چیزوں میں سے کوئی ایک نہ ہو جائے: یا تو صفائی کی جاتی ہے یا ملکیت کو واضح طور پر کہیں اور منتقل کر دیا جاتا ہے۔ چونکہ پہلے سے طے شدہ سلوک "اب تک کامیابی کے ساتھ مختص کردہ تمام اشیاء کو یاد رکھیں” کے بجائے صفائی کا ہوتا ہے، اس سے قبل از وقت واپسی اور جزوی ناکامیوں کے بارے میں استدلال کرنا بہت آسان ہوجاتا ہے۔

یہ وہ جگہ ہے جہاں مختلف جراثیم کش ماڈل ایک ہی ملکیت کی کہانی کے گرد سیدھ میں آنا شروع ہوتے ہیں۔ اگر پچھلا مالک منتقل شدہ چیز کو آزاد کرنا جاری رکھتا ہے، تو ASan نتیجے کے طور پر مفت کے بعد مفت یا غلط رسائی کے نتائج حاصل کر سکتا ہے۔ اگر غلطی کا راستہ کسی شے کو آزاد کرنا بھول جاتا ہے جو اس کی ملکیت ہے، تو LSan یا لیک پر مبنی لین اس شے کو پھاڑ پھاڑ پر ظاہر کر سکتی ہے۔ اگر بیس کال آؤٹ پٹ ڈھانچے کو مکمل طور پر شروع کیے بغیر کامیابی کی اطلاع دیتی ہے، تو MSan دیگر باؤنڈری معاہدے کی ناکامیوں کو ظاہر کر سکتا ہے۔ اگر بند، کال بیک، یا کلین اپ پاتھ تھریڈز میں مقابلہ کرتے ہیں، تو TSan غائب ہم آہنگی کو ظاہر کر سکتا ہے جب وہ آپریشنز رن ٹائم پر ظاہر ہوتے ہیں۔

اگرچہ اوزار مختلف علامات کی اطلاع دیتے ہیں، ان کے ڈیزائن کے کام اکثر ایک جیسے ہوتے ہیں۔ یعنی، یہ ملکیت، رہائی، منتقلی، اور زندگی بھر کی منتقلی کو واضح کرتا ہے تاکہ ہر حد پر صرف ایک ہی معقول تشریح ہو۔

یہ ایک مفید فریم ہے۔ webcrypto.dart کیس اسٹڈی مندرجہ ذیل ہے۔ ڈارٹ، بورنگ ایس ایس ایل، اور بنیادی بلڈ ہکس اور فائنلائزر تفصیلات کو ٹھوس بناتے ہیں، لیکن بنیادی مسئلہ ایسا نہیں ہے۔ یہ وہی ملکیت کا سوال ہے جس کا جواب آخر کار منظم/مقامی حدود کو دینا پڑے گا۔ فی الحال اس وسائل کا مالک کون ہے، اسے کیسے جاری کیا جانا چاہیے، ملکیت منتقل ہونے پر کیا تبدیلیاں آتی ہیں، اور اگر آپریشن وقت سے پہلے ناکام ہو جاتا ہے تو کیا ہوتا ہے؟

کیس اسٹڈی: webcrypto.dart مسئلہ نمبر 278

webcrypto.dart یہ ایک مفید مثال ہے کیونکہ ملکیت کے متعدد نظام ایک کافی چھوٹے سطحی علاقے میں ملتے ہیں۔ براؤزرز میں، پیکجز پلیٹ فارم ویب انکرپشن کے نفاذ پر انحصار کر سکتے ہیں۔ براؤزر کے باہر، ہم اس کے ذریعے مقامی کوڈ میں کودتے ہیں: dart:ffi ذیل میں ہم بورنگ ایس ایس ایل استعمال کرتے ہیں۔ ڈارٹ بلڈ ہکس بنیادی اثاثے بنانے کے ذمہ دار ہیں۔

اس کا مطلب یہ ہے کہ ایک ہی آپریشن میں ڈارٹ آبجیکٹ تک رسائی، ڈیفالٹ ریفرنس کی گنتی، واضح مختص اور صفائی، حتمی شکل دینے والے، اور ٹولز کی تعمیر شامل ہوسکتی ہے جو اس بات کا تعین کرتی ہے کہ ڈیبگر اصل میں کتنا نتیجہ دیکھ سکتا ہے۔

ایک پرت میں غلطی کا مطلب ناکامی کا مطلب نہیں ہے۔ ریپر یا تو بنیادی آبجیکٹ کو لیک چھوڑ سکتا ہے اور صحیح کرپٹوگرافک نتیجہ واپس کر سکتا ہے، یا فائنلائزر کو ایسے ہینڈل سے منسلک رکھ سکتا ہے جس کی ملکیت پہلے ہی کہیں اور منتقل ہو چکی ہے۔

شمارہ #278 1.0.0 کی ریلیز کے لیے کام کے حصے کے طور پر جاری کیا گیا تھا۔ موجودہ ٹیسٹ پہلے سے ہی پیکیج کے فعال پہلوؤں کو اچھی طرح سے احاطہ کرتے ہیں۔ زیادہ مشکل سوال یہ تھا کہ ان کامیاب آپریشنز کے بعد کیا ہوا؟ یہ تھے کہ آیا مقامی اشیاء کو صحیح طریقے سے جاری کیا گیا تھا، آیا ملکیت کی منتقلی پرانے مالکان کے پیچھے رہ گئی ہے، آیا دائرہ کار اور حتمی شکل دینے والے اس بات پر متفق ہیں کہ صفائی کا ذمہ دار کون ہے، اور کیا کوڑا اٹھانے کا وقت زندگی بھر کے کیڑے کو بے نقاب کر سکتا ہے جو عام جانچ میں چھوٹ سکتے ہیں۔

یہ سوالات براہ راست فقروں میں ظاہر ہوتے ہیں جیسے: NativeFinalizer, _Scopeاور _SslAllocator. بورنگ ایس ایس ایل ملکیتی امتیازات بھی پیدا کرتا ہے جسے ڈارٹ ریپرز کو محفوظ رکھنا چاہیے۔ کچھ حوالہ جات مستعار ہیں، کچھ کو برقرار رکھا گیا ہے، اور کچھ کالز ملکیتی ہیں۔ ایک بار ملکیت مقامی کوڈ میں منتقل ہو جانے کے بعد، ڈارٹ سائیڈ اس طرح کام کرنا جاری نہیں رکھ سکتی جیسے وہ ایک ہی ہینڈل کا مالک ہو۔ ریپر کو اسے صفائی کے دائرہ کار سے ہٹانے، فائنلائزر کو الگ کرنے، یا ہینڈل کو مکمل طور پر باطل کرنے کی ضرورت پڑ سکتی ہے۔

قدرتی اگلا قدم زیادہ طاقتور میموری سیفٹی ٹولز کے ساتھ اس راستے پر جانا تھا۔ یہ وہ جگہ ہے جہاں آس پاس کا ٹول چین مسئلہ کا حصہ بن جاتا ہے۔

ویلگرینڈ پہلے کیوں آیا؟

ڈارٹ SDK میں سینیٹائزر کا راستہ مسدود ہے۔ webcrypto.dart اگرچہ یہ مقامی اثاثوں کے لئے تعمیراتی ہکس پر انحصار کرتا ہے، سینیٹائزر سپورٹ کی جانچ ابھی تک اس سیٹ اپ کی مکمل حمایت نہیں کرتی ہے۔ لاپتہ کام کو Dart SDK شمارے #63489 میں اوپر کی طرف ٹریک کیا گیا ہے۔

AOT پیکیجنگ اور سمبلائزیشن سے متعلق دوسرا مسئلہ تھا۔ مرتب شدہ ڈارٹ کوڈ کو موجودہ لے آؤٹ کے رن ٹائم میں پیک کرتے ہوئے، فارم ڈیلیٹ کرنے کی رپورٹ میں علامتوں کو ظاہر کرنا ممکن نہیں تھا، جس کے لیے مقامی ٹولز کی ضرورت تھی۔ اس کام کو شمارہ نمبر 63435 میں الگ سے دیکھا گیا ہے۔

لہذا آپ کو صرف یہ کرنا ہے کہ اندر ایک سینیٹائزر جھنڈا شامل کریں۔ webcrypto.dart ہم جراثیم کش ادویات کی قابل اعتماد لائن تیار نہیں کر پاتے۔ پراجیکٹ کو سب سے پہلے SDK سپورٹ کی ضرورت تھی تاکہ سینیٹائزر کے تحت صحیح بنیادی اثاثے تیار کیے جا سکیں اور ایسی رپورٹیں تیار کی جا سکیں جن کو مفید کوڈ میں دوبارہ میپ کیا جا سکے۔

ویلگرینڈ نے اسی طرح انضمام پر انحصار نہیں کیا۔ لہذا، PR #295 نے ایک Linux Memcheck لین کو شامل کیا جو موجودہ ٹیسٹ کے راستوں کے خلاف چلایا جا سکتا ہے جبکہ سینیٹائزر کا کام اوپر کی طرف بلاک رہتا ہے۔

کام کا بوجھ جان بوجھ کر عام الگورتھم کوریج کے بجائے بنیادی آبجیکٹ لائف ٹائم کو نشانہ بناتا ہے۔ AES-GCM، HMAC، ECDH، RSA-OAEP، کلیدی درآمد اور برآمد، ناکام درآمدات، اور قلیل المدتی اشیاء کی بار بار تخلیق۔

الگورتھم خود دلچسپ حصہ نہیں تھا۔ یہ آپریشن مختلف مختص اور صفائی کے راستوں کی طرف لے جاتے ہیں۔ ملکیت کی تصدیق ہونے سے پہلے کلیدی درآمد متعدد عارضی اشیاء مختص کر سکتی ہے۔ ناکام درآمدات صفائی انجام دیتی ہیں جسے کامیاب راستے کبھی نہیں چھوتے۔ بار بار کی جانے والی مختصر مدتی کارروائیاں قلیل تعداد میں مستقل اشیاء کے ساتھ طویل عرصے تک چلنے والے تھرو پٹ ٹیسٹوں کے مقابلے کو حتمی شکل دینے اور کھولنے پر زیادہ بوجھ ڈالتی ہیں۔

یہ وہ جگہ ہے جہاں میموری چیکر کام آتا ہے۔ ٹیسٹ اب بھی اس بات کی تصدیق کرتے ہیں کہ آپریشن کام کر رہا ہے، لیکن متحرک تجزیہ لین یہ بھی پوچھ سکتے ہیں کہ کیا کوئی چیز لیک ہوئی ہے، غلط طریقے سے آزاد ہوئی ہے، یا ریپر کے سوچنے کے بعد کہ آپریشن مکمل ہو گیا ہے۔

والگرینڈ نے عملی مسائل کو بھی بے نقاب کیا جو جب بھی منظم رن ٹائم کے ارد گرد میموری چیکرز رکھے جاتے تھے تو ظاہر ہوتے تھے۔ اس کا مطلب یہ ہے کہ تمام اطلاع شدہ مختصات لازمی طور پر جانچ کے تحت لائبریری سے تعلق رکھتی ہیں۔

دوسرے بہترین نے قطعی اور ممکنہ لیک دونوں کی اطلاع دی، لیکن صرف قطعی لیک CI میں ناکام رہا۔ ممکنہ لیک اب بھی آؤٹ پٹ میں نظر آئیں گے کیونکہ کچھ نان ڈارٹ VM رن ٹائم رویے سے پیدا ہو سکتے ہیں۔ webcrypto.dart خود اس سے پہلے کہ اس منصوبے کی قطعی طور پر درجہ بندی کی جا سکے مبہم زمروں کو روکنے کی کوئی اہمیت نہیں تھی۔

یہ فرق Valgrind سے آگے اہم ہے۔ ایک کارآمد CI گیٹ کے لیے ناکامی کے زمرے درکار ہوتے ہیں جنہیں ٹیم کارروائی کرنے کے لیے کافی اچھی طرح سمجھتی ہے۔ نتائج کی ایک وسیع رینج کو ریکارڈ کیا جا سکتا ہے اور اس کا بہانہ کیے بغیر جانچ پڑتال کی جا سکتی ہے کہ ان سب میں یکساں اعتبار ہے۔

واقعات کو عام کرنا

اس کیس کا دلچسپ حصہ یہ نہیں ہے کہ ایک ڈارٹ پیکیج ویلگرینڈ کو استعمال کرنے کے لیے ہوا ہے۔

پہلا وسیع سبق یہ ہے: ٹول چین جراثیم کش کوریج کا حصہ ہے۔. ایک کمپائلر ASan یا LSan کو مکمل طور پر سپورٹ کر سکتا ہے، لیکن اس کا مطلب یہ نہیں ہے کہ ہر پیکج، رن ٹائم، ٹیسٹ رنر، مقامی اثاثہ پائپ لائن، یا AOT لے آؤٹ مفید آلات کے ساتھ عمل درآمد کر سکتا ہے۔ اگر متعلقہ کوڈ کو صحیح طریقے سے بنایا، لوڈ یا انکوڈ نہیں کیا جا سکتا ہے تو اکیلے سینیٹائزر جھنڈوں کا بہت کم اثر ہوتا ہے۔

دوسرا یہ ہے کہ کام کے بوجھ کو ملکیت کے ماڈل کی پیروی کرنا چاہئے۔ مزید کرپٹوگرافک آپریشنز چلانا فطری طور پر مفید نہیں ہے۔ ان کارروائیوں کو انجام دینا جو بار بار بنیادی وسائل کو مختص، منتقلی، ناکام، ختم، اور حتمی شکل دیتے ہیں۔ بہت سارے ڈیٹا بیس بائنڈنگز، امیج کوڈیکس، لینگویج رن ٹائمز، GPU ریپرز، JNI کوڈ، Python ایکسٹینشنز، یا دیگر FFIs والے سسٹمز پر بھی یہی لاگو ہوتا ہے۔

تیسرا، ملکیت کی منتقلی سرحد کے دونوں طرف نظر آنی چاہیے۔ ایک بار جب مقامی فریق ہینڈل کو اپنا لیتا ہے، تو منظم سائیڈ کو فوری طور پر مالک کے طور پر ظاہر نہیں ہونا چاہیے۔ اگر صفائی ایک لغوی دائرہ کار میں آتی ہے، تو کامیاب منتقلی کے لیے ضروری ہے کہ اس دائرہ کار سے آبجیکٹ کو ہٹا دیا جائے۔ فائنلائزر ایک فال بیک کے طور پر رہ سکتے ہیں، لیکن انہیں خود بخود انہی وسائل کے لیے عزمی صفائی کا مقابلہ نہیں کرنا چاہیے۔

آخر میں، بلاک شدہ سینیٹائزر انضمام کا مطلب یہ نہیں ہے کہ کوئی متحرک چیکنگ بالکل نہیں ہے۔ اس صورت میں، ہو سکتا ہے کہ SDK ابھی تک سینیٹائزر سے چلنے والے ٹیسٹ پاتھ کو سپورٹ نہ کرے جو آپ کا پروجیکٹ چاہتا ہے۔ Valgrind اب بھی CI میں مقامی زندگیوں کو چلانے کا ایک طریقہ فراہم کرتا ہے، جبکہ سینیٹائزر سپورٹ کی کمی کو ابھی بھی اوپر کی طرف ٹریک کیا گیا تھا۔

ترقی تقریباً اس طرح تھی:

d64605ac-41ae-468a-be14-749fb3347dd9

webcrypto.dart اس آپریشن نے بالآخر مطلوبہ ڈس انفیکشن لین حاصل نہیں کی۔ SDK ابھی تک اس کی حمایت نہیں کرتا ہے۔ ہم نے اس پروجیکٹ سے جو کچھ حاصل کیا وہ ایک دہرائی جانے والی بیس لائن لائف ٹائم کام کا بوجھ تھا، ایک لینکس میموری انسپکشن لین جسے ہم CI پر چلا سکتے تھے، اور ایک اپ اسٹریم مسئلہ جس نے ٹولنگ کے باقی فرق کو واضح کر دیا۔

یہ ڈارٹ سے آگے ایک مفید نمونہ ہے۔ یہ فی الحال قابل مشاہدہ رن ٹائم خصوصیات کو لاگو کرتا ہے اور گمشدہ کوریج کو اس وقت تک ظاہر کرتا رہتا ہے جب تک کہ ٹول چین کسی اور مضبوط چیز کی حمایت نہ کر سکے۔

حقیقی نظاموں میں سوچنے کے نمونے۔

حقیقی دنیا کے واقعات سب سے زیادہ کارآمد ہوتے ہیں جب وہ ناکامی کے طریقوں کو بے نقاب کرتے ہیں جو کہیں اور ظاہر ہوتے ہیں۔ نام اور CVE بگ کی ظاہری شکل سے کم اہم ہیں۔ بگ کے ظاہر ہونے کے لیے کیا ہونا تھا، سینیٹائزر کیا دیکھ سکتا تھا، اور درستی کا اصل تعلق کہاں سے تھا۔

پیٹرن 1: استعمال کے بعد مفت صرف فزنگ میں ہوتا ہے۔

CVE-2024-7528 سے متعلق Mozilla کا IndexedDB مسئلہ اس بات کی ایک اچھی مثال ہے کہ ASan اور fuzzing کیوں ساتھ ساتھ کام کرتے ہیں۔

use-after-free نے واضح ہیپی پاتھ ٹیسٹ کا انتظار نہیں کیا۔ سب سے پہلے، اس کے لیے ایک مخصوص لائف سائیکل حالت کی ضرورت ہوتی ہے۔ کوریج پر مبنی فزنگ نے کوڈ کو اس حالت میں دھکیل دیا، اور ASan نے جو کچھ ہوا اسے دوبارہ ترتیب دینے کے لیے کافی مختص اور ڈیلوکیشن ہسٹری کے ساتھ باسی رسائی کو پکڑ لیا۔

اہم حصہ آرڈر ہے۔ تیار کردہ ان پٹ زندگی بھر کسی چیز تک پہنچ جاتا ہے جسے عام ٹیسٹوں میں شاذ و نادر ہی انجام دیا جاتا ہے۔ ASan غلط رسائی کو پکڑتا ہے، متضاد آدانوں کو محفوظ کیا جاتا ہے، اور ملکیت کی منتقلی پر تصحیحیں ہوتی ہیں جس نے اس قطار کے بجائے باسی حوالہ تخلیق کیا جس نے اس کا حوالہ دیا تھا۔

ایک بار ان پٹ کم سے کم ہونے کے بعد، اسے ریگریشن کارپس میں برقرار رکھا جانا چاہیے۔ اس طرح ایک بار کی جراثیم کش دریافت ایک مستقل امتحان بن جاتی ہے۔

پیٹرن 2: آؤٹ پٹ مکمل طور پر درست ہونے سے پہلے کامیابی واپس کردی جاتی ہے۔

CVE-2022-31741 کے ساتھ منسلک NSS S/MIME بگ "غیر شروع شدہ میموری کا استعمال” کے جملے سے زیادہ دلچسپ ہے۔

کال کرنے والے نے کامیاب واپسی کو آؤٹ پٹ ویلیو استعمال کرنے کی اجازت کے طور پر سمجھا۔ تاہم، کالی میں ایک راستہ اپنے آؤٹ پٹ کو شروع کیے بغیر کامیابی واپس کر سکتا ہے۔ MSan نے بعد میں غیر شروع شدہ قیمت کو پکڑا، لیکن اصل بگ واپسی کی قیمت اور آؤٹ پٹ کنٹریکٹ کے درمیان مماثلت تھی۔

یہ فرق اہم ہے۔ کال سائٹ پر متغیر کو 0 پر سیٹ کرنا ایک رپورٹ کو خاموش کر سکتا ہے، لیکن یہ API کو بھی مبہم بنا دیتا ہے۔ ایک کامیاب کال کے لیے واضح پوسٹ کنڈیشنز قائم کرنی چاہیے۔ اس کا مطلب ہے کہ آؤٹ پٹ کو مکمل طور پر شروع کرنے کی ضرورت ہے، یا API کو جزوی حالت کی واضح طور پر نشاندہی کرنے کے لیے ایک طریقہ کی ضرورت ہے۔

MSan خاص طور پر اس قسم کے کیڑے کے لیے مفید ہے کیونکہ یہ ظاہر کرتا ہے کہ اقدار کہاں قابل مشاہدہ ہیں، اور اصل سے باخبر رہنا اکثر ایسے راستوں کی طرف اشارہ کر سکتا ہے جو ابتدا کو چھوڑ دیتے ہیں۔

پیٹرن 3: ساز و سامان کی حدود پر تنازعہ کی رپورٹس

گرافکس کوڈ پر موزیلا کا TSan کام ایک مختلف مسئلہ پیش کرتا ہے۔ مسابقتی رپورٹس کی تشریح کرنا مشکل ہو سکتا ہے اگر ہم وقت سازی کی کہانی کا کچھ حصہ کوڈ میں ہو جسے TSan نہیں دیکھ سکتا۔

آئیے کہتے ہیں کہ TSan کے نقطہ نظر سے دو رسائییں ترتیب سے باہر نظر آتی ہیں، لیکن اس میں شامل ماڈیولز میں سے ایک آلہ کار نہیں ہے۔ اگر اس ماڈیول میں مطابقت پذیری ہے جو رسائی کو محفوظ بناتی ہے، تو TSan کے پاس آرڈر کو دوبارہ ترتیب دینے کا کوئی طریقہ نہیں ہے۔ اس کے برعکس بھی سچ ہے۔ غیر سازوسامان والے کوڈ کے اندر اصل ریس کی اطلاع بالکل بھی نہیں دی جا سکتی ہے۔

یہی وجہ ہے کہ میٹرک حدود کو شروع سے ہی نسلی درجہ بندی کا حصہ ہونا چاہیے۔ انسٹرومینٹڈ ماڈیولز کو ہم وقت سازی پرائمیٹوز کے ساتھ نقشہ بنائیں جو رپورٹ کو غلط مثبت کے ساتھ کال کرنے سے پہلے رن ٹائم پر ظاہر ہوتے ہیں۔ اگر آرڈر مبہم کوڈ پر منحصر ہے، یا تو اسے زیادہ مکمل انسٹرومینٹیشن اسٹیک کے ساتھ دوبارہ تیار کریں، یا اس حد کو تنگی سے دبائیں اور کیوں دستاویز کریں۔

ایک خطرناک شارٹ کٹ یہ ہے کہ "TSans پورے نظام کو نہیں دیکھ سکتے” جیسا کہ "نسل بے ضرر ہے۔”

پیٹرن 4: چھوٹے لیکس جو اب بھی خلاف ورزی کی طرف اشارہ کرتے ہیں۔

جب برقرار رکھا ہوا کوٹہ چھوٹا ہو تو لیکیج رپورٹس کو آسانی سے نظر انداز کیا جا سکتا ہے۔ بعض اوقات یہ ایک معقول شدت کا تعین ہوتا ہے۔ یہ ملکیت کو صحیح کہنے کے مترادف نہیں ہے۔

ایک تعییناتی لیک کا مطلب ہے کہ کچھ تفویض کیا گیا ہے یا کسی راستے پر برقرار ہے اور وہ رہائی مکمل نہیں ہے۔ یہاں تک کہ چند بائٹس بھی کارآمد ثبوت ہو سکتے ہیں، کیونکہ ایک ہی راستے کو ایک لوپ میں، طویل مدتی درخواستوں کے پیچھے، غلط ان پٹ کے ذریعے بار بار متحرک کیا جا سکتا ہے، یا غلطی سے نمٹنے کے دوران جمع کیا جا سکتا ہے۔

تین سوالوں کو الگ الگ رکھنا مفید ہے۔

  • اثر انداز: روٹ کتنی بار چل سکتا ہے، ہر رن کتنی میموری برقرار رکھتا ہے، اور کیا بیرونی اداکار بار بار روٹ کو متحرک کر سکتے ہیں؟

  • نتیجہ: وہ مالک کون ہے جو ڈی ایلوکیٹ کرنے میں ناکام رہا، یا کس حوالے نے غیر متوقع طور پر مختص کو روک دیا؟

  • پالیسی: کیا یہ موجودہ ریلیز کو روک دے گا؟ کون سے ٹیسٹ یا کام کا بوجھ اس بات کو یقینی بنائے گا کہ لیک دوبارہ نہ ہو؟

لیکس کا اثر کم ہو سکتا ہے اور پھر بھی حقیقی ملکیت کی خرابیوں کی نمائندگی کرتا ہے۔ یہ امتیاز خاص طور پر طویل عرصے سے چلنے والی خدمات اور FFI- ہیوی کوڈ میں محفوظ رکھنے کے قابل ہے، جہاں وقت کے ساتھ ساتھ چھوٹے ٹاسک مخصوص لیکس اہم ہو سکتے ہیں۔

دھندلا پن، تناؤ کا استعمال، اور ہم آہنگی کی تحقیقات

سینیٹائزر صرف ان خلاف ورزیوں کی اطلاع دے سکتے ہیں جو دراصل عمل درآمد کے دوران ہوتی ہیں۔ انسٹرومینٹیشن غلط پھانسیوں میں مرئیت فراہم کرتا ہے، لیکن پروگرام کو خود ہی دلچسپ راستوں پر جانے پر مجبور نہیں کرتا ہے۔

یہ وہ جگہ ہے جہاں کام کا بوجھ ڈیزائن کھیل میں آتا ہے۔

Fuzzers ان پٹ کی جگہ کو تلاش کرنے میں اچھے ہیں. تناؤ کا استعمال بار بار اشیاء کو زندگی کی منتقلی کے ذریعے دھکیلتا ہے۔ کنکرنسی پروبس تھریڈ انٹرلیونگز کی تعداد میں اضافہ کرتی ہیں جو پروگرام کا تجربہ ہوتا ہے۔ ہر ایک فنگسائڈ کو مکمل کرتا ہے کیونکہ یہ دوسری قسم کے نایاب رنز تک پہنچنا آسان بناتا ہے۔

فزنگ: ایسے راستے تلاش کرنا جن تک عام ان پٹ نہیں پہنچ پاتے۔

LLVM کا libFuzzer ایک جاری کوریج گائیڈڈ فزر ہے۔ ہدف ٹیسٹ بائنری سے منسلک ہے اور درج ذیل انٹری پوائنٹس کے ذریعے ظاہر ہوتا ہے: LLVMFuzzerTestOneInput. libFuzzer ان پٹس کو تبدیل کرتا ہے، کوریج انسٹرومینٹیشن کے ذریعے مشاہدہ کرتا ہے کہ کون سے تبدیلیاں نئے کوڈ تک پہنچتی ہیں، اور ان پٹ کو برقرار رکھتی ہیں جو اس کوریج کو بڑھاتے ہیں۔

چھوٹے اہداف میں شامل ہیں:

#include 
#include 

extern "C" void ParseOrImport(const uint8_t* data, size_t size);

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  ParseOrImport(data, size);
  return 0;
}

آسن کا استعمال:

clang++ -O1 -g -fsanitize=fuzzer,address 
  fuzz_target.cc -o fuzz_target

./fuzz_target corpus/

اور اگر آپ MSan کے لیے انحصاری گراف کو کافی طریقے سے تیار کر سکتے ہیں:

clang++ -O1 -g -fsanitize=fuzzer,memory 
  -fsanitize-memory-track-origins=2 
  fuzz_target.cc -o fuzz_target_msan

./fuzz_target_msan corpus/

ریپر فنکشن جان بوجھ کر غیر دلچسپ ہے۔ زیادہ تر کام اس کے پیچھے حدود کا انتخاب کر رہا ہے۔

ایک کارآمد فز ہدف اتنا تنگ ہے کہ تغیرات تیزی سے ایک بامعنی حالت تک پہنچ سکتے ہیں۔ یہ تعیین پسند، معقول حد تک تیز ہونا چاہیے، اور اس میں کوئی رویہ نہیں ہونا چاہیے جیسے کہ عمل کا خاتمہ یا خارجی عالمی حالت جس سے انفرادی آدانوں کو دوبارہ پیدا کرنا مشکل ہو۔ پارسرز، ڈیکوڈرز، پروٹوکول ہینڈلرز، ڈیسیریلائزرز، کلیدی درآمد کنندگان، فائل ریڈرز، اور اسی طرح کی حدود قدرتی اہداف ہیں کیونکہ ان پٹ میں چھوٹی تبدیلیاں بہت مختلف مختص اور غلطی سے نمٹنے کے راستوں کے ذریعے عملدرآمد بھیج سکتی ہیں۔

جراثیم کش اور صاف کرنے والے مختلف کام انجام دیتے ہیں۔ فزر ایسے راستے تلاش کر سکتا ہے جہاں پوائنٹرز باسی ہیں یا آؤٹ پٹ کو جزوی طور پر شروع کیا گیا ہے۔ ASan یا MSan آپ کو بتاتا ہے کہ نتیجے میں عمل درآمد غلط ہے۔

پہلے بیان کردہ NSS S/MIME بگ اس تعلق کی ایک مفید مثال ہے۔ ڈیکوڈر کے راستے میں ایک غیر معمولی پیغام آیا ہے جہاں ایک کامیاب واپسی کا مطلب یہ نہیں ہے کہ آؤٹ پٹ اصل میں شروع کیا گیا ہے. دلچسپ بات یہ ہے کہ یہ صرف اتنا نہیں ہے کہ ان پٹ کو غلط طریقے سے فارمیٹ کیا گیا ہے۔ ان پٹ ایک ایسی حالت تک پہنچ گیا ہے جہاں API کے ابتدائی معاہدے کی خلاف ورزی ہوئی ہے۔

اگر فزی ان پٹ کیڑے کو ظاہر کرتا ہے، تو ان پٹ کو رکھیں۔ اگر ممکن ہو تو کم سے کم کریں، اسی سینیٹائزر کے ساتھ ناکامی کو دوبارہ پیش کریں، بنیادی خرابی کو دور کریں، اور کم سے کم کیسز کو ریگریشن کارپس میں شامل کریں۔ بصورت دیگر، فزر کو ایک ہی کلاس کے کیڑے صرف ایک بار ملیں گے۔

تناؤ کا استعمال: منتقلی کی مشقیں۔

جب دلچسپی کا متغیر ان پٹ کے بجائے آبجیکٹ کی زندگی بھر ہوتا ہے تو فزنگ کم موثر ہوتی ہے۔

ایک باسی فائنلائزر، ایک گمشدہ حوالہ کی کمی، یا صفائی کا راستہ جو 10ویں تخلیق/کلوز سائیکل کے بعد غلط طریقے سے چلتا ہے، ہو سکتا ہے کسی بھی غیر معمولی بائٹس کی ضرورت نہ ہو۔ انہیں کافی بار یا صحیح ترتیب میں ہونے کے لیے ایک ہی زندگی کا چکر درکار ہوتا ہے۔

یہ ایک کشیدگی کے استعمال کا مقصد ہے.

کسی طویل المدتی آبجیکٹ پر ایک بڑا کام کا بوجھ بھیجنے کے بجائے، متعدد قلیل المدتی اشیاء بنائیں اور حذف کریں۔ ناکامیوں کے ساتھ متبادل کامیاب کام۔ بار بار حوالہ جات حاصل کریں اور جاری کریں۔ درآمد پھر برآمد کرنے کی مشق کریں، کھولیں پھر بند کریں، رجسٹر کریں پھر غیر رجسٹر کریں، جڑیں پھر الگ کریں۔ اگر آپ کا رن ٹائم اس کی اجازت دیتا ہے، تو ان ٹرانزیشن کے درمیان GC پریشر متعارف کروائیں۔ اگر مختص کا دوبارہ استعمال اہم ہے، تو اس بات کو یقینی بنانے کے لیے کافی چرن بنائیں کہ حال ہی میں آزاد کردہ میموری کے دوبارہ استعمال ہونے کا امکان ہے۔

مثال کے طور پر، مقامی وسائل کے ارد گرد ایک ریپر اس طرح چل سکتا ہے:

create
  -> use
  -> close

create
  -> transfer
  -> destroy previous wrapper
  -> use new owner
  -> close

create
  -> partially initialize
  -> fail
  -> clean up

repeat thousands of times

اس قسم کے کام کے بوجھ جان بوجھ کر تھرو پٹ بینچ مارک سے مختلف ہوتے ہیں۔ ایک بینچ مارک اپنا زیادہ تر وقت کسی ایسی چیز کے استعمال میں گزار سکتا ہے جس کی ملکیت کبھی تبدیل نہ ہو۔ اپنی پوری زندگی میں، ہارنیس ان حدود کو عبور کرنے میں وقت گزارتے ہیں جو ملکیت کو بدل دیتے ہیں۔

یہ صرف FFI ریپر سے زیادہ پر لاگو ہوتا ہے۔ کنکشن پولز، حوالہ شماری کیشز، پلگ ان لائف سائیکل، غیر مطابقت پذیر درخواست آبجیکٹ، GPU وسائل، فائل ڈسکرپٹرز، عارضی اسٹیڈیم، اور کال بیک رجسٹریشن سب ایک ہی پروسیسنگ سے فائدہ اٹھا سکتے ہیں۔

اس میں ناکام انجیکشن بھی شامل ہیں۔

صفائی کے کچھ راستوں پر عمل درآمد کرنا مشکل ہوتا ہے کیونکہ عام عملدرآمد شاذ و نادر ہی صحیح مقامات پر ناکام ہوتا ہے۔

اگر کوئی کام ترتیب سے چار وسائل مختص کرتا ہے، تو یہ صرف مکمل کامیابی اور فوری ناکامی کا امتحان لیتا ہے، جس سے بہت سی درمیانی ریاستیں اچھوت رہ ​​جاتی ہیں۔ ایک مفید استعمال آپ کو دوسرے، تیسرے یا چوتھے کام کو ناکام ہونے پر مجبور کرنے کی اجازت دیتا ہے اور پھر دیکھیں کہ کون سے کام باقی ہیں۔

یہ اکثر کیڑے کو ظاہر کرتا ہے جیسے:

  • کلین اپ یہ فرض کرتے ہوئے کہ شروعات مکمل ہو گئی ہے۔

  • وسائل کو دو بار جاری کیا گیا ہے کیونکہ ملکیت پہلے ہی منتقل ہو چکی ہے۔

  • جزوی تعمیر کے بعد ہی اشیاء لیک ہوئیں

  • خرابی کا راستہ جس کی آؤٹ پٹ حالت درست معلوم ہوتی ہے۔

  • کال بیکس یا رجسٹریشنز جو ناکام سیٹ اپ سے بچ جاتی ہیں۔

بہت زیادہ ملکیت والے کوڈ کے لیے، یہ درمیانی ناکامی کی حالتیں اکثر خراب ان پٹ سے زیادہ دلچسپ ہوتی ہیں۔

کنکرنسی پروب: ریس کو کامیاب بنائیں

TSan کے کوریج کے دیگر مسائل ہیں۔ آپ کسی دوڑ کی اطلاع صرف اس لیے نہیں دے سکتے کہ دو کام نظریاتی طور پر ایک دوسرے سے مل سکتے ہیں۔ مشاہدہ شدہ عمل کے دوران متضاد رسائی ہونا ضروری ہے۔

مختصر، حتمی یونٹ ٹیسٹ اکثر ایسا شیڈول بنانے کے لیے ناکافی ہوتے ہیں۔

ہم آہنگی کی تحقیقات جان بوجھ کر امکان کو بڑھاتی ہیں۔ انہیں یکے بعد دیگرے شروع کرنے کے بجائے ایک ہی رکاوٹ پر کارکنوں کو شروع کریں۔ اہم کاموں کو کئی بار دہرائیں۔ کارکنوں کی تعداد میں فرق کریں۔ ہٹانے کے لیے مسابقتی رجسٹریشن، تکمیل کے لیے بند، ختم کرنے کے لیے تخلیق، تباہی کے لیے پوسٹنگ۔ لاگو ہونے پر، صرف ٹیسٹ کی پیداوار یا مختصر ٹائم لائنز ان کھڑکیوں کو وسیع کر سکتی ہیں جو عام طور پر صرف چند ہدایات کے لیے موجود ہوتی ہیں۔

جان بوجھ کر سنسنی خیز مثالیں بنیادی خیال کو نمایاں کرنے میں مدد کر سکتی ہیں۔

#include 
#include 

struct SharedState {
  int plain_counter = 0;
  std::atomic stop{false};
};

void writer(SharedState* s) {
  while (!s->stop.load(std::memory_order_relaxed)) {
    s->plain_counter++;  // Intentionally unsynchronized.
  }
}

void reader(SharedState* s) {
  for (int i = 0; i < 1000000; ++i) {
    (void)s->plain_counter;  // Intentionally unsynchronized.
  }

  s->stop.store(true, std::memory_order_relaxed);
}

int main() {
  SharedState state;

  std::thread t1(writer, &state);
  std::thread t2(reader, &state);

  t1.join();
  t2.join();
}

اس مثال میں بگ کے بارے میں کوئی لطیف بات نہیں ہے۔ مفید حصہ کنٹرول کی شکل ہے. ہم آہنگی کی کارروائیوں کو اتنا دہرایا جاتا ہے کہ متضاد رسائی کے اوورلیپ ہونے کا امکان ہے۔

اصل تحقیقات کو اس منتقلی کو نشانہ بنانا چاہیے جو پہلے سے سسٹم میں موجود ہو۔ اگر آبجیکٹ کے بند ہونے کے دوران کال بیک مکمل ہو سکتا ہے تو اس کام کی دوڑ لگائیں۔ اگر آپ رجسٹری پڑھ رہے ہیں جبکہ دوسرا تھریڈ اندراجات کو ہٹا رہا ہے، تو آپ دونوں اطراف کو خراب کر دیتے ہیں۔ واضح صفائی اور پس منظر کی صفائی کو اوورلیپ کرنے پر مجبور کرتا ہے اگر وہ اسی حالت تک پہنچ سکتے ہیں۔

مقصد ایسا رویہ پیدا کرنا نہیں ہے جو ایک حقیقی پروگرام کبھی پیدا نہیں کر سکتا۔ خیال یہ ہے کہ اتفاقی طور پر قانونی لیکن تکلیف دہ وقفہ دریافت کرنے کے لیے شیڈولر پر انحصار کرنا بند کر دیا جائے۔

بے ترتیب بیج، کام کی ترتیب، کارکنوں کی تعداد، اور شیڈول کے دیگر آدانوں کو ریکارڈ کرنا بھی ضروری ہے۔ ایسی ریسیں جو ایک رات کی دوڑ میں ایک بار دکھائی دیتی ہیں، لیکن مقامی طور پر دوبارہ تعمیر نہیں کی جا سکتی ہیں، ان ریسوں کے مقابلے میں جن کے کام کا بوجھ دوبارہ پیدا کیا جا سکتا ہے، ان کو ٹھیک کرنا زیادہ مشکل ہے۔

نتائج کو ریگریشن ان پٹ کے طور پر سمجھیں۔

دھندلاہٹ اور تناؤ کی جانچ اس وقت زیادہ قیمتی ہوتی ہے جب ان کا آؤٹ پٹ ڈیبگنگ سیشنز میں برقرار رہتا ہے۔

fuzzers کے لیے، اس کا عام طور پر مطلب ہے کارپس میں تصادم یا ان پٹ رساو کو کم سے کم کرنا۔ لائف سائیکل کے استعمال کے لیے، اس کا مطلب یہ ہو سکتا ہے کہ کارروائیوں کی درست ترتیب کو محفوظ رکھا جائے جس کی وجہ سے خرابی ہوئی۔ ہم آہنگی کی جانچ کے لیے، اس کا مطلب ایک بیج، کارکنوں کی تعداد، یا شیڈولنگ پیرامیٹرز کو برقرار رکھنا ہو سکتا ہے جو نسل کو دوبارہ پیدا کرنے کے قابل بناتے ہیں۔

OSS-Fuzz ان پروجیکٹس کے لیے بھی ایک کارآمد ماڈل ہے جو خود سروس کو بالکل استعمال نہیں کرتے ہیں۔ ورک فلو الگ الگ ڈیبگنگ سرگرمیوں کے بجائے ایک ہی سسٹم کے حصے کے طور پر فز اہداف، کارپورا، سینیٹائزر بلڈز، ری پروڈیوسرز، اور ریگریشن ٹیسٹس کو ہینڈل کرتا ہے۔

یہ نقل کرنے کی عادت ہے۔ آپ جو کوڈ چلاتے ہیں اس کے ساتھ فز ٹارگٹ کو برقرار رکھیں، کارپس ان پٹ کے ایک مفید ورژن کی وضاحت کریں، فزنگ انفراسٹرکچر کے باہر غلطیوں کو دوبارہ پیدا کرنے کے قابل بنائیں، اور سینیٹائزر کی تعمیر میں پہلے ناکام ان پٹ کو دوبارہ چلائیں۔

بڑا نکتہ سادہ ہے۔ سینیٹائزر کوریج جزوی طور پر تعمیر کی ایک خاصیت ہے، لیکن یہ کام کے بوجھ کی بھی ایک خاصیت ہے۔ ASan پرانے اشارے نہیں پکڑ سکتا جن کا کوئی بھی حوالہ نہیں دیتا۔ MSan جزوی طور پر ابتدائی حالت کو ظاہر نہیں کر سکتا جس تک ٹیسٹ نہیں پہنچے ہیں۔ TSan انٹرلیونگ کی اطلاع نہیں دے سکتا جو واقع نہیں ہوتا ہے۔

اچھا انسٹرومینٹیشن آپ کو بتاتا ہے کہ پھانسی کب غلط ہو جاتی ہے۔ کام کے بوجھ کا اچھا ڈیزائن اس بات کو یقینی بناتا ہے کہ عمل آوری اتنی کثرت سے ہوتی ہے کہ دیکھنے کے قابل ہو۔

سینیٹائزر رپورٹس کو کیسے پڑھیں اور ان کی درجہ بندی کریں۔

جراثیم کش رپورٹ ثبوت ہے، تشخیص نہیں۔

سب سے اوپر والا فریم آپ کو بتاتا ہے کہ رن ٹائم کو آخر کہاں پتہ چلتا ہے کہ کچھ غلط ہے۔ یہ پڑھنا شروع کرنے کی جگہ ہو سکتی ہے، لیکن یہ اکثر وہ جگہ نہیں ہے جہاں سے بگ شروع ہوتا ہے۔ ایک کارآمد ٹریج سیشن رپورٹ کے ذریعے پیچھے کی طرف کام کرتا ہے جب تک کہ ناکام زندگی بھر، دوبارہ ترتیب، یا مطابقت پذیری کا مفروضہ واضح نہ ہو جائے۔

سب سے پہلے، اس بات کو یقینی بنائیں کہ رپورٹ قابل اعتماد ہے۔

کچے پتوں سے بھرے اسٹیک پر استدلال کی کوئی قدر نہیں۔

اپنے کوڈ کو تبدیل کرنے سے پہلے، یہ یقینی بنائیں کہ ناکام ہونے والی بائنری میں مفید ڈیبگ معلومات موجود ہیں، کہ علامتیں صحیح تعمیر سے تعلق رکھتی ہیں، اور یہ کہ دلچسپی کا ماڈیول درحقیقت تیار کیا گیا ہے۔ CI کا استعمال آپ کے خیال سے کہیں زیادہ غلطیوں کا شکار ہے۔ ایک پرانا علامت بنڈل، ایک دوبارہ تعمیر شدہ بائنری، یا کسی اور کام سے نقل کی گئی رپورٹ بالکل قابل فہم لیکن بیکار اسٹیک پیدا کر سکتی ہے۔

کلینگ سینیٹائزر بنانے کے لیے: -g اور -fno-omit-frame-pointer یہ ایک معقول بنیاد ہے۔ llvm-symbolizer جب ٹیسٹ چلتا ہے تو یہ دستیاب ہوتا ہے۔ اگر آپٹمائزیشن اسٹیک کو دوبارہ ترتیب دینا مشکل بناتی ہے، تو ایک اعتدال پسند سطح کا استعمال کریں اور -fno-optimize-sibling-calls اس سے مدد مل سکتی ہے۔

بالکل حذف شدہ بائنریز اور ان کی علامتیں رپورٹ کے ساتھ رکھیں۔ سینیٹائزر کے اختیارات، دبانے والی فائلوں، ری پروڈیوسرز، اور اس رن کو دوبارہ پیش کرنے کے لیے درکار کسی بھی چیز کے لیے بھی یہی ہے۔

ایک غیر علامتی ہیکساڈیسیمل پتہ کم شدت کا بیج نہیں ہے۔ مشاہدے کی کمی ہے۔

یہ دیکھنے کے لیے رپورٹ پڑھیں کہ ٹول آپ پر اصل میں کیا الزام لگاتا ہے۔

یہ ASan، LSan، MSan، TSan، اور Valgrind کے نتائج کو ایک بالٹی میں ڈالنے کے لیے پرکشش ہے: "میموری بگز۔” یہ عام طور پر غلط سمت میں ڈیبگنگ کی طرف جاتا ہے۔

آسان استعمال کے بعد مفت بنیادی طور پر زندگی بھر کا سوال ہے۔ پروگرام کے ایک حصے کو کیوں یقین تھا کہ کسی چیز کو دوسرے حصے کے ختم ہونے کے بعد بھی استعمال کیا جا سکتا ہے؟

Lsan رپورٹ کچھ اور پوچھتی ہے۔ چونکہ الاٹمنٹ تحلیل ہونے تک رکھی گئی تھی، اس لیے کس مالک کو اسے جاری کرنا چاہیے، اور ملکیت کو ختم ہونے سے کیا روکتا ہے؟

MSan کے لیے، دلچسپی کا سوال عام طور پر یہ نہیں ہے کہ "یہ متغیر غیر صفر کیوں ہے؟” یہ وہ جگہ ہے جہاں پروگرام اس قدر کو ابتدائی قیمت کے طور پر ماننے کی اجازت حاصل کرتا ہے۔ اکثر جواب ایک آؤٹ پٹ پیرامیٹر، جزوی طور پر تعمیر شدہ آبجیکٹ، یا کامیابی کے راستے کی طرف لے جاتا ہے جس کی پوسٹ کنڈیشنز کال کرنے والے کے فرض کیے گئے حالات سے کمزور ہوتی ہیں۔

TSan رپورٹس آرڈرز کے بارے میں ہیں۔ دو متضاد رسائییں بغیر کسی مطابقت پذیری کے واقع ہوئیں جو رن ٹائم قائم کر سکتا ہے۔ ڈیبگنگ کا کام ان کناروں کو تلاش کرنا ہے جن کو آرڈر کرنے کی ضرورت ہے اور اس بات کا تعین کرنا ہے کہ آیا وہ غائب ہیں یا صرف آلات کی حدود کے پیچھے چھپے ہوئے ہیں۔

Valgrind بری پڑھنے اور لکھنے کے لیے قدرے زیادہ درجہ بندی کی ضرورت ہوتی ہے کیونکہ وہ کئی مسائل کی طرف اشارہ کر سکتے ہیں جیسے کہ باسی ملکیت، حدود کی غلطیاں، مختص کرنے والے کا غلط استعمال، یا ارد گرد کے رن ٹائم کی وجہ سے پیچیدہ رویہ۔

فرق اہم ہے کیونکہ مقامی تبدیلیاں معاہدے کی مرمت کیے بغیر علامات کو آسانی سے چھپا سکتی ہیں۔ MSan کے رپورٹ کردہ بفر کو 0 پر شروع کرنا مبہم APIs کو برقرار رکھتے ہوئے زہریلے پن کو ختم کر سکتا ہے۔ TSan ریس میں تاخیر کو شامل کرنے سے ایک ٹیسٹ بالکل بھی ہم آہنگی کو متعارف کرائے بغیر پاس ہو جاتا ہے۔

اسٹیک کو ٹائم لائن کی طرح سمجھیں۔

استعمال کے بعد مفت میں، موجودہ کنکشن کہانی میں صرف ایک واقعہ ہے۔

ایلوکیشن اسٹیک آپ کو بتاتا ہے کہ کسی شے کی زندگی کہاں سے شروع ہوئی۔ مفت اسٹیک آپ کو بتاتا ہے کہ کسی نے کہاں فیصلہ کیا ہے کہ زندگی ختم ہوگئی ہے۔ موجودہ اسٹیک آپ کو بتاتا ہے کہ کس نے ابھی تک اتفاق نہیں کیا ہے۔

یہ تضادات عام طور پر رپورٹ کے اوپری حصے کی لائن سے زیادہ مفید ہوتے ہیں۔

یہی خیال دیگر جراثیم کش ادویات پر بھی لاگو ہوتا ہے۔ MSan استعمال کے اسٹیک کو یہ بتانے کی اجازت دیتا ہے کہ ایک غیر شروع شدہ قدر آخر اہم کہاں ہے، جب کہ اصل کا سراغ اس بات کی نشاندہی کر سکتا ہے کہ ایک درست ابتدائی ریکارڈ کے بغیر پروگرام میں پہلی بار کہاں داخل کی گئی تھی۔ TSan کے ساتھ، متضاد رسائی خود اور اپنے آپ میں بے معنی ہیں۔ دھاگوں کی تخلیق، اشاعت، تالا لگانا، ایٹمی صلاحیت اور دیگر ہم آہنگی کے واقعات اسی کہانی کا حصہ ہیں۔

ذہنی طور پر رپورٹ کو کم کرنے میں اکثر مددگار ثابت ہوتا ہے:

object created
    -> ownership transferred
    -> old owner still retains access
    -> new owner destroys object
    -> old owner dereferences stale handle

یا ابتدائی کیڑے کے لیے:

output allocated
    -> rare branch skips initialization
    -> function still reports success
    -> caller consumes output

ایک بار ترتیب ریکارڈ ہونے کے بعد، کریش لائن اکثر بگ کو ٹھیک کرنے کے لیے اچھی جگہ نہیں لگتی ہے۔

بگ پیدا کرنے والے عناصر کو ختم کیے بغیر تولید کو کم سے کم کریں۔

"کم سے کم دوبارہ پیدا کرنے والا” کبھی کبھی بہت لفظی طور پر لیا جاتا ہے۔

سب سے چھوٹا کارآمد پلے بیک پروگرام ضروری نہیں کہ وہ سب سے کم لائنوں والا ہو۔ یہ سب سے چھوٹی چیز ہے جو اب بھی ان حالات کو برقرار رکھتی ہے جس پر بگ انحصار کرتا ہے۔

FFI لائف ٹائم بگز کے لیے، منظم رن ٹائم کو ہٹانے سے فائنلائزر کے رویے کو بھی ہٹایا جا سکتا ہے جو اسے متحرک کرتا ہے۔ پول مختص کرنے والے کو اس سے تبدیل کریں۔ malloc آپ دوبارہ استعمال کے پیٹرن کو ہٹا سکتے ہیں جس کی وجہ سے باسی پوائنٹرز ظاہر ہوتے ہیں۔ ایک دھاگے میں سمورتی جانچ کو آسان بنانا یقینی طور پر پروگرام کو چھوٹا بناتا ہے، لیکن یہ تنازعات کو بھی ختم کرتا ہے۔

یہی دیکھ بھال آپٹمائزیشن لیول، جی سی پریشر، ان پٹ ڈھانچہ، تھریڈز کی تعداد، مختص کنفیگریشن، اور آلات کی حدود پر لاگو ہوتی ہے۔ غیر فعال کوڈ کو فعال طور پر ہٹا دیں، لیکن ایسے میکانزم کو برقرار رکھیں جو ناکامی کو حقیقت بناتے ہیں۔

ایک اچھے ری پروڈکشن پروگرام کو رپورٹ کو کسی دوسرے پروگرام میں منتقل کیے بغیر نکالنا آسان بنانا چاہیے۔

اطلاع شدہ رسائی کے ساتھ ساتھ ملکیت یا مطابقت پذیری کی غلطیوں کو بھی درست کریں۔

سینیٹائزر اکثر اس مقام پر مسائل کو بے نقاب کرتے ہیں جہاں ابتدائی ڈیزائن کے فیصلے بالآخر غیر محفوظ ہوجاتے ہیں۔

ملکیت کی منتقلی کے بعد ریپر کو باطل کرنا اس بات کو یقینی بناتا ہے کہ باسی پوائنٹرز کو درست طریقے سے درست کیا گیا ہے۔ اگر کوئی لیک ہوتا ہے تو، آپ کو ایک ایسی چیز بنانے کی ضرورت پڑسکتی ہے جو منعقد شدہ حوالہ جات کو جاری کرنے کے لیے واضح طور پر ذمہ دار ہو۔ MSan رپورٹس اپنے API کو ہمیشہ کامیابی پر مکمل طور پر ابتدائی نتائج پیدا کرنے کے لیے تبدیل کر سکتی ہیں۔ اگرچہ TSan کے نتائج کو "بذریعہ ڈیفالٹ ایٹم” سمجھا جاتا ہے، لیکن وہ درحقیقت ایسے جھنڈوں کو بے نقاب کر سکتے ہیں جن کے لیے ایک متعین مطابقت پذیری پروٹوکول کی ضرورت ہوتی ہے۔

بعض اوقات درست درستگی دراصل مقامی حدود کی جانچ یا ابتداء کا بیان ہوتا ہے۔ لیکن اس سے پہلے کہ ہم رکنے، ایک اور سوال پوچھنا ضروری ہے۔ سب سے پہلے ایک غلط ریاست کے وجود کی اجازت کس چیز نے دی؟

یہ سوال خاص طور پر FFI اور لائبریری کی حدود میں مفید ہے، جہاں ایک سے زیادہ کال کرنے والے ایک ہی غلطی کو قدرے مختلف شکل میں دہرا سکتے ہیں۔

مسئلہ حل کرنے کے بعد بھی ناکام رہیں

سینیٹائزر کیڑے جو ایک پیچ کے بعد غائب ہو جاتے ہیں لیکن کوئی ریگریشن ٹیسٹنگ نہیں چھوڑتے ہیں انہیں مہینوں بعد آسانی سے دوبارہ دریافت کیا جا سکتا ہے۔

ری پروڈکشن کو جنرل انجینئرنگ ریکارڈ کا حصہ بننا چاہیے۔ مبہم ناکامیوں کا تعلق ریگریشن کارپس سے ہے۔ لائف سائیکل کیڑے انتہائی یونٹ ٹیسٹنگ یا کام کا بوجھ ختم کر سکتے ہیں۔ ایک ریس کے لیے ٹرگر سیڈ، کارکنوں کی تعداد، یا آپریشن کے آرڈر کی ضرورت ہو سکتی ہے جو ٹیسٹ کے ساتھ محفوظ ہیں۔

پھر کام کا بوجھ اسی سینیٹائزر پر دوبارہ چلائیں جس نے مسئلہ دریافت کیا۔

وہ آخری حصہ اہم ہے۔ ASan کو ٹھیک کرنے کے بعد پاس ہونے والے عام یونٹ ٹیسٹ یہ ثابت نہیں کرتے کہ ASan کی غلطیاں دور ہو گئی ہیں۔ انسٹرومینٹیشن رن جس نے اصل میں بگ کو بے نقاب کیا وہ رن ہونا چاہیے جو بگ کو بند کرتا ہے۔

لہذا درجہ بندی کا مقصد صرف رپورٹوں کو غائب کرنا نہیں ہے۔ خیال یہ ہے کہ پھانسی کیوں غلط ہو گئی، اس کے مفروضوں کو درست حدوں سے بازیافت کریں، اور کام کے بوجھ کو چھوڑ دیں کہ اگر وہ واپس آجائے تو اسی غلطی کو پکڑیں۔

CI پالیسی اور منظوری کا معیار

اگر جراثیم کش رپورٹ دوبارہ پیدا کرنے کے قابل اور قابل اعتماد ہے، تو اگلا سوال یہ ہے کہ یہ CI میں کہاں آتا ہے۔

تمام ٹولز کو تمام پل درخواستوں پر لاگو کرنا شاذ و نادر ہی جواب ہوتا ہے۔ ASan، MSan، TSan، لیک کا پتہ لگانے، صاف کرنے اور مکمل پراسیس ٹولز بہت مختلف لاگتیں عائد کرتے ہیں اور میٹرولوجی کی مختلف سطحوں پر انحصار کرتے ہیں۔ ایک مفید CI سیٹ اپ جراثیم کش کو ایک عام "محفوظ” کام کے طور پر علاج کرنے کے بجائے ان اختلافات کی عکاسی کرتا ہے۔

عملی تقسیم مندرجہ ذیل ہے: انضمام کے راستوں کی حفاظت کے لیے فوری چیک کریں۔ اور غلطیوں کا پتہ لگانے کا سست کام جو عام ٹیسٹ سوٹ میں ظاہر ہونے کا امکان نہیں ہے۔.

عام ترقیاتی لوپ کے قریب تعینات کرنے کے لیے ASan اکثر سب سے آسان جراثیم کش ہے۔ اوور ہیڈ قابل توجہ ہے لیکن عام طور پر قابل انتظام ہے، اور رپورٹ کردہ ناکامیاں (مفت، حد سے باہر رسائی کے بعد استعمال کریں، غلط مفت، ڈبل فری) ضم کرنے کی شاذ و نادر ہی کوششیں ہیں۔ مقامی-مرکزی منصوبوں کے لیے، UBSan کے ساتھ مل کر ایک ASan کی تعمیر ایک مناسب پری مرج لین ہے، اگر آپ کا بلڈ اور ٹیسٹ سویٹ اس کی حمایت کر سکتا ہے۔

رساو کا پتہ لگانا قدرے مختلف ہے۔ اگر LSan ASan تعمیر کے حصے کے طور پر چلتا ہے، تو یہ اسی لین میں ختم ہو سکتا ہے۔ آیا تمام لیکس کو فوری طور پر بلاک کرنے کی ضرورت ہے اس کا انحصار اس بات پر ہے کہ رن ٹائم ماحول کتنا صاف ہے۔ فکسڈ بیس ٹیسٹنگ بائنریز جس میں ڈٹرمنسٹک سڑن ہے عام طور پر شروع سے ہی سخت ہو سکتی ہے۔ منظم رن ٹائمز یا بڑے ہوسٹ پروسیسز کو پہلے ایک بیس لائن کی ضرورت پڑ سکتی ہے تاکہ ایپلیکیشن لیک کو رن ٹائم کی باقیات سے الگ کیا جا سکے۔

TSan عام طور پر اہم انضمام کے راستے سے مزید دور واقع ہے۔ رن ٹائم کے اخراجات بہت زیادہ ہیں، اور مفید TSan عمل درآمد کے لیے کام کے بوجھ کی ضرورت ہوتی ہے جو حقیقت میں بامعنی ہم آہنگی پیدا کرتے ہیں۔ ہر کمٹ پر TSan میں یونٹوں کا ایک مختصر سوٹ چلانا مہنگا ہے، لیکن پھر بھی ناقص ریس کوریج فراہم کرتا ہے۔ رات کو پھانسی، پری ریلیز لین، یا انتہائی ہم آہنگی کی تبدیلیوں کے لیے ہدف بنائے گئے کام اکثر زیادہ مفید ثبوت فراہم کرتے ہیں۔

MSan کی دوسری رکاوٹیں ہیں۔ اس کی قدر بڑی حد تک اس بات پر منحصر ہے کہ انحصار گراف کا کتنا حصہ بنایا جا سکتا ہے۔ مستقل MSan ماحول میں آپ کی ایپلیکیشن اور اس کی اہم لائبریریوں کو بنانے کے قابل ہونا ابتدائی کیڑے کو حل کرنے کا ایک بہترین گیٹ وے ہو سکتا ہے۔ اگر آدھا اسٹیک مبہم ہے، تو اسے باقاعدہ PR میٹرکس میں مجبور کرنا اعتماد سے زیادہ الجھن پیدا کر سکتا ہے۔ بہت سے پروجیکٹس کے لیے، MSan باقاعدہ جانچ کے کاموں کے معمول کی مختلف شکلوں کے بجائے ایک وقف شدہ تعمیر بن کر ختم ہوتا ہے۔

Fuzzing کے بھی دو CI کردار ہیں: نئے ان پٹس کے لیے مہنگی تلاشیں مسلسل یا شیڈول کے مطابق چلائی جا سکتی ہیں، لیکن پہلے تلاش کیے گئے ان پٹس کافی سستے ہونے چاہئیں تاکہ اسے زیادہ کثرت سے چلایا جا سکے۔ ایک بار جب متضاد ٹیسٹ کیسز کو کم کر دیا جاتا ہے اور کارپس میں چیک کیا جاتا ہے، تو اس وقت تک انتظار کرنے کی بہت کم وجہ ہوتی ہے جب تک کہ ایک اور مبہم مہم یہ نوٹس نہ دے کہ وہی بگ دوبارہ آ گیا ہے۔

تو عمومی پالیسی یہ ہے:

لین وہ جگہ جہاں آپ عام طور پر گھومتے ہیں۔ کیا ناکام ہونا چاہئے
عام ٹیسٹ تمام تبدیلیاں فنکشنل ٹیسٹ ناکام ہو گیا۔
ASan + UBSan جب عملی ہو تو پہلے سے ضم کریں۔ تمام نتائج قابل اعتماد اور بغیر روک ٹوک
لیک کا پتہ لگانا پہلے سے ضم شدہ یا طے شدہ ملکیتی کوڈ کی وجہ سے ڈیٹرمنسٹک لیک
تسان منصوبہ بند، پری ریلیز، یا ٹارگٹڈ آپ کے اپنے انسٹرومینٹیشن کوڈ میں بے لگام ریسنگ
MS۔ وقف شدہ یا طے شدہ تعمیرات قابل اعتماد غیر شروع شدہ ویلیو رپورٹ
دھندلا پن پری انضمام یا بار بار کریشز، ہینگز، یا سینیٹائزر کی خرابیوں کو دوبارہ پیش کرنے کے لیے محفوظ کردہ ان پٹ
مکمل صفائی طے شدہ یا جاری نئی دریافتیں عام ٹیسٹ کی ناکامیوں کے بجائے درجہ بندی کے نمونے بن جاتی ہیں۔
والگرینڈ / دیگر متبادل تجزیہ اگر کمپائلر سینیٹائزر ابھی تک نہیں چل سکتا ہے۔ پراجیکٹ کے ذریعے منتخب کردہ اعلیٰ اعتماد کی غلط رسائی اور لیک زمرے

عین مطابق شیڈول کیوں سے کم اہم ہے۔ 5 منٹ کی ASan جاب جو حقیقی دنیا کے رجعتوں کو حاصل کرتی ہے، 2 گھنٹے کے TSan کام کے بوجھ کے مقابلے میں ایک ڈویلپر کے زیادہ قریب ہے۔ رات کے وقت MSan کی تعمیرات آدھے آلات والے انحصار کے لیے غیر معتبر PR مخصوص کاموں سے زیادہ قیمتی ہو سکتی ہیں۔

CI کے اخراجات کو ثبوت کے معیار کی پیروی کرنی چاہئے، نہ کہ صرف میٹرکس کو جامع نظر آئے۔

ریڈ لین کا کیا مطلب ہے اس کا تعین کریں۔

سینیٹائزر کے کام پر صرف اس لیے سرخ نشان نہیں لگایا جانا چاہیے کہ اس آلے نے کچھ غیر معمولی پرنٹ کیا ہے۔ اسے سرخ ہونا چاہیے کیونکہ پروجیکٹ نے فیصلہ کیا ہے کہ ایک خاص قسم کے شواہد اس نقص کی نمائندگی کرتے ہیں جسے وہ قبول نہیں کرنا چاہتا۔

آسن کے لیے، معیار عام طور پر آسان ہیں۔ اگر آپ کے اپنے کوڈ میں دوبارہ پیدا کرنے کے قابل غیر دبانے والی میموری کی حفاظت کی خلاف ورزی ہوتی ہے تو آپ کی تعمیر کو ناکام ہونا چاہئے۔

MSan کو اسی طرح ہینڈل کیا جا سکتا ہے جب آلات کا ماحول کافی پختہ ہو جائے تاکہ رپورٹس پر بھروسہ کیا جا سکے۔ ایک غیر شروع شدہ قدر جو عملدرآمد کو متاثر کرتی ہے وہ ایسی چیز نہیں ہے جسے پاس کیا جا سکے کیونکہ ٹیسٹ کامیابی سے مکمل ہو گیا ہے۔

TSan کو آلات کی حدود کے بارے میں کچھ اور سیاق و سباق کی ضرورت ہے، لیکن ایک بار رپورٹ کی تصدیق ہو جانے کے بعد، مالکانہ کوڈ میں رسائی کے درمیان تنازعات کو عام طور پر روکا جانا چاہیے۔ "یہ صرف TSan میں ہوتا ہے” ایک مفید قبولیت کا معیار نہیں ہے۔

رساو کی پالیسیوں میں سب سے زیادہ فیصلے کی ضرورت ہوتی ہے۔ ایک متعین براہ راست لیک جو فوکسڈ مقامی ٹیسٹ میں ہوتا ہے پورے منظم رن ٹائم کے شٹ ڈاؤن کے دوران رپورٹ ہونے والے لیک کے امکان سے بہت مختلف ہوتا ہے۔ کہ webcrypto.dart کیس اسٹڈیز مفید مثالیں ہیں۔ آپ واضح Valgrind لیکس کو بلاک کر سکتے ہیں اور پھر بھی ممکنہ لیکس کو جھنڈا لگاتے ہوئے اس وقت تک روک سکتے ہیں جب تک کہ انہیں زیادہ واضح طور پر منسوب نہ کیا جائے۔

یہ انتہاؤں سے بہتر نمونہ ہے۔ ہر لیک رپورٹ کو نظر انداز کرنا ملکیت کے مفید ثبوت کو ضائع کرتا ہے۔ پہلے دن سے، تمام مبہم اسائنمنٹس میں ناکامی کے نتیجے میں لین ناقابل استعمال ہو سکتی ہے۔

دریافت کو رجعت سے الگ رکھیں

پیشوں کے درمیان مفید امتیازات بھی ہیں۔ نئے کیڑے تلاش کر رہے ہیں۔ اور وہ ایک یقینی بنائیں کہ پرانے کیڑے واپس نہیں ہوئے ہیں۔.

فزر، جو کئی گھنٹوں تک چلتا ہے، تلاش کرتا ہے. ذخیرہ شدہ فز ان پٹ چند ملی سیکنڈ کے اندر دوبارہ چلایا جاتا ہے ایک ریگریشن ٹیسٹ ہے۔

لاکھوں کاموں کو چلانے والے TSan کے لیے ایک دباؤ کا کام تلاش ہے۔ پچھلے مہینے کی ترمیم شدہ ریس کا ایک چھوٹا سا ری پلے ایک ریگریشن ٹیسٹ ہے۔

دریافت ایک بڑے پیمانے پر جداگانہ کام کا بوجھ ہے جو نئے لیکس کو تلاش کرتا ہے۔ ایک 10 لائن مددگار بائنری جو پہلے سے طے شدہ ملکیت لیک کو دوبارہ پیش کرتی ہے ایک رجعت ٹیسٹ ہے۔

دوسری قسم کے لیے عام طور پر انضمام کے راستے کے قریب جانے کی ضرورت ہوتی ہے۔ جب ایک مشکل ناکامی کو سستی اور نازک چیز تک کم کر دیا جاتا ہے، تو اپنے آپ کو اس مہنگے کام میں بند کرنے کی کوئی اہمیت نہیں ہے جس میں آپ نے خود کو اصل میں پایا تھا۔

یہ ایک طریقہ ہے کہ جراثیم کش کوریج وقت کے ساتھ سستی ہو جاتی ہے۔ مہنگی دریافت کا نتیجہ چھوٹے ریگریشن ٹیسٹوں میں ہوتا ہے۔

ناکامیوں کو ڈیبگ کرنے کے لیے کافی سیاق و سباق کو محفوظ کریں۔

اگر سینیٹائزر لین ناکام ہو جاتی ہے، تو CI کو سرخ یا اس سے زیادہ درجہ چھوڑ دینا چاہیے۔

کارآمد نمونے وہ ہیں جو ایک ہی عمل کو دوبارہ تشکیل دینے کے لیے درکار ہیں۔ یعنی حذف شدہ بائنریز، مماثل علامتیں، خام رپورٹس، حذف کرنے کے اختیارات، دبی ہوئی فائلیں، اور کوئی بھی ان پٹ، سیڈ، یا کام کا بوجھ پیرامیٹر جو خرابی کا سبب بنے۔

فزنگ آپریشن کو متضاد ان پٹ کو برقرار رکھنا چاہیے۔ کنکرنسی ورک بوجھ کو لازمی طور پر ایک بیج یا کام کی ترتیب کو برقرار رکھنا چاہیے، اگر کوئی موجود ہو۔ ٹول چین کے لیے مخصوص تعمیرات کو کمپائلر اور سینیٹائزر کے رن ٹائم ورژن کو ریکارڈ کرنا چاہیے جنہوں نے رپورٹ تیار کی۔

اسے GitHub ایکشنز، GitLab CI، Buildkite، Jenkins، یا کسی دوسرے رنر سے منسلک ہونے کی ضرورت نہیں ہے۔ نفاذ کا نحو بدل جاتا ہے، لیکن تقاضے نہیں بدلتے۔ ڈیولپرز جو کل ناکامی کا اندازہ لگاتے ہیں انہیں CI سسٹم کو ریورس انجینئر کیے بغیر اسی انسٹرومینٹیشن کے عمل کو دوبارہ پیش کرنے کے قابل ہونا چاہیے۔

اپنی پالیسی لکھیں۔

اس بات کا تعین کرنے کا سب سے برا وقت کہ آیا سینیٹائزر کا نتیجہ ریلیز بلاک ہو رہا ہے جب ریلیز کا انتظار ہو رہا ہو۔

آپ کے پروجیکٹ میں ہر لین کے لیے قوانین کا ایک چھوٹا، واضح سیٹ ہونا چاہیے۔ یعنی، کیا مشاہدہ کیا جائے گا، کیا نتائج ناکام ہوں گے، کون سے زمرے معلوماتی ہیں، کس قسم کی روک تھام کی اجازت ہے، وغیرہ۔

یہ اصول تیار ہو سکتے ہیں۔ جب آپ بیس لائن کو سمجھتے ہیں، تو آپ نئے لیک کے راستے شروع کرنے کے لیے رپورٹس اکٹھا کر سکتے ہیں، اور پھر شور ہٹانے کے بعد تعییناتی لیکس کو روک سکتے ہیں۔ TSan ملازمتیں راتوں رات شروع کی جا سکتی ہیں اور بعد میں کام کے بوجھ میں تیزی آنے کے بعد منتخب کردہ پل کی درخواستوں پر منتقل ہو سکتی ہیں۔ MSan ماحول پیمانہ ہو سکتا ہے کیونکہ زیادہ انحصار آلات کے لیے دستیاب ہو جاتا ہے۔

اہم بات یہ ہے کہ گرین لین کا ایک مستحکم معنی ہے۔

"آسن پاس” کا مطلب ہے "CI کمانڈ 0 کے ساتھ باہر نکل گئی” سے زیادہ۔ اس کا مطلب یہ ہونا چاہئے کہ متوقع کوڈ کو تیار کیا گیا تھا، مطلوبہ کام کا بوجھ مکمل کیا گیا تھا، رپورٹیں علامتی تھیں، اور پروجیکٹ کے زمروں کو روکنے میں کوئی نتیجہ نہیں نکلا۔

یہ جراثیم کش ادویات کے لیے ہماری CI پالیسی کا بنیادی حصہ ہے۔ یہ میٹرکس میں ٹولز کی تعداد کو زیادہ سے زیادہ کرنے کے بارے میں نہیں ہے، یہ اس بات کو یقینی بنانے کے بارے میں ہے کہ ہر سبز نتیجہ حقیقت میں کچھ کہتا ہے جس پر آپ بھروسہ کر سکتے ہیں۔

پیداوار کی حکمت عملی، قرض پر قابو پانے اور اشارے

زیادہ تر سینیٹائزر تعمیرات وسیع پیمانے پر پیداواری استعمال کے بجائے جانچ کے لیے بنائے گئے ہیں۔ رن ٹائم لاگت، میموری فوٹ پرنٹ، اور آلات کے تقاضے اسے بہت سے لائیو کام کے بوجھ کے لیے غیر موزوں بناتے ہیں۔

فنگسائڈ پروگراموں کے لیے پیداوار اہم ہے۔ یہ آپ کو بتاتا ہے کہ کون سے کام کا بوجھ اہم ہے، پری پروڈکشن میں کون سی غلطیاں ہوئیں، اور جہاں آپ کی پیمائش کی لینیں بہت تنگ ہیں۔ ایک مفید کنکشن ایک فیڈ بیک لوپ ہے۔ پیداوار میں، جانچ میں چھوٹ جانے والا کوئی بھی رویہ بے نقاب ہو جاتا ہے اور وہ رویہ حذف کرنے کا نیا کام کا بوجھ، ریپرو، یا ریگریشن ٹیسٹ بن جاتا ہے۔

اپنی نئی لین کو مکمل ہونے سے پہلے آن لائن لائیں۔

نئی جراثیم کش نوکریاں جب پہلی بار چلائی جاتی ہیں تو شاذ و نادر ہی صاف ہوتی ہیں۔

آپ کے موجودہ کوڈبیس میں پہلے سے ہی حقیقی نقائص، فریق ثالث کی رپورٹس، رن ٹائم باقیات، گمشدہ علامتیں، نامکمل انسٹرومینٹیشن، یا پچھلے کام سے وراثت میں ملنے والی دباو پر مشتمل ہوسکتا ہے۔ اگر آپ فوری طور پر تمام نتائج کو مسدود کر دیتے ہیں، تو آپ کی ٹیم مستقل طور پر منقطع ہو جائے گی اور اسے اس بات کا واضح اندازہ نہیں ہو گا کہ کون سے نتائج پر کارروائی کرنے کے قابل ہے۔

اصل رول آؤٹ رپورٹس جمع کرنے اور بیس لائنز سیکھنے سے شروع ہوتا ہے۔ اپنے ہی کوڈ میں تعییناتی کیڑے درست کریں۔ ان نتائج کو انحصار کے شور اور آلات کے فرق سے الگ کریں۔ دلچسپ ناکامیوں کو دوبارہ پیدا کرنے کے قابل بناتا ہے۔ ایک بار جب کسی زمرے کو نئی رپورٹ کے واضح معنی کے لیے کافی سمجھ لیا جائے تو اسے بلاک کیا جا سکتا ہے۔

لین کو اسی سمت چلنا جاری رکھنا چاہیے۔ صرف مشاہدے کے آپریشنز جو مشاہدات کو برقرار رکھتے ہیں غیر معینہ مدت تک ڈیٹا اکٹھا کرتے ہیں لیکن اکثر انجینئرنگ کنٹرول کے طور پر استعمال نہیں ہوتے ہیں۔

لین شامل کرنے سے پہلے بالکل صاف بیس لائن کا انتظار کرنا دیگر مسائل کا سبب بنتا ہے۔ تنظیمی کام اکثر ہوتا ہے کیونکہ نتائج نظر آتے ہیں اور دہرائے جا سکتے ہیں۔ CI سے کسی کام کو چھوڑ کر جب تک کہ سب کچھ پہلے سے طے نہ ہو جائے اس کے نتیجے میں وہ کام غیر معینہ مدت کے لیے ملتوی ہو سکتا ہے۔

جبر کو عارضی محسوس کرنا چاہیے۔

کچھ جبر ناگزیر ہے۔ فریق ثالث کی لائبریریوں میں ایسی دوڑیں ہوسکتی ہیں جنہیں باکس سے باہر نہیں نکالا جاسکتا۔ رن ٹائم کسی مختص کو اس وقت تک فعال رکھ سکتا ہے جب تک کہ یہ ختم نہ ہو جائے۔ پیمائش کی حدود ایسی رپورٹیں تیار کر سکتی ہیں جن کی ابھی تک واضح طور پر شناخت نہیں کی جا سکتی ہے۔

مسئلہ اس وقت شروع ہوتا ہے جب دبانے والی فائل ایک ایسی جگہ بن جاتی ہے جہاں تکلیف دہ نتائج غائب ہوجاتے ہیں۔

ایک کارآمد روک تھام کو اگلے شخص کو یہ سمجھنے کے لیے کافی بتانا چاہیے کہ یہ کیوں موجود ہے: کون سی رپورٹ چھپی ہے، یہ کہاں سے آئی ہے، اب اس میں ترمیم کیوں نہیں کی جا سکتی، پیروی کرنے کا ذمہ دار کون ہے، اور کام کو ٹریک کرنے میں کیا مسئلہ ہے۔

میچوں کی حد ممکن حد تک تنگ ہونی چاہیے۔ ایک پوری لائبریری یا نام کی جگہ کو دبانا آج کے دور میں معلوم مسائل کو خاموش کر سکتا ہے، ساتھ ہی بعد میں متعارف کرائے گئے غیر متعلقہ رجعت کے ساتھ۔

عمر اکثر خام نمبروں سے زیادہ معلومات فراہم کرتی ہے۔ فعال اپ اسٹریم کیڑے سے متعلق آخری 5 دبانے کے قابل انتظام ہوسکتے ہیں۔ پانچ جبر جن کا تین سالوں میں کسی نے جائزہ نہیں لیا پروگرام کی مختلف ریاستوں کو بیان کرتے ہیں۔

ایک بار جب بنیادی خرابی طے ہو جاتی ہے، اسی تبدیلی سے دباو ہٹا دیا جاتا ہے۔ اس کو چھوڑنے سے سینیٹائزر کو کوڈ کے لیے کم قابل توجہ بنا دے گا جسے اب مستثنیات کی ضرورت نہیں ہے۔

دبانے کے بارے میں سوچنا مفید ہے: مشاہداتی قرض. ہر ایک درست ہو سکتا ہے، لیکن ہر ایک اس بات کو بھی کمزور کرتا ہے کہ ان کی صاف عملداری ایمانداری سے کیا کہہ سکتی ہے۔ ان کی گنتی کریں، ان کی عمر کا پتہ لگائیں، اور کسی بھی استثناء کو دکھائی دیں جو بھولنے کے قابل نہیں ہیں۔

بعد میں ناکامیوں کا محاسبہ کرنے کے لیے تعمیر کو کافی دیر تک رکھیں۔

سمبلائزیشن صرف CI میں مقامی ڈیبگنگ تفصیل کی طرح محسوس ہوتی ہے جب تک کہ سینیٹائزر ناکام نہ ہو جائے۔

اس مقام پر، رپورٹ صرف اس صورت میں کارآمد ہے جب اس کے ایڈریس کو رپورٹ کو تیار کرنے والے عین مطابق بائنری سے منسلک کیا جائے۔ ایک ہی عہد سے دوبارہ تعمیر کرنا ہمیشہ ایک جیسا نہیں ہوتا ہے۔ اصلاح، لنکر فیصلے، تیار کردہ کوڈ، اور ٹول چین ورژن سبھی ترتیب کو تبدیل کر سکتے ہیں۔

رکھنے کے قابل سینیٹائزر کاموں کے لیے، خرابی کو دوبارہ تشکیل دینے کے لیے درکار نمونے رکھیں: انسٹرومینٹڈ بائنریز، مماثل ڈیبگ انفارمیشن، خام سینیٹائزر آؤٹ پٹ، متعلقہ رن ٹائم آپشنز، اور رپورٹ کو متحرک کرنے والا ان پٹ یا کام کا بوجھ۔ بلڈ ID اور کمپائلر/رن ٹائم ورژن اس وقت کارآمد ہوتے ہیں جب آپ کی پائپ لائن ایک ہی پروگرام کی متعدد قسمیں تیار کرتی ہے۔

منظم رن ٹائمز، JIT، AOT کمپائلرز، اور پلگ ان سسٹمز کو اضافی دیکھ بھال کی ضرورت ہوتی ہے کیونکہ ان کے بیس ایڈریسز براہ راست باقاعدہ سورس فائلوں سے نقشہ نہیں بن سکتے۔

ڈارٹ اے او ٹی کے مسئلے پر تبادلہ خیال کیا گیا تھا: webcrypto.dart کیس اسٹڈیز ایک اچھی مثال ہیں۔ مقامی ٹولز غلط عمل درآمد کا مشاہدہ کرنے میں آپ کی مدد کر سکتے ہیں، لیکن اگر رن ٹائم لے آؤٹ مفید ڈارٹ علامتوں کو اسٹیک پر ظاہر ہونے سے روکتا ہے، تو رپورٹ کی زیادہ تر حقیقی قدر ضائع ہو جاتی ہے۔

سینیٹائزر کی رپورٹ صرف اتنی ہی کارآمد ہے جتنی اس کوڈ سے جوڑنے کی صلاحیت جس نے اسے بنایا ہے۔ علامتی تحفظ کا تعلق ترتیبات کی تعمیر اور ریلیز سے ہے، نہ کہ ڈویلپر کی مقامی ڈیبگنگ ٹرکس سے۔

فیڈ کی پیداوار کے نتائج سینیٹائزر کے کام کے بوجھ پر واپس آتے ہیں۔

کلین سینیٹائزر میٹرکس میں اب بھی صرف ٹیسٹ کے ماحول میں پیدا ہونے والی پھانسیوں پر مشتمل ہے۔

پروڈکشن میں، ہم مختلف آبجیکٹ لائف ٹائم، درخواست مکس، ایلوکیٹر پریشر، مشین کا سائز، تھریڈ شیڈولنگ، اور طویل عرصے تک چلنے والا رویہ دیکھتے ہیں۔ اگر آپ کا پلیٹ فارم ان کو سپورٹ کرتا ہے تو پروٹیکٹڈ ایلوکیٹر، ہارڈ ویئر کی مدد سے میموری ٹیگنگ، سیمپلنگ، کینری ڈیپلائمنٹس، اور زیادہ کریش ٹیلی میٹری CI میں نظر نہ آنے والی غلطیوں کو بے نقاب کر سکتی ہے۔

یہ میکانزم مختلف قسم کے ثبوت فراہم کرتے ہیں۔ کچھ غیر نتیجہ خیز، نمونے دار، یا پلیٹ فارم کے لیے مخصوص ہیں۔ ان کی قدر یہ ہے کہ وہ جراثیم کش لیبارٹریوں کو ان رنز کا مشاہدہ کرنے کی اجازت دیتے ہیں جو وہ خود پیدا نہیں کر سکتے اور ان نتائج کو دوبارہ ٹیسٹ سسٹم میں فیڈ کرتے ہیں۔

اگر آپ کے موجودہ تناؤ کے ٹیسٹ پروڈکشن کریشز کی وجہ سے ختم نہیں ہوتے ہیں تو اس لائف سائیکل کو ASan ورک بوجھ میں منتقل کریں۔ اگر ٹیلی میٹری کسی مخصوص ناکامی کے راستے کے بعد میموری کی ترقی کو ظاہر کرتی ہے، تو ایک فوکسڈ سڑن کیس بنائیں اور اسے لیک کی نشاندہی کے تحت چلائیں۔ اگر ہم آہنگی کی ناکامیاں صرف زیادہ بوجھ کے تحت ظاہر ہوتی ہیں، تو ہم آپریشن کے متعلقہ ترتیب کو محفوظ رکھتے ہیں اور TSan تناؤ کے ٹیسٹ کے ساتھ اس پر حملہ کرتے ہیں۔

یہ فیڈ بیک لوپس پروڈکشن کو سینیٹائزر لیب جیسا بنانے کی کوشش کیے بغیر ہی سینیٹائزر کے کام کے بوجھ کو اصل نظام کے رویے سے منسلک رکھتے ہیں۔

پیمائش کریں کہ کیا لین زیادہ کارآمد ہو رہی ہیں۔

فنگسائڈ پروگرام بڑی تعداد میں پیدا کر سکتے ہیں۔ مفید سوالات تین عملی سوالات کے جوابات دیتے ہیں:

  1. کیا آپ ایک حقیقی بگ کی تلاش میں ہیں؟

  2. کیا آپ اسے دوبارہ پیدا کر سکتے ہیں؟

  3. کیا ایسا کرنے کی قیمت اب بھی معقول ہے؟

میٹرکس کا ایک چھوٹا سیٹ عام طور پر آپ کو ایک بڑے ڈیش بورڈ سے زیادہ بتاتا ہے۔

میٹرک نظام یہ آپ کو کیا بتا سکتا ہے؟
نئی دریافتیں جن پر آپ وقت کے ساتھ اعتماد کر سکتے ہیں۔ چاہے میموری، لائف ٹائم، یا تنازعہ کی رجعتیں اب بھی کوڈ بیس میں داخل ہوں۔
دبانے کی تعداد اور مدت کیا معلوم اندھے دھبے سکڑ رہے ہیں یا خاموشی سے مستقل ہو رہے ہیں؟
تولیدی کامیابی کی شرح کیا ناکامی کا اصل میں انجینئرنگ کے کام میں ترجمہ کیا جا سکتا ہے؟
یہ کام کرنے کے لئے کچھ مفید علامتی ڈھیر لگانے کا وقت ہے۔ کیا ڈیبگنگ انفراسٹرکچر ٹھیک سے کام کر رہا ہے؟
لین فلیک ریٹ چاہے ناکامی کا مطلب "بگ” ہے یا صرف "نوکری کو دوبارہ چلانا”
رن ٹائم اور حساب کے اخراجات آیا لین اب بھی وہیں گرتی ہے جہاں اسے اس وقت چلایا جا رہا ہے۔
ایک محفوظ شدہ fuzz یا کشیدگی کی خرابی کامیابی سے چلائی گئی ہے۔ آیا پچھلی دریافتیں رجعت کی کوریج سے محفوظ ہیں۔

ان نمبروں کو سیاق و سباق کی ضرورت ہے۔

اگر آپ علامت کو ہٹا کر وہاں پہنچ جاتے ہیں تو تیز سینیٹائزر لینز کوئی بہتری نہیں ہیں۔ ایک TSan کام جس میں کوئی فلیکس نہیں ہے وہ صرف کام کا بوجھ چلا رہی ہے جو بہت کم ہم آہنگی پیدا کرتا ہے۔ ایک فز کارپس متاثر کن لائن کوریج کو ظاہر کر سکتا ہے جب کہ لائف سائیکل ٹرانزیشن غائب ہو جائے جہاں اصل میں ملکیت ختم ہو جاتی ہے۔

یہاں تک کہ چھوڑے گئے کیڑے کی تعداد بھی مبہم ہے۔ ہو سکتا ہے کہ آپ کا کوڈ بیس درحقیقت صحت مند ہو رہا ہو، یا ہو سکتا ہے کہ آپ کے کام کے بوجھ نے دلچسپ راستے اختیار کرنا چھوڑ دی ہوں۔

میٹرکس اس وقت کارآمد ہوتے ہیں جب وہ ان معاملات میں فرق کرنے میں مدد کرتے ہیں۔ جب نمبرز خود ہی مقصد بن جاتے ہیں، تو بنیادی شواہد کو خراب کرتے ہوئے ڈیش بورڈ کو بہتر بنانا آسان ہو جاتا ہے۔

پختگی کیسی دکھتی ہے۔

ایک بالغ جراثیم کش پروگرام میں CI میٹرکس ہوگا جہاں نتائج قابل فہم اور مفید ہیں۔ کاموں کی تعداد ثانوی ہے۔

اس لین نے ناکامی کے موڈ کو سمجھا۔ رپورٹ دوبارہ پیش کرنے کے قابل ہے۔ دبانا تنگ اور عارضی ہے۔ پرانے کیڑے سستے ریگریشن ٹیسٹ بن جاتے ہیں۔ مہنگے سرچ آپریشنز کا استعمال ایسی معلومات کو شامل کرنے کے لیے کیا جاتا ہے جو تیز تر آپریشنز نہیں کر سکتے۔ پروڈکشن کا واقعہ نئے کام کے بوجھ کو دوبارہ سازگار ماحول میں فیڈ کرتا ہے۔

وقت گزرنے کے ساتھ، آپ اپنے آپ سے پوچھ سکتے ہیں، "کیا ہم ASan، TSan، MSan چلا رہے ہیں؟” یہ اس سے کم دلچسپ ہے کہ "ہمارے دیکھے بغیر اس نظام سے کون سی غلط سزائیں گزر سکتی ہیں؟”

دوسرا سوال اہم خلا کو بے نقاب کرتا ہے، جیسے کام کے بوجھ کی کمزور کوریج، مبہم انحصار، کمزور علامت، ملکیت کی منتقلی جو ٹیسٹوں میں عمل میں نہیں آتی، یا ہم وقت سازی جو ٹولز میں قابل مشاہدہ نہیں ہے۔

جراثیم کشی کے پروگرام بہتر ہوتے ہیں کیونکہ نابینا دھبے چھوٹے ہو جاتے ہیں، بہتر طور پر سمجھے جاتے ہیں، اور نئے رجعت کو اپنے اندر چھپانا مشکل ہو جاتا ہے۔

اختتامی نقطہ نظر

سینیٹائزر سب سے زیادہ کارآمد ہوتے ہیں جب وہ اس بات کا حصہ بن جاتے ہیں کہ آپ اپنے سسٹم کو کس طرح بناتے اور جانچتے ہیں، بجائے اس کے کہ انہیں حادثے کے بعد آن کیا جائے۔

ASan، LSan، MSan، اور TSan مختلف خرابیوں کا مشاہدہ کرتے ہیں، لیکن ان کی تمام رپورٹیں آپ کو ان سوالوں کے جواب دینے پر مجبور کرتی ہیں جن پر آپ کا پروگرام پہلے سے انحصار کرتا ہے۔

کیا یہ میموری اب بھی قابل رسائی ہے؟ اسے عام کرنے کا ذمہ دار کون ہے؟ کیا یہ قدر اصل میں استعمال ہونے سے پہلے شروع کی گئی تھی؟ آپ نے کس مطابقت پذیری کے ساتھ ان دونوں رسائی کا حکم دیا؟

یہ مفروضے آلات کے ساتھ یا اس کے بغیر موجود ہیں۔ سینیٹائزر ان میں سے کچھ کو رن ٹائم پر قابل مشاہدہ بناتا ہے۔

یہی وجہ ہے کہ مرتب کرنے والے جھنڈے ترتیبات کا ایک چھوٹا حصہ ہیں۔ آپ کو متعلقہ کوڈ کو آلہ بنانے کی ضرورت ہے۔ کام کا بوجھ زندگی بھر کی منتقلی، ناکامی کے راستوں، یا دھاگوں کے انٹرلیونگ کو مارنا چاہیے جہاں مفروضے ٹوٹ سکتے ہیں۔ رپورٹ میں کافی علامتی معلومات ہونی چاہیے تاکہ جو کچھ ہوا اسے دوبارہ ترتیب دیا جا سکے۔

CI کو واضح پالیسیوں کی ضرورت ہے کہ کن نتائج پر بھروسہ کیا جا سکتا ہے، جو ابھی زیر تفتیش ہیں، اور کون سے خلاء جان بوجھ کر لین سے باہر ہیں۔

اس ہینڈ بک میں ملکیت ایک بار بار چلنے والا موضوع ہے۔ کیونکہ بنیادی حدود زندگی بھر کے گھر کو کھونا خاص طور پر آسان بنا سکتی ہیں۔ قرضے، ہولڈز، منتقلی اور انکشافات بک کیپنگ تفصیلات نہیں ہیں۔ یہ فیصلہ کرتا ہے کہ اب بھی وسائل تک کس کی رسائی ہے اور آخر کس نے انہیں تباہ کرنا ہے۔ فائنلائزر، کلین اپ اسکوپس، کسٹم ایلوکیٹر، اور ایف ایف آئی ریپرز مزید ایسی جگہیں شامل کرتے ہیں جہاں پروگرام کے دو حصے مختلف جوابات کے ساتھ ختم ہوسکتے ہیں۔

کہ webcrypto.dart کیس اسٹڈی ٹولنگ سائیڈ پر بھی یہی مسئلہ دکھاتی ہے۔ چونکہ پراجیکٹ کو مطلوبہ سینیٹائزر کا راستہ اپ اسٹریم کو بلاک کر دیا گیا تھا، اس لیے میموری کے معائنے کے راستے پر کام کیا گیا جسے موجودہ بلڈ سسٹم سپورٹ کر سکتا ہے۔ ہم بنیادی زندگی بھر کے کام کے بوجھ کو جانچنا جاری رکھ سکتے ہیں، ہم اعلیٰ اعتماد کے نتائج کو لاگو کرنا جاری رکھ سکتے ہیں، اور جراثیم کش سپورٹ کی کمی کو حل ہونے پر غور کرنے کے بجائے ظاہر ہوتا رہے گا۔

تفصیلات صرف ڈارٹ، بورنگ ایس ایس ایل، بلڈ ہکس اور ویلگرینڈ پر لاگو ہوتی ہیں۔ ایسا نہیں ہے۔ اگر ابتداء اس کوڈ سے جوڑتی ہے جسے آلہ نہیں بنایا جا سکتا، MSan مراعات کھو دیتا ہے۔ جب مبہم انحصار کے اندر مطابقت پذیری ہوتی ہے تو TSan کی تشریح کرنا زیادہ مشکل ہو جاتا ہے۔ ASan منطقی آبجیکٹ کی حدود کو نافذ نہیں کر سکتا جسے کسٹم ایلوکیٹر بے نقاب نہیں کرتا ہے۔

کلین ایگزیکیوشن تب ہی سمجھ میں آتا ہے جب آپ ان حدود کو سمجھتے ہیں۔

یہ بگ کے ملنے کے بعد بھی لاگو ہوتا ہے۔ مفید رپورٹس دوبارہ پیش کی جا سکتی ہیں۔ تولیدی صلاحیت ریگریشن ٹیسٹنگ بن جاتی ہے۔ بار بار چلنے والی ملکیت کی ناکامیاں ایک اور مقامی فکس شامل کرنے کے بجائے API کو تبدیل کرنے کا جواز پیش کر سکتی ہیں۔ ریسنگ، جو صرف اس وقت سامنے آتی ہے جب آپ تناؤ کا شکار ہوں، آپ کو کام کا بوجھ چھوڑ دینا چاہیے جو دوبارہ نقل پیدا کر سکتا ہے۔ جبر اس وقت ختم ہو جانا چاہیے جب اس کی وجہ ختم ہو جائے۔

وقت گزرنے کے ساتھ، جراثیم کش پروگرام کی قدریں بدل جاتی ہیں۔ انفرادی رپورٹس اب بھی اہم ہیں، لیکن بڑا انعام ایک کوڈبیس ہے جس میں کم جگہیں ہیں جہاں زندگی بھر، ابتدا، اور ہم آہنگی کی غلطیاں کسی کا دھیان نہیں جاتی ہیں۔

سبز جراثیم کش لین اس بات کا سرٹیفکیٹ نہیں ہے کہ پروگرام محفوظ ہے۔ یہ اس بات کا ثبوت ہے کہ رن ٹائم معاہدوں کا ایک مخصوص سیٹ پھانسیوں کے ایک مخصوص سیٹ سے بچ گیا۔

اس رن کے بعد ایک مفید سوال وہ ہے جو لین اب بھی نہیں دیکھ سکتی۔

سینیٹائزر ڈیبگ جھنڈا نہیں ہے۔ یہ ان معاہدوں کی ایک قابل عمل جانچ ہے جن پر آپ کا پروگرام پہلے سے انحصار کرتا ہے۔

حوالہ جات اور اضافی وسائل

جراثیم کش دستاویزات اور ڈیزائن

مبہم اور مسلسل جانچ

اونر شپ، ایف ایف آئی اور اینکر کیس اسٹڈیز

عوامی واقعات کا حوالہ مواد

اوپر تک سکرول کریں۔