مرورگرت با ریاضی لو میده روی چه سیستمعاملیای
خلاصهٔ کاملتر
تو بلاگ مهندسی Scrapfly اومده که فینگرپرینتینگ معمولاً دربارهٔ canvas و WebGL و فونت و صداست، ولی یه سیگنال ساکتتر هم هست که تو بیتهای آخر یه عدد زندگی میکنه. کافیه تو کنسول مرورگر یه تابع مثلثاتی رو با ورودی مناسب صدا بزنی تا سه سیستمعامل سه جواب بدن.
Math.tanh(0.8)
// 0.6640367702678491 genuine Linux Chrome (glibc)
// 0.664036770267849 genuine macOS Chrome (libsystem_m)
// 0.6640367702678489 genuine Windows Chrome (UCRT)به گفتهٔ نویسنده، این خروجی یه تقریبه و بیتهای دقیقش به سیستمعاملی بستگی داره که حسابش کرده. مک این تابع رو از کتابخانهٔ ریاضی اپل میگیره و لینوکس از glibc؛ این دوتا روی حدود یکچهارم ورودیها با هم اختلاف دارن، معمولاً به اندازهٔ یک واحد در آخرین رقم. ویندوز هم با هر دو فرق داره و روی این ورودی خاص، هر سه به سه عدد متفاوت میرسن.
ریشهش تو استاندارده: IEEE 754 مشخص میکنه یه double چطور ذخیره بشه، ولی الزام نمیکنه توابعی مثل sin و cos و tanh کاملاً درست گرد بشن. گرد کردن دقیق گرونه، پس هر فروشنده یه libm با ضرایب و جدولهای خودش میسازه و کسری از یه واحد دقت رو با سرعت معامله میکنه. برای یه سیستم تشخیص، حتی ریاضی هم لازم نیست؛ فقط یه جدول مقایسه کافیه.
نکتهٔ مهم اینه که این نشونه تازهست. تا کروم ۱۴۷، موتور V8 خودش این تابع رو با پورتی از fdlibm حساب میکرد و روی همهٔ سیستمعاملها یه جواب میداد، یعنی چیزی لو نمیرفت. یه کامیت تو V8 اون رو با std::tanh عوض کرد که از libm میزبان میخونه و از کروم ۱۴۸ به بعد این نشتی وجود داره.
نویسنده میگه «خب توابع مک رو دوباره پیاده کن» بهسرعت به دیوار میخوره. اول اینکه فقط بخشی از ریاضی نشت میکنه: توابعی مثل exp و pow و atan و همینطور sin و cos از کتابخانههای استاتیکِ خود V8 میان و روی همهٔ سیستمعاملها یکسانن، پس دستکاریشون خودش ناسازگاری میسازه — و همین نامتقارنی قابل بررسیـه.
دوم اینکه ریاضی جاوااسکریپت و ریاضی CSS دو مسیر کد جدان. توابع مثلثاتی CSS با Math.sin کد مشترک ندارن؛ موتور چیدمان زاویه رو به درجه کاهش میده و بعد تابع پلتفرم رو صدا میزنه، پس هر هفت تابع مثلثاتی CSS هم سیستمعامل رو لو میدن. تیم Scrapfly میگه مرحلهٔ کاهش درجه و تبدیل رادیان به درجه رو بیتبهبیت بازتولید کرده، نه فقط خود تابع نهایی رو.
زمانبندی هم خودش یه نشونهست: به گفتهٔ نویسنده اولین نسخهٔ ساخت اونها چند برابر کندتر از حالت بومی اجرا میشد و یه حلقهٔ ساده که نسبت زمان دو تابع رو اندازه بگیره، لوش میداد؛ روشنکردن FMA سختافزاری هم سرعت رو برگردوند و هم خروجی رو بیتبهبیت یکسان نگه داشت.
برای اعتبارسنجی هم هر انتشار روی ۸۷۱ هزار ورودی آزمایش میشه، با یه دستگاه واقعی و یه کروم واقعی روی مک بهعنوان مرجع. جمعبندی مقاله اینه که ریاضی قطعیـه، پرسیدنش ارزونه و جعلش سخت — برای مدافع یه سیگنال قوی و برای اسکرپر یه بدهی؛ البته یادمون باشه که خود Scrapfly مرورگر اسکرپینگ میفروشه.
نکات کلیدی:
- استاندارد IEEE 754 گرد کردن دقیق توابع مثلثاتی رو الزام نمیکنه
- هر سیستمعامل libm خودش رو داره: glibc، libsystem_m، UCRT
- از کروم ۱۴۸، تابع tanh از کتابخانهٔ میزبان میخونه و سیستمعامل رو لو میده
- بقیهٔ توابع Math از کتابخانهٔ داخلی V8 میان، پس دستکاریشون ناسازگاری میسازه
- توابع مثلثاتی CSS مسیر کد جداگانه دارن و اونها هم نشت میکنن
- سرعت اجرا هم قابل اندازهگیریـه؛ بازتولید کند خودش یه نشونهست




